在PHP中不再需要global关键字


Eliminating the need for the global keyword in PHP

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

拥有一个全局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设计?

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

。有一种东西叫做参数,例如:

function __construct($user)
{ ... }

现在,你可以调用:

$controller = new MyController($user);

. .你不需要'global'。

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

然后,这些数据库可以被设置为控制器的属性。下一个类将知道这个控制器。你可以在全局变量中设置控制器实例,或者更好的是,把它传递给其他类的构造函数,这样它们就完全不依赖全局变量了。

如果那些类不需要控制器,而只需要数据库,你可以只传递数据库类。这将使这些类更加独立于控制器和任何全局变量,所以你可以很容易地在其他应用程序中重用它们,前提是数据库本身也不(直接或间接)依赖于控制器。

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

最后我这样做了:

class BaseController
{
    public $user, $db, $errors;
    function __construct()
    {
         global $user, $db, $errors;
         $this->user = $user;
         $this->db = $db;
         $this->errors = $errors;
    }
}

每个控制器都扩展了BaseController(它也有一些抽象的功能,这只是一个解决这个特定问题的BaseController的例子)。这样我只需要使用一次global,然后我可以在每个控制器上使用user, db和错误处理程序实例,只需在每个控制器的构造函数中调用parent::__construct(),然后通过$this->user引用它们,等等。