Singleton reference and recursion in PHP
I have a main bootstrap class (singleton1 in the example bellow) that instantiates some singleton classes. In those singleton classes, I need to keep a reference to the app main class for easy and quick reference to it, but doing so gives me a:
Fatal error: Maximum function nesting level of '100' reached, aborting
Here is the exmaple code:
<?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 =开发者_如何学Python new $class;
}
return self::$instance;
}
public function test () {
$this->singleton1->test();
}
private function __clone() { }
private function __wakeup() { }
}
Singleton1::instance();
Singleton2::instance()->test();
I can't find any logical explanation to the issue ...
Thanks.
Your code has the following loop:
Singleton2::__construct()
Singleton1::instance()
Singleton1::__construct()
Singleton2::instance()
Singleton2::__construct()
You can remove Singleton2::instance()
line from Singleton1
constructor to see "Good" message.
You should just not use Singletons. They're Bad Practice(tm), as they introduce global state, which makes your Code much harder to test.
One could rewrite your example by using Inversion Of Control this way:
<?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
is your Main Application's class and SomeService
is your Singleton2
.
No need for private constructors, etc. here and SomeService
gets only instantiated once, with your App (considered you only instantiate your App once).
Repeat this with other Services you want to add to your App instance.
Some good articles on this, which are worth reading:
- http://www.potstuck.com/2009/01/08/php-dependency-injection/
- http://fabien.potencier.org/article/11/what-is-dependency-injection
精彩评论