Return to Snippet

Revision: 25393
at June 7, 2013 07:05 by freelancephp


Updated Code
<?php
/**
 * Lim_Registry Class
 *
 * Registry for managing global vars and references with support for lazy loading.
 *
 * @package  Registry
 * @version  2.0.0
 * @author   Victor Villaverde Laan
 * @link     http://www.freelancephp.net/lim_registry-php-lazy-registry-class/
 * @license  MIT license
 */
class Lim_Registry {

	/**
	 * Default overwrite entries when being set more than once
	 * @var boolean
	 */
	protected $_defaultOverwrite = true;

	/**
	 * Singleton pattern
	 * @var array
	 */
	private static $_instances = array();

	/**
	 * Containing all entries
	 * @var array
	 */
	protected $_entries = array();

	/**
	 * Protected contructor for singleton protection
	 */
	protected final function __construct() {
	}

	/**
	 * Private clone method for singleton protection
	 */
	private final function __clone() {
	}

	/**
	 * Get instance of (called) class
	 * @return Lim_Registry
	 */
	public static function getInstance() {
		$class = self::_getClass();

		if (empty(self::$_instances[$class]))
			self::$_instances[$class] = new $class;

		return self::$_instances[$class];
	}

	/**
	 * Set default overwriting entries when being set more than once.
	 * @param boolean $overwrite Optional, else used as a getter
	 * @return boolean
	 */
	public static function defaultOverwrite($overwrite = null) {
		if ($overwrite !== null)
			self::getInstance()->_defaultOverwrite = (bool) $overwrite;

		return self::getInstance()->_defaultOverwrite;
	}

	/**
	 * Set value of given key
	 * @param string $key
	 * @param mixed $value
	 * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
	 * @return boolean Value was set succesfully
	 */
	public static function set($key, $value, $overwrite = null) {
		$settings = array('type' => 'value', 'loaded' => true, 'value' => $value);
		return self::getInstance()->_setEntry($key, $settings, $overwrite);
	}

	/**
	 * Set value by reference (for arrays)
	 * @param string $key
	 * @param mixed $value
	 * @return boolean Value was set succesfully
	 */
	public static function setByRef($key, & $value) {
		$settings = array('type' => 'value', 'loaded' => true, 'value' => & $value);
		return self::getInstance()->_setEntry($key, $settings, true);
	}

	/**
	 * Set lazy entry of a class. Instance will only be created when entry is requested using the get method.
	 * @param string $key
	 * @param string $class
	 * @param array $args
	 * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
	 * @return boolean Value was set succesfully
	 */
	public static function setLazyClass($key, $class, $args = array(), $overwrite = null) {
		$settings = array('type' => 'class', 'class' => $class, 'args' => $args, 'loaded' => false, 'value' => null);
		return self::getInstance()->_setEntry($key, $settings, $overwrite);
	}

	/**
	 * Set lazy entry of a callback function. Function will only be called when entry is requested using the get method.
	 * @param string $key
	 * @param array $callback
	 * @param array $args
	 * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
	 * @return boolean Value was set succesfully
	 */
	public static function setLazyCallback($key, $callback, $args = array(), $overwrite = null) {
		$settings = array('type' => 'callback', 'callback' => $callback, 'args' => $args, 'loaded' => false, 'value' => null);
		return self::getInstance()->_setEntry($key, $settings, $overwrite);
	}

	/**
	 * Get value of given key
	 * @param string $key
	 * @param boolean $reload Reload if class or callback was already loaded
	 * @return mixed
	 * @throw Exception
	 */
	public static function get($key, $reload = false) {
		$instance = self::getInstance();

		// check if entry exists
		if (!key_exists($key, $instance->_entries))
			self::_throwException('Key "' . $key . '" could not be found.');

		// get current entry
		$entry = $instance->_entries[$key];

		// check if entry should be loaded or reloaded
		if (!$entry['loaded'] || $reload) {
			if ($entry['type'] == 'class') {
				// get reflection class
				$refClass = new ReflectionClass($entry['class']);
				// create instance
				if (empty($entry['args'])) {
					$entry['value'] = $refClass->newInstanceArgs();
				} else {
					$entry['value'] = $refClass->newInstanceArgs($entry['args']);
				}
			} else if ($entry['type'] == 'callback') {
				// run callback and set return value
				$entry['value'] = call_user_func_array($entry['callback'], $entry['args']);
			} else {
				self::_throwException('Type "' . $type . '" is not supported.');
			}

			// set (new) value and change "loaded" setting
			$instance->_entries[$key]['value'] = $entry['value'];
			$instance->_entries[$key]['loaded'] = true;
		}

		return $entry['value'];
	}

	/**
	 * Get value by reference (for arrays)
	 * @param string $key
	 * @return mixed By reference
	 */
	public static function & getByRef($key) {
		$instance = self::getInstance();

		// check if entry exists
		if (!key_exists($key, $instance->_entries))
			self::_throwException('Key "' . $key . '" could not be found.');

		// get current entry
		$entry = $instance->_entries[$key];

		return $entry['value'];
	}

	/**
	 * Check if given entry exists
	 * @param string $key
	 * @return boolean
	 */
	public static function has($key) {
		return key_exists($key, self::getInstance()->_entries);
	}

	/**
	 * Check if given (lazy) entry is already loaded
	 * @param string $key
	 * @return boolean
	 */
	public static function isLoaded($key) {
		return (self::has($key) && self::getInstance()->_entries[$key]['loaded'] === true);
	}

	/**
	 * Remove the given entry
	 * @param string $key
	 * @throw Exception
	 */
	public static function remove($key) {
		if (!self::has($key))
			self::_throwException('Key "' . $key . '" does not exist.');

		unset(self::getInstance()->_entries[$key]);
	}

	/**
	 * Remove all entries
	 */
	public static function clear() {
		$keys = array_keys(self::getInstance()->_entries);

		foreach ($keys as $key)
			self::remove($key);
	}

	/**
	 * Set value of given key
	 * @param string $key
	 * @param mixed $settings
	 * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
	 * @return boolean Value was set succesfully
	 */
	protected function _setEntry($key, $settings, $overwrite = null) {
		// check if overwriting is allowed
		$overwrite = ($overwrite === null) ? $this->_defaultOverwrite : $overwrite;

		// check if entry exists and overwriting is allowed
		if (key_exists($key, $this->_entries) && !$overwrite)
			return false;

		$this->_entries[$key] = $settings;

		return true;
	}

	/**
	 * Throw exception
	 * @param string $msg
	 * @throw Exception
	 */
	protected static function _throwException($msg) {
		throw new Exception(self::_getClass() . ' - ' . $msg);
	}

	/**
	 * get_called_class() equivalent also support for PHP < 5.3.
	 * @return string
	 */
	protected static function _getClass() {
		if (function_exists('get_called_class'))
			return get_called_class();

		$class = __CLASS__;

		try {
			$bt = debug_backtrace();
			$l = 0;

			do {
				$l++;
				$lines = file($bt[$l]['file']);
				$callerLine = $lines[$bt[$l]['line']-1];
				preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/', $callerLine, $matches);
			} while ($matches[1] === 'parent' && $matches[1]);

			if (class_exists($matches[1]))
				$class = $matches[1];
		} catch (Exception $e) {
		}

		return $class;
	}

} // Lim_Registry

Revision: 25392
at July 24, 2011 21:56 by freelancephp


Updated Code
<?php
/**
 * LRegistry Class
 *
 * Managing globals with the registry pattern.
 * This class provides lazy loading functionallity. This means it is possible to
 * add a callback or class (with arguments) which will be called or instanciated
 * when it is being used for the first time.
 *
 * @version  1.1
 * @author   Victor Villaverde Laan
 * @link     http://www.freelancephp.net/php-lazy-registry-class/
 * @license  MIT license
 */
class LRegistry {

	/**
	 * Singleton pattern
	 * @var Registry object
	 */
	protected static $_instance = NULL;

	/**
	 * Containing all entries
	 * @var array
	 */
	protected $_entries = array();

	/**
	 * Default overwrite entries when being set more than once
	 * @var boolean
	 */
	protected $_default_overwrite = TRUE;

	/**
	 * Private contructor for singleton protection
	 */
	private final function __construct() {}

	/**
	 * Private clone method for singleton protection
	 */
	private final function __clone() {}

	/**
	 * Get instance of this class
	 * @return Registry object
	 */
	public static function get_instance() {
		if ( self::$_instance === NULL )
			self::$_instance = new LRegistry;

		return self::$_instance;
	}

	/**
	 * Get value of given key
	 * @param string  $key
	 * @param boolean $reload  reload if class or callback was already loaded
	 * @return mixed
	 * @throw Exception
	 */
	public static function get( $key, $reload = FALSE ) {
		$instance = self::get_instance();

		// check if entry exists
		if ( ! key_exists( $key, $instance->_entries ) )
			throw new Exception( get_class( self::get_instance() ) . ': Key "' . $key . '" could not be found.' );

		// get current entry
		$entry = $instance->_entries[$key];

		// check if entry should be loaded or reloaded
		if ( ! $entry['loaded'] OR $reload ) {
			if ( $entry['type'] == 'class' ) {
				// get reflection class
				$ref_class = new ReflectionClass( $entry['class'] );
				// create instance
				$entry['value'] = $ref_class->newInstanceArgs( $entry['args'] );
			} else if ( $entry['type'] == 'callback' ) {
				// run callback and set return value
				$entry['value'] = call_user_func_array( $entry['callback'], $entry['args'] );
			} else {
				throw new Exception( get_class( self::get_instance() ) . ': Type "' . $type . '" is not supported.' );
			}

			// set (new) value and change "loaded" setting
			$instance->_entries[$key]['value'] = $entry['value'];
			$instance->_entries[$key]['loaded'] = TRUE;
		}

		return $entry['value'];
	}

	/**
	 * Set value of given key
	 * @param string  $key
	 * @param mixed   $value
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	public static function set( $key, $value, $overwrite = NULL ) {
		// set normal value settings
		$settings = array( 'type' => 'value',
							'loaded' => TRUE,
							'value' => $value );

		return self::get_instance()->_set( $key, $settings, $overwrite );
	}

	/**
	 * Set lazy entry of a class. Instance will only be created when entry
	 * is requested using the get method.
	 * @param string  $key
	 * @param string  $class
	 * @param array   $args
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	public static function set_lazy_class( $key, $class, $args = array(), $overwrite = NULL ) {
		// set lazy class settings
		$settings = array( 'type' => 'class',
							'class' => $class,
							'args' => $args,
							'loaded' => FALSE,
							'value' => NULL );

		return self::get_instance()->_set( $key, $settings, $overwrite );
	}

	/**
	 * Set lazy entry of a callback function.Function will only be called when entry
	 * is requested using the get method.
	 * @param string  $key
	 * @param array   $callback
	 * @param array   $args
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	public static function set_lazy_callback( $key, $callback, $args = array(), $overwrite = NULL ) {
		// set lazy callback settings
		$settings = array( 'type' => 'callback',
							'callback' => $callback,
							'args' => $args,
							'loaded' => FALSE,
							'value' => NULL );

		return self::get_instance()->_set( $key, $settings, $overwrite );
	}

	/**
	 * Check if given entry exists
	 * @param string $key
	 * @return boolean
	 */
	public static function has( $key ) {
		return key_exists( $key, self::get_instance()->_entries );
	}

	/**
	 * Check if given (lazy) entry is already loaded
	 * @param string $key
	 * @return boolean
	 */
	public static function is_loaded( $key ) {
		return ( self::has( $key ) AND self::get_instance()->_entries[$key]['loaded'] === TRUE );
	}

	/**
	 * Remove the given entry
	 * @param string $key
	 * @throw Exception
	 */
	public static function remove( $key ) {
		if ( ! self::has( $key ) )
			throw new Exception( get_class( self::get_instance() ) . ': Key "' . $key . '"does not exist.' );

		unset( self::get_instance()->_entries[$key] );
	}

	/**
	 * Set default overwriting entries when being set more than once.
	 * @param boolean|NULL $overwrite  optional, if empty can be used as a getter
	 * @return boolean
	 */
	public static function default_overwrite( $overwrite = NULL ) {
		if ( $overwrite !== NULL )
			self::get_instance()->_default_overwrite = (bool) $overwrite;

		return self::get_instance()->_default_overwrite;
	}

	/**
	 * Set value of given key (private use)
	 * @param string  $key
	 * @param mixed   $settings
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	protected function _set( $key, $settings, $overwrite = NULL ) {
		$instance = self::get_instance();

		// check if overwriting is allowed
		$overwrite = ( $overwrite === NULL )
					? $this->_default_overwrite
					: $overwrite;

		// check if entry exists and overwriting is allowed
		if ( key_exists( $key, $this->_entries ) AND ! $overwrite )
			return FALSE;

		$this->_entries[$key] = $settings;

		return TRUE;
	}

}

/*?> // ommit closing tag, to prevent unwanted whitespace at the end of the parts generated by the included files */

Revision: 25391
at March 30, 2010 04:35 by freelancephp


Initial Code
<?php
/**
 * LRegistry Class
 *
 * Managing globals with the registry pattern.
 * This class provides lazy loading functionallity. This means it is possible to
 * add a callback or class (with arguments) which will be called or instanciated
 * when it is being used for the first time.
 *
 * @version  1.0
 * @author   Victor Villaverde Laan
 * @link     http://www.freelancephp.net/php-lazy-registry-class/
 * @license  MIT license
 */
class LRegistry {

	/**
	 * Singleton pattern
	 * @var Registry object
	 */
	private static $_instance = NULL;

	/**
	 * Containing all entries
	 * @var array
	 */
	private $_entries = array();

	/**
	 * Default overwrite entries when being set more than once
	 * @var boolean
	 */
	private $_default_overwrite = TRUE;

	/**
	 * Private contructer for singleton protection
	 */
	private final function __construct() {
	}

	/**
	 * Private clone method for singleton protection
	 */
	private final function __clone() {
	}

	/**
	 * Get instance of this class
	 * @return Registry object
	 */
	public static function get_instance() {
		if ( self::$_instance === NULL )
			self::$_instance = new LRegistry;

		return self::$_instance;
	}

	/**
	 * Get value of given key
	 * @param string  $key
	 * @param boolean $reload  reload if class or callback was already loaded
	 * @return mixed
	 */
	public static function get( $key, $reload = FALSE ) {
		$instance = self::get_instance();

		// check if entry exists
		if ( ! key_exists( $key, $instance->_entries ) )
			$instance->_exception( 'Key "' . $key . '" could not be found.' );

		// get current entry
		$entry = $instance->_entries[$key];

		// check if entry should be loaded or reloaded
		if ( ! $entry['loaded'] OR $reload ) {
			if ( $entry['type'] == 'class' ) {
				// get reflection class
				$ref_class = new ReflectionClass( $entry['class'] );
				// create instance
				$entry['value'] = $ref_class->newInstanceArgs( $entry['args'] );
			} else if ( $entry['type'] == 'callback' ) {
				// run callback and set return value
				$entry['value'] = call_user_func_array( $entry['callback'], $entry['args'] );
			} else {
				$instance->_exception( 'Type "' . $type . '" is not supported.' );
			}

			// set (new) value and change "loaded" setting
			$instance->_entries[$key]['value'] = $entry['value'];
			$instance->_entries[$key]['loaded'] = TRUE;
		}

		return $entry['value'];
	}

	/**
	 * Set value of given key
	 * @param string  $key
	 * @param mixed   $value
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	public static function set( $key, $value, $overwrite = NULL ) {
		// set normal value settings
		$settings = array( 'type' => 'value',
							'loaded' => TRUE,
							'value' => $value );

		return self::get_instance()->_set( $key, $settings, $overwrite );
	}

	/**
	 * Set lazy entry of a class. Instance will only be created when entry
	 * is requested using the get method.
	 * @param string  $key
	 * @param string  $class
	 * @param array   $args
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	public static function set_lazy_class( $key, $class, $args = array(), $overwrite = NULL ) {
		// set lazy class settings
		$settings = array( 'type' => 'class',
							'class' => $class,
							'args' => $args,
							'loaded' => FALSE,
							'value' => NULL );

		return self::get_instance()->_set( $key, $settings, $overwrite );
	}

	/**
	 * Set lazy entry of a callback function.Function will only be called when entry
	 * is requested using the get method.
	 * @param string  $key
	 * @param array   $callback
	 * @param array   $args
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	public static function set_lazy_callback( $key, $callback, $args = array(), $overwrite = NULL ) {
		// set lazy callback settings
		$settings = array( 'type' => 'callback',
							'callback' => $callback,
							'args' => $args,
							'loaded' => FALSE,
							'value' => NULL );

		return self::get_instance()->_set( $key, $settings, $overwrite );
	}

	/**
	 * Check if given entry exists
	 * @param string $key
	 * @return boolean
	 */
	public static function has( $key ) {
		return key_exists( $key, self::get_instance()->_entries );
	}

	/**
	 * Check if given (lazy) entry is already loaded
	 * @param string $key
	 * @return boolean
	 */
	public static function is_loaded( $key ) {
		return ( self::has( $key ) AND self::get_instance()->_entries[$key]['loaded'] === TRUE );
	}

	/**
	 * Remove the given entry
	 * @param string $key
	 */
	public static function remove( $key ) {
		if ( ! self::has( $key ) )
			self::get_instance()->_exception( 'Key "' . $key . '"does not exist.' );

		unset( self::get_instance()->_entries[$key] );
	}

	/**
	 * Set default overwriting entries when being set more than once.
	 * @param boolean|NULL $overwrite  optional, if empty can be used as a getter
	 * @return boolean
	 */
	public static function default_overwrite( $overwrite = NULL ) {
		if ( $overwrite !== NULL )
			self::get_instance()->_default_overwrite = (bool) $overwrite;

		return self::get_instance()->_default_overwrite;
	}

	/**
	 * Set value of given key (private use)
	 * @param string  $key
	 * @param mixed   $settings
	 * @param boolean $overwrite  optional, when set will ignore the default overwrite setting
	 * @return boolean  value was set succesfully
	 */
	protected function _set( $key, $settings, $overwrite = NULL ) {
		$instance = self::get_instance();

		// check if overwriting is allowed
		$overwrite = ( $overwrite === NULL )
					? $this->_default_overwrite
					: $overwrite;

		// check if entry exists and overwriting is allowed
		if ( key_exists( $key, $this->_entries ) AND ! $overwrite )
			return FALSE;

		$this->_entries[$key] = $settings;

		return TRUE;
	}

	/**
	 * Throw an exception
	 * @param string $message
	 */
	protected function _exception( $message ) {
		throw new Exception( 'LRegistry: ' . $message );
	}

}

/*?> // ommit closing tag, to prevent unwanted whitespace at the end of the parts generated by the included files */

Initial URL
http://www.freelancephp.net/php-lazy-registry-class/

Initial Description
Managing globals with the registry pattern. This class provides lazy loading functionallity. This means it is possible to add a callback or class (with arguments) which will be called or instanciated when it is being used for the first time.

Initial Title
Lim_Registry – PHP Lazy Registry Class

Initial Tags
class, php

Initial Language
PHP