Home arrow PHP arrow Page 2 - Dependency Injection and Service Locators in PHP

Modifying the library by injecting the registry locator - PHP

In this second tutorial of the series, I show how the combined functionality provided by dependency injection and a service locator can be quite helpful in the construction of testable object graphs.

TABLE OF CONTENTS:
  1. Dependency Injection and Service Locators in PHP
  2. Modifying the library by injecting the registry locator
By: Alejandro Gervasio
Rating: starstarstarstarstar / 3
February 15, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Merging the functionality provided by dependency injection with that given by a service locator is a  straightforward, easy-to-understand process. Since I want to demonstrate how to use this approach with the earlier registry library, the first thing I must change is the definition of the registry locator, which needs to be injectable. 

To make this change, the locator's originating class must no longer be a static factory, but a dynamic one instead. The following code sample clearly reflects this modification:

(Registry/RegistryLocator.php)   

<?php

namespace Registry;

class RegistryLocator
{
    /**
     * Get the array registry
     */
    public function getArrayRegistry()
    {
        return new ArrayRegistry;
    } 
}

Done. Now that the "RegistryLocator" class can be instantiated, the next step is to make the client registry ask for the locator in its constructor. Again, the following snippet accomplishes this goal:

(Registry/Registry.php)

<?php

namespace Registry;

class Registry
{  
    protected $_registryLocator;
    protected $_registryBackend;
   
    /**
     * Constructor
     */
    public function __construct(RegistryLocator $registryLocator)
    {
        $this->_registryLocator = $registryLocator;
    }
   
     /**
     * Get the registry backend
     */
    public function getRegistryBackend()
    {
        if ($this->_registryBackend === null) {
            $this->_registryBackend = $this->_registryLocator->getArrayRegistry();
        }
        return $this->_registryBackend;
    }
     
    /**
     * Save the specified element to the registry
     */
    public function set($key, $value)
    {
        $this->getRegistryBackend()->set($key, $value);
        return $this;
    }

    /**
     * Get the specified element from the registry
     */
    public function get($key)
    {
        return $this->getRegistryBackend()->get($key);
    }
   
    /**
     * Clear the registry
     */
    public function clear()
    {
        $this->getRegistryBackend()->clear();
    }         
}

That looks much better, doesn't it? As you can see, now the client registry class accepts, through its constructor, an instance of the locator, which is stored as a protected property. This simple change demonstrates that injecting a service locator is in fact much simpler than one might think. Plus, there's an additional benefit to using this approach: now it's perfectly possible to replace the locator with a mock-up, which makes testing the client registry a breeze.

Unfortunately, an injected locator also has its own drawbacks. If the client registry needs to use a different registry backend, the only way to achieve this is to add a new factory method to the locator and call it explicitly. This isn't very flexible.

However, in those cases where collaborators of a client have a shorter life cycle than the client itself, injecting locators that are concrete factories, responsible for spawning only a single dependency, makes a lot of sense.

Well, having clarified those concepts, we still need to test the improved version of the registry library, once the previous changes have been properly implemented.

This will be done below, so keep reading. 

A final example

As I promised above, here's a concrete example that shows how to work with the enhanced registry library, now that it uses an injected service locator:

<?php

// example injecting a service locator
use RegistryRegistry as Registry,
    RegistryRegistryLocator as RegistryLocator;

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

// create an instance of the registry and save some data in it
$registry = new Registry(new RegistryLocator);
$registry->set('name', 'Mary Wilson')
         ->set('email', 'mary@domain.com');

// get the data from the registry
echo 'Name: ' . $registry->get('name') . ' Email: ' . $registry->get('email');

Although the above script does nothing spectacular, other than saving and retrieving some information about our fictional user, Mary Wilson, it does demonstrate how the functionality of dependency injection and service locators working together can help to write classes that are easier to test in isolation.

Naturally, if you've developed applications composed of a large number of object graphs, much more complex than the one above, dependency injection on its own is, in my opinion, the best approach. However, in relatively simple use cases, an injected locator may fit your needs.   

Closing thoughts

In this second tutorial of the series, I attempted to show how the combined functionality provided by dependency injection and a service locator can be quite helpful in the construction of testable object graphs.

While the example that you just learned was pretty illustrative, it would be desirable to set up one that resembles a more realistic use case. Thus, in the next part I'm going to show you how to implement a service locator in the construction of a simple blog application.

Don't miss the next part!



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: