Singleton and Registry Help

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Singleton and Registry Help

Post by John Cartwright »

Okay.. I've been using registry for awhile but I recently noticed that my singleton was not acting like a singleton at all.. there is obviously something I am missing.. but I cannot find much helpful documentation on this.. :\

Heres the code I'm using

Code: Select all

class Registry 
	{
		 var $_cache_stack;
	
		 function Registry() {
			  $this->_cache_stack = array(array());
		 }
		 
		 function setEntry($key, &$item) {
			  $this->_cache_stack[0][$key] = &$item;
		 }
		 
		 function &getEntry($key) {
			  return $this->_cache_stack[0][$key];
		 }
		
		 function isEntry($key) {
			  return ($this->getEntry($key) !== null);
		 }
		 
		 function &instance() {
			  static $registry = false;
			  if (!$registry) {
					$registry = new Registry();
			  }
			  return $registry;
		 }
		 
		 function save() {
			  array_unshift($this->_cache_stack, array());
			  if (!count($this->_cache_stack)) {
					trigger_error('Registry lost');
			  }
		 }
		 
		 function restore() {
			  array_shift($this->_cache_stack);
		 }
	}

	class Singleton 
	{
		 function Singleton() {
			  $registry = &Registry::instance();
			  if ($registry->isEntry('singleton ' . get_class($this))) {
					trigger_error(
							  'Already an instance of singleton ' .
							  get_class($this));
			  }
			  
			  echo 'testing';
		 }
		 
		 function &instance($class) {
			  $registry = &Registry::instance();
			  if (!$registry->isEntry('singleton ' . $class)) {
					$registry->setEntry(
							  'singleton ' . $class, new $class());
			  }
			  return $registry->getEntry('singleton ' . $class);
		 }
	}
Anways, I did a quick test to see if the instance was being saved, which is wasn't

Code: Select all

class testRegistry 
	{
		var $_input;
	}

        $testReg = Singleton::instance('testRegistry');
	$testReg->_input = 'snap1';
	
	$testReg = Singleton::instance('testRegistry');
	print_r($testReg);	#failed
	$testReg->_input = 'snap2';
	print_r($testReg);	#ok
	
	class testRegMethod 
	{
		function testRegMethod() {
			$testReg = Singleton::instance('testRegistry');
			print_r($testReg); #failed
			$testReg->_input = 'snap3';
			print_r($testReg); #ok
			
		}
	}
	
	$testRegMethod = new testRegMethod();
	$testReg = Singleton::instance('testRegistry');	
	print_r($testReg); #failed
outputs

Code: Select all

testregistry Object
(
    [_input] => 
)
testregistry Object
(
    [_input] => snap2
)
testregistry Object
(
    [_input] => 
)
testregistry Object
(
    [_input] => snap3
)
testregistry Object
(
    [_input] => 
)
Somethings that I realized is, when does the singleton's constructor get called, since I only should be calling this class statically, correct?
When and where do the methods $registry->save() and $registry->restore() actually get called?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

If you are using PHP4 (which cannot store references in statics) I believe it needs to be:

Code: Select all

function &instance() {
              static $registry = array();
              if (! $registry) {
                    $registry[0] = & new Registry(); 
              }
              return $registry[0];
         }
In PHP5 you can just create a static class property (rather than function local var) which simpifies things.
(#10850)
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

I've tried that.. but to the same effect.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

What version of PHP are you using. With PHP5 I get:

Code: Select all

1: testRegistry Object
(
    [_input] => snap1
)

2: testRegistry Object
(
    [_input] => snap2
)

3: testRegistry Object
(
    [_input] => snap2
)

4: testRegistry Object
(
    [_input] => snap3
)

5: testRegistry Object
(
    [_input] => snap3
)
What are you using the static calls for anyway? I try to do straight composition and stay away from static calls. I prefer the Registry over the Singleton -- I can't think of anywhere I use them anymore.
(#10850)
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

What are you using the static calls for anyway?
Wouldn't it eliminate the need to instantiate the class?
I try to do straight composition and stay away from static calls.
Sorry could you elabortate a bit more?
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Well, I guess I'll take this as an excuse to finally upgrade.. thanks arborint :wink:
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Jcart wrote:Wouldn't it eliminate the need to instantiate the class?
Well you are instantiating a class anyway. My question is why your architecture needs globals? To me those calls indicate that you don't have clean dependencies.
Jcart wrote:Sorry could you elabortate a bit more?
It may seem a pain, but passing object through the constructor oftens ends up creating the most testable and solid code in the long run in PHP. The dependencies are clear and the interface is polymorphic. The next step past composition is to in some way inject the object/methods into the object that need them. Not so easy in PHP.
(#10850)
User avatar
m3mn0n
PHP Evangelist
Posts: 3548
Joined: Tue Aug 13, 2002 3:35 pm
Location: Calgary, Canada

Post by m3mn0n »

Jcart wrote:Well, I guess I'll take this as an excuse to finally upgrade.. thanks arborint :wink:
Atta boy! PHP 5 ftw! :)
Post Reply