消除了PHP中对global关键字的需求

时间:2011-11-23 23:35:38

标签: php model-view-controller global-variables

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

例如,拥有全局User类允许任何控制器通过检查$user->loggedIn(或类似的东西)在$user中实例化index.php来检查用户是否已登录{1}}。

以下是我在代码中描述的内容:

// 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设计的同时,还有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

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

首先。有一些参数,例如:

function __construct($user)
{ ... }

现在,您可以致电:

$controller = new MyController($user);

..而且你不需要'全球'。

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

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

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

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

答案 1 :(得分: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一次,然后我就可以在每个控制器的构造函数中调用parent::__construct()然后通过{引用它们来跨每个控制器使用user,db和错误处理程序实例{1}}等等。