PHP Singleton:达到'100'的最大函数嵌套级别,正在中止

时间:2014-11-13 19:34:14

标签: php singleton

我正在从头开始编写自定义PHP应用程序,对于某些类我使用singleton模式,因为我需要一些信息来计算,我只是使用它们。今天我写了我的应用程序的很大一部分,当我全部测试它时,它会抛出以下错误:达到'100'的最大函数嵌套级别,正在中止。我做了一些测试,发现错误是由这样的事情产生的:

的index.php

class Foo
{
    public function __construct()
    {
        if(!class_exists('Bar', false))
        {
            require 'Bar.php';
        }

        $bar = new Bar;
        $bar->doSomething();
    }

    public function showSomeInformation()
    {
        // information
    }
}

function F()
{
    static $instance = null;

    if(is_null($instance))
    {
        $instance = new Foo;
    }

    return $instance;
}

F();

Bar.php

class Bar
{
    public function doSomething()
    {
        F()->showSomeInformation();
    }
}

在我看来它是有效的,因为之前调用了F(),它应该在静态变量中有Foo的实例,我相信它应该以某种方式工作,但事实并非如此。

我现在感到迷茫。如何使其工作或至少如何改变某些东西以具有相似的行为?

3 个答案:

答案 0 :(得分:1)

好的我已经在评论中提到了它,但是你走了。

$instance值始终为null。为什么?好好了解在将实例设置为$instance之前会发生什么。

$instance具有任何不同价值之前,您再次致电$bar->doSomething();

这意味着您再次运行F(),但$instance仍为null。现在,您再次实例化Foo,但猜测$instance仍为空。

编辑:试试这个:

<?php class Foo
{
    static $instance = null;

    public function __construct()
    {
        if(!class_exists('Bar', false))
        {
            require 'Bar.php';
        }

        self::$instance = $this;

        $bar = new Bar;
        $bar->doSomething(self::$instance);
    }

    public function showSomeInformation()
    {
        // information
    }
}

class Bar
{
    public function doSomething($instance)
    {
        F($instance)->showSomeInformation();
    }
}

function F($instance = null)
{
    if(is_null($instance))
    {
        $instance = new Foo;
    }

    return $instance;
}

F();

如果使用单例模式,请确保类本身跟踪是否已初始化。让外部源处理这会导致很多问题(正如您刚才所经历的那样)。

答案 1 :(得分:0)

无限递归发生在foo的构造函数中:

  function F()
  {
    static $instance = null;

    if(is_null($instance))
    {
        $instance = new Foo;
          echo("Never reached\n");
          if( is_null($instance) )
          {
                  echo("Still null!\n");
          }
      }

      return $instance;
  }

第一个F(); call不会创建一个Foo,它会调用Foo的构造函数,它会在返回Foo对象之前调用F(),但是F()会调用另一个Foo上的构造函数,它将永远执行相同的操作,所以没有新的Foo将从F()返回所以我们没有堆栈。

这是PHP中一个理智的单例模式的例子。 http://www.phptherightway.com/pages/Design-Patterns.html

答案 2 :(得分:0)

我不喜欢Singleton模式而且我猜,如果你有一点经验并开始进行单元测试,你也会讨厌它。但这种模式并不像你尝试过的那样。

class MySingletonClass 
{
    private static $instance;

    //make constructor protected, to prevent direct instantiation
    protected function __construct() {}

    /**
    * @return MySingletonClass
    */
    public static function getInstance()
    {
         if (!self::$instance) {
             self::$instance = new self(); //new static() would we valid too, relevant for extending (late state binding)
         }
         return self::$instance;
    }

    public function getSomething() 
    {
         if (!$this->calculated) {
             $this->calculated = $this->calculateSomething();
         }
         return $this->calculated;
    }
}

echo MySingletonClass::getInstance()->getSomething();