Segregated interfaces aren't anything new in PHP. Simply put,a segregated interface is a regular interface whose contract provides implementers with the functionality to perform one or more specific tasks. In this second part of a series, we will be using them to create a registry system.
Since the segregated interfaces created before establish a clearly-defined group of contracts, building a couple of implementers of them, capable of saving/fetching/dumping elements from different storage mechanisms is a simple process. Take a look at the following class, which is a basic array-based registry:
(ArrayRegistry.php)
<?php
class ArrayRegistry implements RegistrableInterface, DumpableInterface { protected $_data = array();
/** * Save the specified value to the array registry */ public function set($key, $value) { $this->_data[strtolower($key)] = $value; }
/** * Get the specified value from the array registry */ public function get($key) { $key = strtolower($key); return isset($this->_data[$key]) ? $this->_data[$key] : null; }
/** * Dump the whole array registry */ public function dump() { ob_start(); var_dump($this->_data); return ob_get_clean(); }
/** * Clear the array registry */ public function clear() { $this->_data = array(); } }
Effectively, the above “ArrayRegistry” class implements the previous segregated interfaces, something that gives it the ability for storing and retrieving data from a protected array, and even for dumping the whole registry. Leaving apart its simplicity, the beauty of this class is that its functionality has been achieved by agreeing two different, highly-granular contracts.
Having defined the first registry back-end, it’s time to show the one that uses internally PHP sessions. Here it is:
(SessionRegistry.php)
<?php
class SessionRegistry implements RegistrableInterface, DumpableInterface { /** * Constructor */ public function __construct() { session_start(); }
/** * Save the specified value to the session registry */ public function set($key, $value) { $_SESSION[strtolower($key)] = $value; }
/** * Get the specified value from the session registry */ public function get($key) { $key = strtolower($key); return isset($_SESSION[$key]) ? $_SESSION[$key] : null; }
/** * Dump the whole session registry */ public function dump() { ob_start(); var_dump($_SESSION); return ob_get_clean(); }
/** * Destroy the session */ public function clear() { session_start(); $_SESSION = array(); session_destroy(); } }
The logic implemented by the prior “SessionRegistry” class closely resembles the one of its counterpart “ArrayRegistry”, with a few subtle exceptions, of course. The former is a simple wrapper for the $_SESSION superglobal PHP array, something that lets it store, fetch and dump session data in a pretty straightforward fashion. Again, it’s worth to stress how this class implements the earlier segregated interfaces, in order to perform the aforementioned tasks.
So far, so good. With the two previous registry classes coexisting happily side-by-side, it’s easy to create an adapter capable of asking for them (or for any other registry back-end) in the constructor. The following class does exactly that:
(DataHandler.php)
<?php
class DataHandler { protected $_registry;
/** * Class constructor */ public function __construct(RegistrableInterface $registry) { $this->_registry = $registry; }
/** * Save data to the registry */ public function set($key, $value) { $this->_registry->set($key, $value); return $this; }
/** * Get data from the registry */ public function get($key) { return $this->_registry->get($key); }
/** * Clear the registry */ public function clear() { $this->_registry->clear(); } }
Even when this new adapter class is a rather simple structure, it’s clearly a winner one! On one hand, its uses transparently the “Plug-in” pattern (http://www.devshed.com/c/a/PHP/The-PHP-Plugin-Pattern/), which provides it with the ability for switching different registry back-ends at construction time, while on the other one, the collaborator that it asks for in the constructor is actually a segregated interface, thus sticking to the commandment “Coding to an interface, not an implementation” that you’ve probably heard hundreds of times before.
And now that you grasped how the use of segregated interfaces can be of great help in the construction of a flexible, expandable registry system, the only thing that remains undone is to set up a couple of scripts that show how to utilize the system in a useful manner.