2011-11-23 44 views
0

我正在用MVC设计制作一个简单的PHP应用程序。所有的请求都被发送到index.php,然后路由到适当的控制器。因为所有的请求都经过index.php,所以我想在那里创建一些对象并且能够全局使用它们,而不管哪个控制器处理请求。即,这些对象是User,ErrorHandlerDatabase类型。在PHP中取消对全局关键字的需求

具有全局User类,例如,允许任何控制器检查用户是否通过检查$user->loggedIn(或类似的东西),其中$userindex.php实例登录。

以下是我在代码中我描述:

// index.php: 

<?php 
    include('lib/User.php'); 

    $user = new User(); 

    // other stuff that index.php needs to do, perhaps route to FooController 
?> 

// FooController.php: 

<?php 
    class FooController { 
     function __construct() { 
      global $user;   

      if ($user->loggedIn) { 
       // do whatever 
      } 
     } 
    } 
?> 

这只是随机码我刚刚输入了这么请原谅任何愚蠢的错误 - 但我希望你的想法。此代码将起作用,但global $user;行必须包含在FooController.php内的每个函数中。

这会招人烦的时候每个函数必须有三个global语句,一个用于UserErrorHandlerDatabase。有没有更好的方式去做这件事,同时保留我的MVC设计?

+0

你可以使用几种模式来实现这一点。例如,看看Singleton,Multiton和Registry模式。最后一个可能是您替换全局变量的最佳选择。 – Macmade

+1

为什么不将$ user传递给控制器​​的构造函数? – CodeZombie

+0

FooController类扩展用户{...? –

回答

1

我落得这样做:

class BaseController 
{ 
    public $user, $db, $errors; 

    function __construct() 
    { 
     global $user, $db, $errors; 

     $this->user = $user; 
     $this->db = $db; 
     $this->errors = $errors; 
    } 
} 

每个控制器扩展了BaseController(其中有一些抽象的功能,以及,这仅仅是一个BaseController解决了这一特定问题的例子)。这样,我只需要使用global一次,然后我可以使用用户,db和错误处理跨每个控制器实例通过简单地在每个控制器的构造函数调用parent::__construct()然后$this->user提到他们,等

2

你几乎不需要global。只是不要创建全局变量。

首先。有这样的事情作为参数,例如:

function __construct($user) 
{ ... } 

现在,您可以拨打:

$controller = new MyController($user); 

..和你并不需要 '全球性'。

如果您的控制器是管理整个应用程序流的控制器,那更好。在这种情况下,你只需要将它传递给几个类,例如一个数据库类和一个输入分析器。如果你不关心这个,你可以让控制器自己实例化一个数据库类和解析器。如果您需要支持多种类型的数据库和多种输入,则始终可以重构该部分。

然后,可以将这些数据库设置为控制器的属性。每个下一个班级都会知道这个控制器。您可以将控制器实例设置为全局,或者甚至更好地将其传递给其他类的构造函数,因此它们根本不依赖于全局变量。

如果这些类不需要控制器,但只需要一个数据库,则只能传递数据库类。这将使这些类更加独立于控制器和任何全局变量,因此您可以在其他应用程序中轻松地重用它们,前提是数据库本身不直接或间接地依赖于控制器。

看看像Kohana这样的框架。他们很好地解决了这些问题,尽管总有改进的余地。

+0

您也可以在类public'User;'中设置属性,然后在您的构造函数$ this-> User = $ user'中设置该属性。然后在任何你需要用户类的地方......'$ this-> User'。 – Benjam

+0

是的,这或多或少是我写的。 – GolezTrol

+1

我不想将$ user,$ database和$ errorhandler(或其他)发送给我制作的每个控制器。这是重点......重点不一定是消除全球变数。它更重要的是必须实例化一次变量,并让它们在任何控制器中都可访问,而不必执行其他任何东西(不管是使用'global',检索singleton实例还是传递参数)。 –