Posted By

freelancephp on 03/30/10


Tagged

class php register Singleton callback registry static lazy


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

dantreacy


Lim_Registry – PHP Lazy Registry Class


 / Published in: PHP
 

URL: http://www.freelancephp.net/php-lazy-registry-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.

  1. <?php
  2. /**
  3.  * Lim_Registry Class
  4.  *
  5.  * Registry for managing global vars and references with support for lazy loading.
  6.  *
  7.  * @package Registry
  8.  * @version 2.0.0
  9.  * @author Victor Villaverde Laan
  10.  * @link http://www.freelancephp.net/lim_registry-php-lazy-registry-class/
  11.  * @license MIT license
  12.  */
  13. class Lim_Registry {
  14.  
  15. /**
  16. * Default overwrite entries when being set more than once
  17. * @var boolean
  18. */
  19. protected $_defaultOverwrite = true;
  20.  
  21. /**
  22. * Singleton pattern
  23. * @var array
  24. */
  25. private static $_instances = array();
  26.  
  27. /**
  28. * Containing all entries
  29. * @var array
  30. */
  31. protected $_entries = array();
  32.  
  33. /**
  34. * Protected contructor for singleton protection
  35. */
  36. protected final function __construct() {
  37. }
  38.  
  39. /**
  40. * Private clone method for singleton protection
  41. */
  42. private final function __clone() {
  43. }
  44.  
  45. /**
  46. * Get instance of (called) class
  47. * @return Lim_Registry
  48. */
  49. public static function getInstance() {
  50. $class = self::_getClass();
  51.  
  52. if (empty(self::$_instances[$class]))
  53. self::$_instances[$class] = new $class;
  54.  
  55. return self::$_instances[$class];
  56. }
  57.  
  58. /**
  59. * Set default overwriting entries when being set more than once.
  60. * @param boolean $overwrite Optional, else used as a getter
  61. * @return boolean
  62. */
  63. public static function defaultOverwrite($overwrite = null) {
  64. if ($overwrite !== null)
  65. self::getInstance()->_defaultOverwrite = (bool) $overwrite;
  66.  
  67. return self::getInstance()->_defaultOverwrite;
  68. }
  69.  
  70. /**
  71. * Set value of given key
  72. * @param string $key
  73. * @param mixed $value
  74. * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
  75. * @return boolean Value was set succesfully
  76. */
  77. public static function set($key, $value, $overwrite = null) {
  78. $settings = array('type' => 'value', 'loaded' => true, 'value' => $value);
  79. return self::getInstance()->_setEntry($key, $settings, $overwrite);
  80. }
  81.  
  82. /**
  83. * Set value by reference (for arrays)
  84. * @param string $key
  85. * @param mixed $value
  86. * @return boolean Value was set succesfully
  87. */
  88. public static function setByRef($key, & $value) {
  89. $settings = array('type' => 'value', 'loaded' => true, 'value' => & $value);
  90. return self::getInstance()->_setEntry($key, $settings, true);
  91. }
  92.  
  93. /**
  94. * Set lazy entry of a class. Instance will only be created when entry is requested using the get method.
  95. * @param string $key
  96. * @param string $class
  97. * @param array $args
  98. * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
  99. * @return boolean Value was set succesfully
  100. */
  101. public static function setLazyClass($key, $class, $args = array(), $overwrite = null) {
  102. $settings = array('type' => 'class', 'class' => $class, 'args' => $args, 'loaded' => false, 'value' => null);
  103. return self::getInstance()->_setEntry($key, $settings, $overwrite);
  104. }
  105.  
  106. /**
  107. * Set lazy entry of a callback function. Function will only be called when entry is requested using the get method.
  108. * @param string $key
  109. * @param array $callback
  110. * @param array $args
  111. * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
  112. * @return boolean Value was set succesfully
  113. */
  114. public static function setLazyCallback($key, $callback, $args = array(), $overwrite = null) {
  115. $settings = array('type' => 'callback', 'callback' => $callback, 'args' => $args, 'loaded' => false, 'value' => null);
  116. return self::getInstance()->_setEntry($key, $settings, $overwrite);
  117. }
  118.  
  119. /**
  120. * Get value of given key
  121. * @param string $key
  122. * @param boolean $reload Reload if class or callback was already loaded
  123. * @return mixed
  124. * @throw Exception
  125. */
  126. public static function get($key, $reload = false) {
  127. $instance = self::getInstance();
  128.  
  129. // check if entry exists
  130. if (!key_exists($key, $instance->_entries))
  131. self::_throwException('Key "' . $key . '" could not be found.');
  132.  
  133. // get current entry
  134. $entry = $instance->_entries[$key];
  135.  
  136. // check if entry should be loaded or reloaded
  137. if (!$entry['loaded'] || $reload) {
  138. if ($entry['type'] == 'class') {
  139. // get reflection class
  140. $refClass = new ReflectionClass($entry['class']);
  141. // create instance
  142. if (empty($entry['args'])) {
  143. $entry['value'] = $refClass->newInstanceArgs();
  144. } else {
  145. $entry['value'] = $refClass->newInstanceArgs($entry['args']);
  146. }
  147. } else if ($entry['type'] == 'callback') {
  148. // run callback and set return value
  149. $entry['value'] = call_user_func_array($entry['callback'], $entry['args']);
  150. } else {
  151. self::_throwException('Type "' . $type . '" is not supported.');
  152. }
  153.  
  154. // set (new) value and change "loaded" setting
  155. $instance->_entries[$key]['value'] = $entry['value'];
  156. $instance->_entries[$key]['loaded'] = true;
  157. }
  158.  
  159. return $entry['value'];
  160. }
  161.  
  162. /**
  163. * Get value by reference (for arrays)
  164. * @param string $key
  165. * @return mixed By reference
  166. */
  167. public static function & getByRef($key) {
  168. $instance = self::getInstance();
  169.  
  170. // check if entry exists
  171. if (!key_exists($key, $instance->_entries))
  172. self::_throwException('Key "' . $key . '" could not be found.');
  173.  
  174. // get current entry
  175. $entry = $instance->_entries[$key];
  176.  
  177. return $entry['value'];
  178. }
  179.  
  180. /**
  181. * Check if given entry exists
  182. * @param string $key
  183. * @return boolean
  184. */
  185. public static function has($key) {
  186. return key_exists($key, self::getInstance()->_entries);
  187. }
  188.  
  189. /**
  190. * Check if given (lazy) entry is already loaded
  191. * @param string $key
  192. * @return boolean
  193. */
  194. public static function isLoaded($key) {
  195. return (self::has($key) && self::getInstance()->_entries[$key]['loaded'] === true);
  196. }
  197.  
  198. /**
  199. * Remove the given entry
  200. * @param string $key
  201. * @throw Exception
  202. */
  203. public static function remove($key) {
  204. if (!self::has($key))
  205. self::_throwException('Key "' . $key . '" does not exist.');
  206.  
  207. unset(self::getInstance()->_entries[$key]);
  208. }
  209.  
  210. /**
  211. * Remove all entries
  212. */
  213. public static function clear() {
  214. $keys = array_keys(self::getInstance()->_entries);
  215.  
  216. foreach ($keys as $key)
  217. self::remove($key);
  218. }
  219.  
  220. /**
  221. * Set value of given key
  222. * @param string $key
  223. * @param mixed $settings
  224. * @param boolean $overwrite Optional, when set will ignore the default overwrite setting
  225. * @return boolean Value was set succesfully
  226. */
  227. protected function _setEntry($key, $settings, $overwrite = null) {
  228. // check if overwriting is allowed
  229. $overwrite = ($overwrite === null) ? $this->_defaultOverwrite : $overwrite;
  230.  
  231. // check if entry exists and overwriting is allowed
  232. if (key_exists($key, $this->_entries) && !$overwrite)
  233. return false;
  234.  
  235. $this->_entries[$key] = $settings;
  236.  
  237. return true;
  238. }
  239.  
  240. /**
  241. * Throw exception
  242. * @param string $msg
  243. * @throw Exception
  244. */
  245. protected static function _throwException($msg) {
  246. throw new Exception(self::_getClass() . ' - ' . $msg);
  247. }
  248.  
  249. /**
  250. * get_called_class() equivalent also support for PHP < 5.3.
  251. * @return string
  252. */
  253. protected static function _getClass() {
  254. if (function_exists('get_called_class'))
  255. return get_called_class();
  256.  
  257. $class = __CLASS__;
  258.  
  259. try {
  260. $bt = debug_backtrace();
  261. $l = 0;
  262.  
  263. do {
  264. $l++;
  265. $lines = file($bt[$l]['file']);
  266. $callerLine = $lines[$bt[$l]['line']-1];
  267. preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/', $callerLine, $matches);
  268. } while ($matches[1] === 'parent' && $matches[1]);
  269.  
  270. if (class_exists($matches[1]))
  271. $class = $matches[1];
  272. } catch (Exception $e) {
  273. }
  274.  
  275. return $class;
  276. }
  277.  
  278. } // Lim_Registry

Report this snippet  

You need to login to post a comment.