我有一个主引导类(下面示例中的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实例中的其他服务重复此操作。
一些关于这方面的好文章,值得一读:
- http://www.potstuck.com/2009/01/08/php-dependency-injection/
- http://fabien.potencier.org/article/11/what-is-dependency-injection