Registry Design Pattern with Lazy Load

The registry design pattern is a great way to store info throughout your application. But certain information isn't necessary on each request - and you don't always know when you will need it. We've taken the basic registry design pattern and added lazy load capabilities to give you optimum performance and save resources.

Example

Let's say you are storing application info in your registry. This info is needed often, and is populated with a database call. But there are many requests where this information is not needed. The solution is to lazy-load the info into your registry so it is always available when you need it, but never using resources when you don't.

Before:

  1. <?php
  2. $q = Your_Registry::get('dbh')->query('select * from infoTable');
  3. $info = new stdClass;
  4. while ($r = $q->fetch()) {
  5. $info->name = $r['name'];
  6. $info->foo = $r['foo'];
  7. }
  8. /* Save in Registry */
  9. Your_Registry::set('info', $info);
  10. /* Elsewhere in your code to access info... */
  11. echo Your_Registry::get('info')->name;
  12. ?>

Although this wasn't a complex query, it will hit your database server unnecessarily on requests where you don't need access to this info. Using our modified registry pattern with lazy load and closures (anonymous functions), we can improve performance.

After:

Let's store this process inside of a closure, and pass it as an argument to our lazyLoad() method along with the registry key we want to associate it with - in this case, info.

  1. <?php
  2. Your_Registry::lazyLoad('info',
  3. function() {
  4. $q = Your_Registry::get('dbh')->query('select * from infoTable');
  5. $info = new stdClass;
  6. while ($r = $q->fetch()) {
  7. $info->name = $r['name'];
  8. $info->foo = $r['foo'];
  9. }
  10. /* Save in Registry. This needs to be within our closure */
  11. Your_Registry::set('info', $info);
  12. }
  13. );
  14. ?>

Now when get('info') is called, if that key does not exist in our registry store, the class will check to see if we have associated a lazy load function with that key. If so, it will execute the function (which saves to the registry), then give us the information. It will also erase the lazy load after executing, and future requests for this data within the same script execution will be pulled directly out of the registry store.

Note: If you aren't running PHP >= 5.3, you will not be able to use closures and will instead need to use create_function(). You can also create a regular function, and pass in the function name as a string, then use call_user_func() within the get() method to execute the function.

Download

Here is the modified registry pattern with lazy loading added.

  1. <?php
  2. class Your_Registry
  3. {
  4. /**
  5. * Hold our object
  6. *
  7. * @var Your_Registry
  8. **/
  9. protected static $_instance = null;
  10. /**
  11. * The actual registry store
  12. *
  13. * @var array
  14. */
  15. protected $_store = array();
  16. /**
  17. * A store of closures (functions) that correspond to registry keys.
  18. * Allows the class to lazy load only if needed
  19. *
  20. * @var array
  21. */
  22. protected $_lazyLoad = array();
  23. /**
  24. * Enforce our singleton
  25. *
  26. **/
  27. private function __construct() {}
  28. /**
  29. * Get the object instance
  30. *
  31. * @return Your_Registry
  32. **/
  33. public static function getInstance()
  34. {
  35. if (is_null(self::$_instance)) {
  36. self::$_instance = new self;
  37. }
  38. return self::$_instance;
  39. }
  40. /**
  41. * Assign a closure with a registry key to be lazy-loaded
  42. *
  43. * @param string $key the key or identifier
  44. * @param closure the function to execute when the key is requested for the first time
  45. **/
  46. public static function lazyLoad($key, $func)
  47. {
  48. self::getInstance()->_lazyLoad[$key] = $func;
  49. }
  50. /**
  51. * Remove an item from the registry store
  52. *
  53. * @param string the key to remove
  54. * @return void
  55. **/
  56. public static function remove($key)
  57. {
  58. $instance = self::getInstance();
  59. if (self::isRegistered($key)) {
  60. unset($instance->_store[$key]);
  61. }
  62. }
  63. /**
  64. * Retrieves a value from the registry based on a key
  65. *
  66. * @param string $key the name of the item to retrieve
  67. * @return mixed
  68. */
  69. public static function get($key)
  70. {
  71. $instance = self::getInstance();
  72. if (isset($instance->_store[$key])) {
  73. return $instance->_store[$key];
  74. }
  75. /* Check for lazy load */
  76. if (isset($instance->_lazyLoad[$key])) {
  77. /* No need to assign value - the function sets the registry value */
  78. $instance->_lazyLoad[$key]();
  79. unset($instance->_lazyLoad[$key]);
  80. return $instance->_store[$key];
  81. }
  82. return false;
  83. }
  84. /**
  85. * Stores a key/value pair in the registry
  86. *
  87. * @param string $key the name of the item we are storing
  88. * @param mixed $value
  89. */
  90. public static function set($key, $value)
  91. {
  92. self::getInstance()->_store[$key] = $value;
  93. }
  94. /**
  95. * Checks to see if the key is currently stored in the registry
  96. *
  97. * @param string $key the name of the item to check
  98. * @return bool
  99. */
  100. public static function isRegistered($key)
  101. {
  102. return isset(self::getInstance()->_store[$key]);
  103. }
  104. /**
  105. * Enforce our singleton
  106. *
  107. * @throws Exception
  108. */
  109. public function __clone()
  110. {
  111. throw new Exception('Cannot clone ' . __CLASS__ . ' class');
  112. }
  113. }
  114. ?>

Comments

Let us know what you think!

 

We've taken a chore and made it enjoyable

Our customers tell us that they actually enjoy updating their websites with Compass. Find out why. Schedule a one-on-one, no-obligation demo to see Compass in action.

Small to Midsize Businesses • Non-Profits • Organizations • Professional Service Firms

Testimonial CFO Selections

Tom Varga
Managing Partner, CFO Selections

    "Compass is a must have application for any business. It's brilliantly crafted and significantly
                  better then what has been previously available on the market to manage your website."

Hosted Web Content Management System CMS

We offer a fully managed Software as a Service (SaaS) solution that lets you focus on running a great website - not managing servers and software code. Learn More

Our Usability Principles

Compass CMS is built around the principle that software should be easy to use. Here's what that means to us. Learn More

Sign up for our WCM email newsletter

Our email newsletter contains information on web content management (WCM), usability, website best practices, SaaS, and other free resources.

Powered By Compass