PHP中的单例引用和递归


Singleton reference and recursion in PHP

我有一个主引导类(下面示例中的singleton1),它实例化了一些单例类。在那些单例类中,我需要保持对应用程序主类的引用,以便轻松快速地引用它,但这样做会给我一个:

Fatal error: Maximum function nesting level of '100' reached, aborting
下面是示例代码:
<?php
class Singleton1 {
    private static $instance;

    private function __construct() {
        Singleton2::instance();
    }
    public static function instance () {
        if( !self::$instance ) {
            $class = __CLASS__;
            self::$instance = new $class;
        }
        return self::$instance;
    }
    public function test () {
        echo 'Good.';
    }
    private function __clone() { }
    private function __wakeup() { }
}
class Singleton2 {
    private static $instance;
    private $singleton1;
    private function __construct() {
        $this->singleton1 = Singleton1::instance();
    }
    public static function instance () {
        if( !self::$instance ) {
            $class = __CLASS__;
            self::$instance = new $class;
        }
        return self::$instance;
    }
    public function test () {
        $this->singleton1->test();
    }
    private function __clone() { }
    private function __wakeup() { }
}
Singleton1::instance();
Singleton2::instance()->test();

对于这个问题我找不到任何合理的解释。

谢谢。

你的代码有以下循环:

Singleton2::__construct()
Singleton1::instance()
Singleton1::__construct()
Singleton2::instance()
Singleton2::__construct()

您可以从Singleton1构造函数中删除Singleton2::instance()行,以看到"Good"消息

你不应该使用单例。它们是坏实践(tm),因为它们引入了全局状态,这使得您的代码更难测试。

你可以用控制反转重写你的例子:

<?php
// A simple Singleton for the Application
function Application()
{
     static $instance = null;
     if (null === $instance) {
         $instance = new Application;
     }
     return $instance;
}
class Application
{
     protected $someService;
     function __construct()
     {
         $this->someService = new SomeService($this);
     }
     function test()
     {
         echo "Good.";
     }
}
class SomeService
{
     protected $application;
     function __construct(Application $app)
     {
         $this->application = $app;
     }
     function test()
     {
         $this->application->test();
     }
}

Application是你的主应用程序的类,SomeService是你的Singleton2

不需要私有构造函数等,SomeService只被实例化一次,与你的应用程序(认为你只实例化你的应用程序一次)。

对你想要添加到App实例中的其他服务重复此操作。

一些关于这方面的好文章,值得一读:

  1. http://www.potstuck.com/2009/01/08/php-dependency-injection/
  2. http://fabien.potencier.org/article/11/what-is-dependency-injection