我正在从头开始编写自定义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的实例,我相信它应该以某种方式工作,但事实并非如此。
我现在感到迷茫。如何使其工作或至少如何改变某些东西以具有相似的行为?
答案 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();