Registry failure

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
jurriemcflurrie
Forum Commoner
Posts: 61
Joined: Wed Jul 06, 2005 7:14 am
Location: Den Haag, the Netherlands

Registry failure

Post 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.
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Post 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()?
User avatar
jurriemcflurrie
Forum Commoner
Posts: 61
Joined: Wed Jul 06, 2005 7:14 am
Location: Den Haag, the Netherlands

Post 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?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Technically, in PHP 4 you can call any method staticly. Whether the method is built to work staticly is another story.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post 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 ;)
User avatar
jurriemcflurrie
Forum Commoner
Posts: 61
Joined: Wed Jul 06, 2005 7:14 am
Location: Den Haag, the Netherlands

Post 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.
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Post 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 :)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post 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.
(#10850)
Post Reply