【问题标题】:PHP: How can I get spl_autoload to work within a class on the global scope?PHP:如何让 spl_autoload 在全局范围内的类中工作?
【发布时间】:2013-02-22 19:29:02
【问题描述】:

我正在使用 spl_autoload 进行依赖注入。

spl_autoload_register(function ($class)
{
    $cFilePath = _CLASSLIB_ . "/class.$class.php";

    if(file_exists($cFilePath))
    {
        include($cFilePath);
    }
    else
    {
        die("Unable to include the $class class.");
    }
});

这很好用。但是,假设这些是我的课程:

class Test 
{ 
   public function foo() 
   { 
      echo "Here."; 
   } 
}  

class OtherTest 
{ 
   public function bar() 
   { 
      global $Test; 

      $Test->foo(); 
   } 
}  

所以,在我的执行代码中:

<?php
$OT = new OtherTest(); //Dependency Injection works and loads the file.
$OT->bar();
?>

我会收到一个错误,因为 bar() 尝试在测试类中全局化(它没有被实例化,因此从未自动加载)。

除了在每个方法中尝试使用 $Test 全局变量之前检查它是否是一个对象之外,最好的实现方法是什么?

【问题讨论】:

    标签: php class autoload


    【解决方案1】:

    尽可能避免使用全局变量。您在评论中提到了依赖注入:您可以使用 DI 来解决此问题。

    如果 OtherTest 依赖于一个 Test 实例,则该 Test 实例应在构造时提供给 OtherTest,例如

    $T = new OtherTest($Test);
    

    您显然需要修改您的 OtherTest 类以将 Test 的实例作为属性,以及将 Test 作为参数的构造函数,例如:

    class OtherTest 
    {
    
        protected $test = null;
    
        public function __construct(Test $test)
        {
            $this->test = $test;
        }
    
        public function bar()
        {
            return $this->test->foo();
        }
    
    }
    

    然后您可以执行以下操作:

    $test = new Test();
    $otherTest = new OtherTest($test);
    $otherTest->bar();
    

    【讨论】:

    • 谢谢,克里斯!我最终要做的是设置构造函数,这样我就可以用类名和对象的数组作为键/值对重载它,通过 switch 语句运行它并将其分配给类中适当的受保护属性。
    【解决方案2】:

    我认为您对依赖注入的含义感到困惑。类自动加载不是依赖注入。依赖注入是您实际将对象可能具有的依赖注入到对象中以便它可以使用它的地方。因此,接收依赖的对象完全不需要创建它的依赖。

    在这种情况下,实现依赖注入的最佳方法是在 OtherTest 实例化时将 Test 类的依赖注入到 OtherTest 中。所以 Othertest 可能看起来像这样:

    class OtherTest 
    { 
       protected $test_object = NULL;
    
       public function __construct($test_obj) {
          if ($test_obj instanceof Test === false) {
              throw new Exception('I need a Test object');
          } 
          $this->test_obj = $test_obj;
       }
    
       public function bar() 
       { 
          $this->$test_obj->foo(); 
       } 
    }
    

    而要实例化的代码可能如下所示:

    $OT = new OtherTest(new Test()); // both OtherTest and Test would be autoloaded here if not previously loaded.
    

    请注意,引用未声明的变量(在您的示例中为$Test)不会自动加载类,因为变量名本身没有类的上下文。尝试在非对象上调用方法最终会出错。

    【讨论】:

      猜你喜欢
      • 2014-11-22
      • 1970-01-01
      • 2019-08-27
      • 2012-01-19
      • 2019-01-26
      • 2019-01-25
      • 1970-01-01
      • 2015-11-24
      • 2011-09-26
      相关资源
      最近更新 更多