Page 1 of 1

Registry failure

Posted: Thu Sep 07, 2006 9:13 am
by jurriemcflurrie
Hey, can anyone tell me why the following isn't working?

Code: Select all

<?
class Registry {
	
	var $objects = array();
	
	function set($name, &$object) {
		if(!is_object($object)) {
			trigger_error('Non-object feeded to the registry', E_USER_ERROR);
		}
		$this->objects[$name] = &$object;
	}
	
	function &get($name) {
		if(isset($this->objects[$name])) {
			return $this->objects[$name];
		}
	}
	
	function delete($name) {
		if(isset($this->objects[$name])) {
			unset($this->objects[$name]);
		}
	}
	
	function &instance() {
		static $reg;
		if(!$reg) {
			$reg = &new Registry();
		}
		return $reg;
	}
	
}

class Class1 {
	
	var $reg;
	
	function Class1() {
		$this->reg = &Registry::instance();
	}
	
	function checkReg() {
		print_r($this->reg);
	}
	
}

class Class2 {
	
	var $reg;
	
	function Class2() {
		$this->reg = &Registry::instance();
	}
	
	function checkReg() {
		print_r($this->reg);
	}
	
}

$reg = &Registry::instance();
$reg->set('Class1', new Class1());
$reg->set('Class2', new Class2());

$Class1 = &$reg->get('Class1');
$Class1->checkReg();
$Class2 = &$reg->get('Class2');
$Class2->checkReg();
?>
I was hoping that I could feed the registry anywhere in my script and that it's everywhere 'updated'. That's what pass-by-reference does, I thought.

Posted: Thu Sep 07, 2006 10:00 am
by Mordred
http://www.php.net/manual/en/language.v ... .scope.php

Code: Select all

function &instance() { 
                static $reg; 
                if(!$reg) { 
                        $reg = new Registry();  //no reference!
                } 
                return $reg; 
        }
BUT

Your main trouble is that you're doing it all wrong (IMO) ;)

You're implementing Singleton, but you're keeping references to the object (why?). You're trying to write as in C++/Java mayhap?

Make some static functions Registry::Set(), Registry::Get() and Registry::Delete() and that's it. No hassles with references, no global $registry; <span style='color:blue' title='I&#39;m naughty, are you naughty?'>smurf</span>, no $this->reg->how->many->arrows->did->I->write->already()?

Posted: Thu Sep 07, 2006 2:59 pm
by jurriemcflurrie
You're right!! Sometimes I think waaayyy too difficult.

But I'm affraid that can only be done in php5? Or is there a way to get static functions in php4?

Posted: Thu Sep 07, 2006 3:05 pm
by feyd
Technically, in PHP 4 you can call any method staticly. Whether the method is built to work staticly is another story.

Posted: Thu Sep 07, 2006 3:11 pm
by Chris Corbyn
jurriemcflurrie wrote:You're right!! Sometimes I think waaayyy too difficult.

But I'm affraid that can only be done in php5? Or is there a way to get static functions in php4?
Static registries don't work in PHP4 since you can't have static properties, you can only have static functions. A halfway approach is to use a global as a container where you'd usually have a static property.

Something like:

Code: Select all

$___registry = array();

class Registry
{
    function add(&$object, $name)
    {
        global $___registry;
        $___registry[$name] =& $object;
    }
    
    function has($name)
    {
        global $___registry;
        return array_key_exists($name, $___registry);
    }

    function &get($name)
    {
        global $___registry;
        if ($this->has($name))
        {
            return $___registry[$name];
        }
    }
    
    function delete($name)
    {
        global $___registry;
        if ($this->has($name))
        {
            unset($___registry[$name]);
        }
    }
}
You could easily make that entire class static too since it's completely monostate anyway ;)

Posted: Fri Sep 08, 2006 1:51 am
by jurriemcflurrie
Thanks, helped me a lot.

This is how they do it in CakePHP, works very well I believe.

Code: Select all

class Registry {
	
	var $objects = array();
	
	function &instance() {
		static $reg;
		if(!$reg) {
			$reg = new Registry();
		}
		return $reg;
	}
	
	function set($name, &$object) {
		$_this = &Registry::instance();
		$_this->objects[$name] = &$object;
	}
	
	function &get($name) {
		$_this = &Registry::instance();
		return $_this->objects[$name];
	}
	
}
But the above is untested.

Posted: Fri Sep 08, 2006 2:24 am
by Mordred
feyd wrote:Technically, in PHP 4 you can call any method staticly. Whether the method is built to work staticly is another story.
Easy, if it uses $this, it ain't no static :)

Posted: Fri Sep 08, 2006 2:27 am
by Christopher
The question I would have about using the Singleton pattern here is -- do you really have the problem of creating multiple instances of the Registry? I see code like this all the time where the programmer creates a single instance and passes it through the controllers without actually needing the Singleton code they implemented. I would treat the Singelton as a last resort. Most often when you only want one of an object you just simply only create one.