Jump to content

Singleton: different data on members??


phant0m

Recommended Posts

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.

 

 

Link to comment
Share on other sites

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();
        } 
}
?>

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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(); 
        }

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.