Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中的单例引用和递归_Php_Recursion_Singleton_Nested - Fatal编程技术网

PHP中的单例引用和递归

PHP中的单例引用和递归,php,recursion,singleton,nested,Php,Recursion,Singleton,Nested,我有一个主引导类(下面示例中的singleton1),它实例化了一些singleton类。在这些单例类中,我需要保留对app main类的引用,以方便快速地引用它,但这样做会给我一个: Fatal error: Maximum function nesting level of '100' reached, aborting 以下是exmaple代码: <?php class Singleton1 { private static $instance; priva

我有一个主引导类(下面示例中的singleton1),它实例化了一些singleton类。在这些单例类中,我需要保留对app main类的引用,以方便快速地引用它,但这样做会给我一个:

Fatal error: Maximum function nesting level of '100' reached, aborting
以下是exmaple代码:

<?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”消息。

您不应该使用Singletons。它们是坏习惯(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();
     }
}

是的,当我做$this->singleton1=singleton1::instance()时,我想我刚刚得到了它;在Singleton2构造函数中,Singleton1尚未完成实例化,因此实例在静态$instance变量中还不可用,因此它尝试再次实例化它,并且再次……首先,这是一个非常糟糕的应用程序设计。你真的应该避免在你的代码中使用单例,而是支持依赖注入。也许你会理解。依赖注入是一个奇特的术语,简单的意思是:将对象传递给构造函数,或者通过setter方法。(通常通过某种类型的注册表或单例模式来对比检索对象,就像您现在所做的那样)。@fireyedboy,不,不是。如果您这样做,那么您就没有使用依赖项注入。。你之所以称它为DI,只是因为它是一个花哨的术语。@tereško:从根本上说,它是。您正在注入依赖项(通常通过构造函数或setter)。DI通常也是通过另外使用一些容器和/或工厂来创建对象的实例并将依赖项连接在一起来实现的,这并不意味着DI本身就是简单地向对象注入它们所依赖的东西。但是有一个特殊的原因,Singleton2应该由主类实例化。我想我会在第一次实例化主类时使用init方法来运行。是的,只是不要在Singleton1的构造函数中实例化Singleton2,因为Singleton1实例不是由该调用创建的。虽然这稍微好一点,你现在有一个循环引用,它仍然很糟糕。我过去经常做这样的事情,但我认为我必须对只需要实例化一次的类使用singleton。这不是一个好的实践吗?您将只创建一次应用程序实例,但您可以将应用程序设置为单例,因此服务实例也只创建一次。这里的要点是,您至少应该通过Setter/Constructor将应用程序实例注入到服务中,以避免调用
application::getInstance()
,从而导致递归。@igorw这不应该是交易制动器吗?PHP应该在请求端释放应用程序使用的所有内存。虽然我也认为应该避免。