phant0m Posted June 12, 2010 Share Posted June 12, 2010 I have been using the singleton pattern for some time now, and never experienced any problems with it. <?php static public function getInstance(){ if (self::$instance === NULL){ self::$instance = new ThemeEngine(); } return self::$instance; } private function __construct(){ $this->reqh = RequestHandler::getInstance(); $this->var = array(); } ?> Now, I request the instance at the very beginning of my script: $theme Then somewhere in the middle, some object requests the instance (let's call it $object->theme, and using a method of the requested instance (via getInstance() of course) modified the $object->theme->var member. Now come the interesting part: $theme->var is different from $object->theme->var And even more interestingly: $theme2 = ThemeEngine::getInstance(); and $theme2->var is the same as $object->theme->var How can this be? I have placed breakpoints in the constructor of my class, and it hits only once. Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/ Share on other sites More sharing options...
trq Posted June 12, 2010 Share Posted June 12, 2010 We need to see some relevant code. Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/#findComment-1071278 Share on other sites More sharing options...
phant0m Posted June 12, 2010 Author Share Posted June 12, 2010 index.php <?php require_once 'initialiser.php'; $object1 = new Object1(); [...] $theme2 = ThemeEngine::getInstance(); var_dump($theme->var['test']); //yields undefined var_dump($theme2->var['test']); //yields "XYZ" initialiser.php <?php require_once 'object1.php'; $theme = ThemeEngine::getInstance(); ?> Object1.php <?php class Object1{ protected $theme; public function __construct(){ $this->theme = ThemeEngine::getInstance(); $this->theme->var = 'XYZ'; } } ?> themeengine.php <?php class ThemeEngine{ static private $instance = null; public $var; static public function getInstance(){ if (self::$instance === NULL){ self::$instance = new ThemeEngine(); } return self::$instance; } private function __construct(){ $this->reqh = RequestHandler::getInstance(); $this->var = array(); } } ?> Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/#findComment-1071281 Share on other sites More sharing options...
phant0m Posted June 12, 2010 Author Share Posted June 12, 2010 For further testing, I added var_dump() with a custom text indicating the location of the statement in the constructor of ThemeEngine. It shows only once in the source of my webpage. Apparently, the singleton is working, but why are the members still different even when they are access right one after another? Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/#findComment-1071291 Share on other sites More sharing options...
trq Posted June 12, 2010 Share Posted June 12, 2010 I don't see anywhere where you actually set $theme->var['test'] Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/#findComment-1071294 Share on other sites More sharing options...
phant0m Posted June 12, 2010 Author Share Posted June 12, 2010 I just made an error when typing the code above^^ Just assume that I wrote $this->theme->var['test'] = 'XYZ'; Anyway, I have discovered what messes with my variables: PHPUnit. I was trying to integrate this into my Framework to automate unit testing. But somehow it breaks the relationship between the original $theme and the $theme after PHPUnit has run. However, once PHPUnit has run, $theme is still an instance of the Class it was before, but $theme === $theme->getInstance() yields false. How can PHPUnit change that, if it is unable to create a new instance of ThemeEngine directly, because the access is set to private? //Edit: I have just had a look at PHPUnit's code. Apparently it serializes all my objects in the global scope and unserializes them when it's done. That would explain how the relationship is broken. I guess I'll just have to implement __sleep and __wakeup accordingly. Any other ideas? Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/#findComment-1071296 Share on other sites More sharing options...
phant0m Posted June 13, 2010 Author Share Posted June 13, 2010 Here's how I got around the problem: public function __wakeup(){ $reflection = new ReflectionClass(__CLASS__); $properties = $reflection->getProperties(); foreach($properties as $property){ $this->{$property->getName()} =& self::$instance->{$property->getName()}; } } public function __sleep(){ return array(); } Quote Link to comment https://forums.phpfreaks.com/topic/204604-singleton-different-data-on-members/#findComment-1071329 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.