PHP5 OOP - The registry pattern and solving name space problems

Posted by: §intå×

PHP5 OOP - The registry pattern and solving name space problems - 05/30/08 11:32 PM

<rant>

Okay so it has been a while since I was up in this biotch. I have been busy. Having developed in PHP for the last 8 years I have evolved with it. Started out coding as most in procedural style. In the last 3 years I have done almost nothing but OOP code. PHP5 was a huge step forward in terms of OOP capabilities. In my opinion since PHP has stopped development on PHP4 it is best to move up to PHP5 as if you do not PHP6 will be a real pain for you.

</rant>

Okay so how many of you have ran into this problem. You design a function.
Php Code:

function myFunc(){
   $value = 'This is my value';
}

echo $value;
 


Only to find out the example above no worky. This can be solved with a return clause.

Php Code:

function myFunc(){
   $value = 'This is my value';
   return $value;
}

echo myFunc();
 


Now that works... But what if we want to have a function give us back more than one value. We could creat an array in the function and pass that back. Then break the array down after we call the function. Bleh. Work work work. Code code code.

What if we had one place to store values. A magical place that crosses name space, yet helps us not overwrite our values on accident. Kinda like a registry of sorts. Well I have that place. Here is how it works.

Php Code:


<?php
 /**
  * Declare my registry
  */
 $reg = new registry();

/**
 * Define my function
 */
 function myFunc( $reg ){
   $reg->set('value', 'This is my value');
   $reg->set('value2', 'This is my other value');
   $reg->set('value3', 'This is my third value')

   $myArray = array();
   $myArray[1] = 'string 1';
   $myArray[2] = 'string 2';
   $myArray[3] = 'string 3';

   $reg->set('myArray', $myArray);
}

echo $reg->get('value');

echo $reg->get('value2');

echo $reg->get('value3');

print_r(
		 $reg->get('myArray')
		);




The above code, works if you use the registry pattern. Instead of having to pass around tons of vars in your code, you could pass just one. Here is the code for my registry class.

Php Code:


<?php
	/**
	* Registry class file
	*
	* This is the CMS registry.  All global objects should be registered in this class before use.
	* @author		 Russell Vance
	* @copyright	 (C)VanceConcepts.com 2007
	* @version		 0.0.1
	* @license		 http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
	* @filesource
	* @todo		 Look into implementing multiple registries.  For example maybe a seperate one for MySQL or Smarty
	*/
	

/**
* This is the registry class for the system.  
*
* The registry allows for a centralized place to store objects and data.  Any class can store and retrieve objects from here.  Uses an implementation of the registry pattern.
* @author			   §intå×
* @copyright			(C)VanceConcepts.com 2007
* @version		 0.0.3
* @Package			 Registry
* @since		 5/28/2008
*/

class registry{
	/**
	* This variable will store the registry in an array.  It can not be called directly, you must used the get() and set() methods.
	* @access private
	* @var array
	*/
	public $reg;
	
	/**
	* This is the constructor for the registry class
	*
	* This method will initiate the class.  In other words to use this method you MUST get an instance of this class. 
	* To initiate this class you need to something like the following example.
	* <code>
	* //Example:
	* $_reg		= new registry();	# No parameters are required for start up.
	* </code>
	* @access	 public
	* @param	void
	* @return	void
	*/	
	public function __construct($reg = null){
		$this->reg = array();
	}
	
	/**
	* This method checks to see if a object is stored in the registry or not.
	*
	* This is a private method and is not called directly. It Checks the registry 
	* to see is a registry key exists.  It returns the coresponing boolean value.
	* @access	 public
	* @param	string	$key	The key to the object you are trying to retreive.
	* @return	boolean			[True] if registry key exists, [False] is it doesn't.
	*/
	public function isValid($key){
		return array_key_exists($key, $this->reg);
	}
	
	/**
	* This method creats new registry items.
	*
	* This is method takes a key name and a object and creates a new registry 
	* item.  The key name should have no spaces.  If the key Name exists already 
	* a catchable exception is thrown.
	* <code>
	* Example:
	*
	* $reg = new registry();
	* try{
	*	 $reg->set( 'mysqli', new mysqli( $host:$port, $user, $psswd, $database ) );
	* }catch(Exception $e){
	*	controlCore::handleError($e->getMessage(), 'general');
	* }
	* </code>
	* @uses	registry::isValid()			Used to test if a key is valid.  isValid is a private method and can not be called directly.
	* @access	 public
	* @param	string				$key	The key to the object you are trying to retreive.
	* @param	object				$obj	The object you want stored in the registry
	* @return	boolean				[True] if new registry item is created, [False] if registry item exists already.
	*/
	public function set($key, $obj){
		if(!$this->isValid($key)){
			$this->reg[$key] = $obj;
			$retVal = true;
		}else{
			$retVal = false;
			//controlCore::handleError('Could not set registry item "'.$key.'" as it is in use already', 'reg');
		}
		return $retVal;
	}
	
	/**
	* This method retrieves an object from the registry
	*
	* This is the accesor method for the Registry.  It requires you call it with the 
	* key to the object you want to retrieve.  On failure a catchable exception is thrown.
	* <code>
	* Example:
	*
	* $reg = new registry();
	*
	* //Insert object into registry
	* try{
	*	reg->set( 'mysqli', new mysqli( $host:$port, $user, $psswd, $database ) );
	* }catch(Exception $e){
	*	controlCore::handleError($e->getMessage(), 'general');
	* }
	*
	* //get object from registry
	* try{
	*	$mysqli = reg->get('mysqli');
	* }catch(Exception $e){
	*	controlCore::handleError($e->getMessage(), 'general');
	* }
	* </code>
	* @access	 public
	* @uses	registry::isValid()			Used to test if a key is valid.  isValid is a private method and can not be called directly.
	* @param	string					$key	The key to the object you are trying to retreive.
	* @return	object|boolean			On sucess an object is returned, On fail a boolean value of false is returned.
	*/
	public function get($key){
		if($this->isValid($key)){
			$retVal = $this->reg[$key];
		}else{
			$retVal = false;
			//controlCore::handleError('Could not get registry item "'.$key.'."  Does not exist in registry','reg');
		}
		return $retVal;
	}
	
	/**
	* This method over writes an object in the registry
	*
	* This is the over write method for the Registry.  It requires you call it with the 
	* key to the object you want to over write and the data you are over writing 
	* with.  If the key did not exist previously, a boolean false is returned and an 
	* exception is thrown, but the data is entered into the database.
	* <code>
	* Example:
	*
	* $reg = new registry();
	*
	* //Insert object into registry
	* try{
	*	$reg->set( 'mysqli', new mysqli( $host:$port, $user, $psswd, $database ) );
	* }catch(Exception $e){
	*	controlCore::handleError($e->getMessage());
	* }
	*
	* //Over write object in the registry
	* try{
	*	$reg->overWrite('mysqli', new mysqli( $alt_host:$alt_port, $alt_user, $alt_psswd, $alt_database ) );
	* }catch(Exception $e){
	*	controlCore::handleError($e->getMessage());
	* }
	* </code>
	* @access	 public
	* @uses	registry::isValid()		Used to test if a key is valid.  isValid is a private method and can not be called directly.
	* @param	string				$key	The key to the object you are trying to retreive.
	* @param	mixed				$obj	Any data that you want to store.  Arrays, objecsts, boolean, strings, integers etc.
	* @return	boolean				On boolean [TRUE] is returned, On fail a boolean value of [FALSE] is returned and a catchable exception is thrown.
	*/
	public function overWrite($key, $obj){
		if($this->isValid($key)){
			$this->reg[$key] = $obj;
			$retVal = true;
		}else{
			$this->reg[$key] = $obj;
			$retVal = false;
			//controlCore::handleError('Could not over write registry item because it does not exist"'.
				//				$key.'."  Did not exist in registry', 'reg');
		}
		return $retVal;
	}
}
?>




You will notive in the code "controlCore::handleError" I have another class I will be sharing named controlCore. For now I have commented it out. If you wanted to handle errors however, this is where your code would go. Feel free to use this class, change it, re-write it. I really do not care it is nothing major. It is however a nice easy class to start teaching with.

In this class we have

  • 1 class variable named $reg
  • 5 methods
    • __construct() - instantiates the class
    • isValid() - Checks to make sure a value exists
    • get() - retrieves a value from the register
    • set() - Sets a value into the registry, will not let you overwrite a value.
    • overWrite() - allows for explicit overwrite of a value.


To use, copy and save the code to registry.php(or whatever you want to name it).

In your code you must require or include the code once..

Php Code:

@require_once('/path/to/registry.php');

//Instantiate the class
$reg = new registry();

//If you wanted more than one  just do this.
$reg2 = new registry();

//To use methods just use the ->

$reg->set('value1', 'some Value');

echo $reg->get('value1');

$reg->overWrite('value1', 'A new Value');

echo $reg->get('value1');
 



I make you call overWrite() explicitly to prevent accidental overwrites. Each method calls isValid() before doing what you ask it to do. If a value already exists, set() will fail and return false. Please post any questions below. I hope it helps but I do not guarantee this code to work, use it at your own risk. I can not know every set up of every system. Please test well before putting this in a production environment. If you make improvements to the code feel free to share. I can not find it but I have a version of this with a flush method. I had a project where I actually needed to be able to flush the whole registry and be able to rebuild it. I will post that later.
Posted by: §intå×

Re: PHP5 OOP - The registry pattern and solving name space problems - 05/30/08 11:41 PM

I will be documenting this with phpDocumentor and making the documentation available too. Next up is php5.2.x OOP and caching mysql result sets.
Posted by: Gremelin

Re: PHP5 OOP - The registry pattern and solving name space problems - 05/31/08 05:39 AM

I need to get the code parser updated lol
Posted by: §intå×

Re: PHP5 OOP - The registry pattern and solving name space problems - 05/31/08 12:34 PM

Just get the black text to be white and I think we are good.
Posted by: §intå×

Re: PHP5 OOP - The registry pattern and solving name space problems - 05/31/08 11:53 PM

That is why you are the man Gizmo. looks MUCH better man. Nice.