【问题标题】:How to avoid using PHP global objects?如何避免使用 PHP 全局对象?
【发布时间】:2009-07-18 17:27:37
【问题描述】:

我目前正在创建博客系统,我希望将来能将其变成一个完整的 CMS。

有两个类/对象可用于全局访问(mysqli 数据库连接和一个检查用户是否登录的自定义类)。

我正在寻找一种方法来做到这一点,而不使用全局对象,并且如果可能的话,不要在每次调用时将对象传递给每个函数。

【问题讨论】:

    标签: php global


    【解决方案1】:

    您可以将对象设为静态,然后您可以在任何地方访问它们。示例:

    myClass::myFunction();
    

    这将适用于脚本中的任何位置。但是,您可能想阅读静态类,并可能使用 Singleton 类在静态对象内创建可在任何地方使用的常规类。

    扩展

    我认为您尝试做的与我对 DB 类所做的非常相似。

    class myClass
    {
        static $class = false;
        static function get_connection()
        {
            if(self::$class == false)
            {
                self::$class = new myClass;
            }
            return self::$class;
        }
        // Then create regular class functions.
    }
    

    在您获得连接后,使用 $object = myClass::get_connection(),您将能够定期执行任何操作。

    $object = myClass::get_connection();
    $object->runClass();
    

    扩展

    完成静态声明后,您只需调用 get_connection 并将返回值分配给一个变量。然后其余的函数可以具有与您使用 $class= new myClass 调用的类相同的行为(因为这就是我们所做的)。您所做的只是将类变量存储在静态类中。

    class myClass
    {
        static $class = false;
        static function get_connection()
        {
            if(self::$class == false)
            {
                self::$class = new myClass;
            }
            return self::$class;
        }
        // Then create regular class functions.
        public function is_logged_in()
        {
            // This will work
            $this->test = "Hi";
            echo $this->test;
        }
    }
    
    $object = myClass::get_connection();
    $object->is_logged_in();
    

    【讨论】:

    • 是的,对于静态类执行与声明变量 $class 相同的操作。唯一的事情是您“必须”声明您使用的每个变量。
    • 但是,我给你的代码允许你使用任何常规类,嗯,经常。静态部分只是为您提供类,而不是全局化它。我将进行编辑以显示更多内容。
    • 没错!整个 Static 类只是所创建类的容器。
    • 静态类只是另一种类型的全局对象。
    • 您不必每次创建新文件或类时都将其全局化,这是 OP 试图解决的基本问题。
    【解决方案2】:

    您可以将当前的全局对象传递给构造函数。

    <?php
      class Foo {
        protected $m_db;
        function __construct($a_db) {
          $this->m_db = $a_db;
        }
      }
    ?>
    

    【讨论】:

      【解决方案3】:

      我最近修改了我的框架,为我们公司 CMS 的第二个版本做准备。我取消了大量我制作为静态的东西,以便用普通对象替换它们。在这样做的过程中,我创造了巨大的灵活性,过去依赖于我浏览和侵入核心文件。我现在只在唯一的替代方案是全局函数时使用静态构造,这仅与低级核心功能相关。

      我将展示我的 bootstrap.php 文件的几行(我的所有请求都通过该文件发送,但您可以通过将其包含在每个文件的顶部来获得相同的结果)向您展示什么我是说。这是你可能会在你的情况下使用的一个相当大的版本,但希望这个想法是有帮助的。 (这一切都略有修改。)

       //bootstrap.php
      
      ...
      
      // CONSTRUCT APPLICATION
      
      {       
          $Database = new Databases\Mysql(
              Constant::get('DATABASE_HOST'),
              Constant::get('DATABASE_USER'),
              Constant::get('DATABASE_PASSWORD'),
              Constant::get('DATABASE_SCHEMA')
          );
      
          $Registry     = new Collections\Registry;
          $Loader       = new Loaders\Base;
          $Debugger     = new Debuggers\Dummy; // Debuggers\Console to log debugging info to JavaScript console
      
          $Application  = new Applications\Base($Database, $Registry, $Loader, $Debugger);
      }
      
      ...
      

      如您所见,我有各种选项来创建我的应用程序对象,我可以将其作为构造函数中的参数提供给其他对象,以使它们能够访问这些“全局”必需品。

      数据库对象是不言自明的。注册表对象充当我可能想要在应用程序的其他地方访问的对象的容器。加载器用作加载其他资源(如模板文件)的实用程序。并且调试器可以处理调试输出。

      例如,我可以更改我实例化的数据库类,瞧,我已经连接到 SQLite 数据库。我可以更改调试器的类(如前所述),现在我的所有调试信息都将记录到我的 JavaScript 控制台。

      好的,现在回到问题上来。你如何让其他对象访问所有这些?您只需将其作为参数传递给构造函数即可。

      // still bootstrap.php
      
      ...
      
      // DISPATCH APPLICATION
      
      {
          $Router = new Routers\Http($Application);
          $Router->routeUri($_SERVER['REQUEST_URI']); 
      }
      
      ...
      

      不仅如此,我的路由器(或我用它构造的任何对象)也更加灵活。现在我可以以不同的方式实例化我的应用程序对象,我的路由器将相应地表现不同。

      【讨论】:

        【解决方案4】:

        好吧,如果您已经有一些引用博客系统的对象,您可以将这些对象组合到其中,以便它们是 $blog-&gt;db()$blog-&gt;auth() 或其他。

        【讨论】:

        • 可以,但对象也需要在博客类之外访问。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-07
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        • 2019-07-13
        • 2013-04-18
        • 2012-05-04
        相关资源
        最近更新 更多