Dynamic Registry in PHP

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.

Segregating a monolithic interface in a set of more granulated contracts permits us to build classes that stick more efficiently to the “separation of concerns” paradigm, and additionally makes it easy to develop applications that can be easily extended by means of Composition, rather than with Inheritance.

To demonstrate how to utilize segregated interfaces, in the introductory installment of this series I developed a typical array collection class, which utilized three segregated interfaces (namely the native ones Countable, Iterator and ArrayAccess) in order to implement a structure capable of traversing arrays, as well as counting and manipulating their elements.

Segregated interfaces can be used in many scenarios and situations, apart from the one mentioned above. In this second tutorial of the series I’m going to show you how to utilize a pair of custom segregated interface in the construction of a flexible registry system. Thanks to the utilization of these interfaces along with the “Plug-in” pattern, the registry will have the ability to store/fetch/remove elements through plain arrays and via PHP sessions as well.

Taking the first step: creating a couple of segregated interfaces

I’m going to develop a simple –yet functional- dynamic registry, pretty similar to the one that I created here (http://www.devshed.com/c/a/PHP/Building-a-service-Locator-in-PHP/). As stated in the introduction, though, there will be a subtle difference, as client code consuming the registry will be able to swap between an array-based registry and one that uses PHP sessions.

(RegistrableInterface.php)

<?php

interface RegistrableInterface
{
    public function set($key, $value);
   
    public function get($key);
   
    public function clear();
}


If I had to say something about the above “RegistrableInterface” interface, it would be that the contract that it defines is a very narrowed one. After all, it only declares three methods which, when concretely implemented, will allow us to save, retrieve and clear data in a storage/registry system. But why should it be more generous, if this is only the functionality that its implementers will need?

Now, since I want the different registry classes to dump the store data, I’m going to define a separate contract for performing this task. This contract, not surprisingly is established by another segregated interface called “DumpableInterface” (sorry for the name, seriously). Here it is:

(DumpableInterface.php)

<?php

interface DumpableInterface
{
    public function dump(); 
}


Due to its simplicity, I think that this new interface doesn’t bear any further analysis. It’s worth noting, however, that at this point I managed to create a flexible API, thanks to the existence of a couple of segregated interfaces.

So, with the previous contracts properly defined, the next thing that must be done is to define the classes implementing the pertinent interfaces, which will handle data using different back-ends.  

{mospagebreak title=Implementing PHP Segregated Interfaces}

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.

{mospagebreak title=Using PHP Registry Classes}

To demonstrate how to put to work in conjunction all the source classes and interfaces developed so far, I’m going to appeal to the functionality of basic autoloader. This class is very similar to others shown in previous articles published here at the Developer Shed network, so feel free to skip over its definition if you want to. For the sake of completeness, here’s how this autoloader looks:

(Autoloader.php)

<?php

class Autoloader
{
    private static $_instance;
   
    /**
     * Get the Singleton instance of the autoloader
     */
    public static function getInstance()
    {
        if (self::$_instance === null) {
            self::$_instance = new self;
        }
        return self::$_instance;
    } 
   
    /**
     * Reset the instance of the autoloader
     */
    public static function resetInstance()
    {
        self::$_instance = null;
    }
   
    /**
     * Constructor
     */
    private function __construct()
    {
        spl_autoload_register(array(__CLASS__, 'load'));
    }
   
    /**
     * Prevent to clone the instance of the autoloader
     */
    private function __clone(){}
   
    /**
     * Load a given class or interface
     */
    public static function load($class)
    {
        $file = $class . '.php';
        if (!file_exists($file)) {
            throw new OutOfBoundsException('The file ' . $file . ' containing the requested class or interface ' . $class . ' was not found.');
        }
        require $file;
        if (!class_exists($class, false) && !interface_exists($class, false)) {
            throw new OutOfBoundsException('The requested class or interface ' . $class . ' was not found.');
        }
    }  
}


Certainly, understanding how the above autoloader works is an easy-to-grasp process, so move on and take a peek at the following script, which demonstrates how to save and fetch some trivial data using the earlier array-based registry:

<?php

// example using the ArrayRegistry class

// include the autoloader
require_once 'Autoloader.php';
Autoloader::getInstance();

// create an instance of the data handler
$dataHandler = new DataHandler(new ArrayRegistry);

// set some data into the data handler
$dataHandler->set('fname', 'Alex')
            ->set('lname', 'Gervasio')
            ->set('email', 'alex@domain.com');

// get some data from the data handler
echo ' First Name: ' . $dataHandler->get('fname') .
     ' Last Name: ' . $dataHandler->get('lname') .
     ' Email: ' . $dataHandler->get('email');

This example is indeed pretty basic; it shows how convenient it is to combine the power of dependency injection with the use of segregated interfaces. But, if the pertaining example doesn’t fulfill your expectations yet, pay attention to the following one, which performs the same saving/fetching process but this time by means of the session-based registry:

<?php

// example using the SessionRegistry class

// include the autoloader
require_once 'Autoloader.php';
Autoloader::getInstance();

// create an instance of the data handler
$dataHandler = new DataHandler(new SessionRegistry);

// set some data into the data handler
$dataHandler->set('fname', 'Alex')
            ->set('lname', 'Gervasio')
            ->set('email', 'alex@domain.com');

// get some data from the data handler
echo ' First Name: ' . $dataHandler->get('fname') .
     ' Last Name: ' . $dataHandler->get('lname') .
     ' Email: ' . $dataHandler->get('email');

There you have it. As the earlier code fragment shows, swapping between different registry back-ends is pretty much like replacing a Lego block by another. Plus, thanks to the transparent use of the previous segregated interfaces, each back-end implements only the functionality required to perform the tasks it’s responsible for.

Finally, feel free to tweak all the code samples shown before, something that will let you acquire a better background on segregated interfaces, so you can take advantage of them during the development of your own object-oriented applications.    

Final thoughts

Over this second part of the series, I went through the development of a basic registry system, whose respective back-ends used a few custom segregated interfaces to implement the functionality that they needed to perform their corresponding tasks. However simple, this example showed a pretty realistic use case, where the definition of some segregated interfaces made easy to establish the “appropriate” contracts for a set of related classes.

Needless to say that a segregated interface can be utilized in all sort of use cases, others than the one previously discussed. With that concept in mind, in the upcoming tutorial I’m going to demonstrate how to construct a flexible caching system, whose internal classes will made use, not surprisingly, of a user-defined segregated interface as well.

As usual, don’t miss the next part! 

 

 

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan