Singletons, Registries, and GLOBALS

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
neophyte
DevNet Resident
Posts: 1537
Joined: Tue Jan 20, 2004 4:58 pm
Location: Minnesota

Singletons, Registries, and GLOBALS

Post by neophyte »

The point of singletons and registries is to be able to instantiate an object such as a database object once and be able to call it in a different class with out having to instantiate a new object or pass it by reference into the object.

So far what I've read says this is best done through static variables in functions or methods. But what would be wrong with doing something like:

Code: Select all

function set_global( &$object, $handle = '' ){
		$class =(empty($handle))? get_class($object): $handle;
		$GLOBALS[$class] = &$object;
	}
	function get_global($handle){
		return $GLOBALS[$handle];
	}
functions are global and $GLOBALS will hold the value...

Seriously is this a good substitute? Is this just the same pattern reworked? Bad idea? Would like feed back....

Thanks
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

neophyte wrote:Seriously is this a good substitute?
I feel it's somewhat of a personal preference depending on how OOP you want to be or whether you feel that a many entries in the $GLOBALS array is better than one or none, depending on the "alternate" implementation. So all I can really say is I prefer Singletons and Registries over "standard" globals, however none of the directions are what I consider "prefect" or "optimal" ..
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I'm not even sure if your approach may perhaps be slower... I'd have to test that. You've kind of removed the whole side OOP that brings you encapsulation though since you've downright forced globals there. Your approach would work well nicely yes even in non OO frameworks -- in fact, I used to store the resource id in the session.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

It'd work fine - might cause some confusion (which may be a good point) about where the instantiated object is actually stored. In a singleton, the class locates an instantiated object in a static variable. Globals although workable just don't seem half as tidy.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Singletons, Registries, and GLOBALS

Post by Christopher »

The problem is that the code you posted is that it does not provide the protection from the real problem with globals -- that you cannot isolate your dependencies. Any code that uses those functions has a potential dependancy on every piece of code in your application because you can do $GLOBALS['foo'] = 'overwrite the value'; anywhere in the code. If you use a Registry you have clear dependencies.
(#10850)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Are you just thinking more about how to reduce the amount of typing or fetching of item from the registry? If you're using PHP5 have you looked into using an inherited registry? This way the registry contents will be quickly accessible by any object that inherits from it (stick the registry somewhere toward the bottom of the hierarchy).

I was just going over this with my boss about ten mins ago so here's a demonstration :P

Code: Select all

<?php

error_reporting(E_ALL);

//This would hold your database instance as static, it will also contain wrappers
class db
{
	static private $instance = null; //This will hold an instance of itself
	
	private $dbConn;
	
	private function __construct($host, $user, $pass, $name) //Note that this is private
	{
		$this->connect($host, $user, $pass);
		$this->selectDb($name);
	}
	
	static public function getInstance($host, $user, $pass, $name)
	{
		if (self::$instance == null)
		{
			self::$instance = new db($host, $user, $pass, $name); //Only creates object once *ever*
		}
		return self::$instance;
	}

	public function connect($host, $user, $pass)
	{
		$this->dbConn = mysql_connect($host, $user, $pass);
	}

	public function selectDb($name)
	{
		mysql_select_db($name, $this->dbConn);
	}
	
	/*
	 Some other wrapper functions here
	 */
	
}

class registry
{
	protected static $handlers = array();
	
	static public function add($name, $data)
	{
		if (!isset(self::$handlers[$name])) self::$handlers[$name] = $data;
	}

	static public function del($name)
	{
		if (!isset(self::$handlers[$name])) unset(self::$handlers[$name]);
	}

	protected function __get($name) //Overloaded getter
	{
		return self::$handlers[$name];
	}
}

//This is your typical class, with the registry somewhere at the base of the hierarchy
class foo extends registry
{
	function __construct()
	{
		//
	}

	public function reflect($obj)
	{
		print_r($this->$obj); //You'll see a DB object in here!
	}

	public function dump()
	{
		print_r($this);
	}
}

registry::add('db', db::getInstance('localhost', 'someuser', 'pass', 'www')); //Stick a database object in the registry

$obj = new foo;
$obj->reflect('db');

/*
 db Object
 (
     [dbConn] => Resource id #2
 )
 */

?>
So from inside the object you have access to $this->db->whateverMethod() at all times.
User avatar
neophyte
DevNet Resident
Posts: 1537
Joined: Tue Jan 20, 2004 4:58 pm
Location: Minnesota

Post by neophyte »

Wow! Thanks for all your comments.

I think I've decided that this is an okay solution as long as you're dealing with 2,3 maybe 4 objects in a small app (especially in php4). But for php 5 I think doing it that way would be just silly... Especialy on a big project.

As always I've learned a lot from your posts!

On a side note:
I got a new puter at work today! Very nice box and 0' course its a dual boot with Kubuntu.

:)
fastfingertips
Forum Contributor
Posts: 242
Joined: Sun Dec 28, 2003 1:40 am
Contact:

Post by fastfingertips »

I hate globals.

Since you are able to create a nice singleton (d11wtq you should know that you may scary people that are seeing private constructors :p ) why we should store tons of data in globals? I think that this is a designing problem.
Post Reply