Home arrow PHP arrow Page 2 - Building a Service Locator in PHP

Implementing a basic service locator - PHP

In this first part of a series, I introduce you to the key concepts that surround the definition of a service locator. I'll also show you how to use this approach in the development of a basic registry library.

TABLE OF CONTENTS:
  1. Building a Service Locator in PHP
  2. Implementing a basic service locator
By: Alejandro Gervasio
Rating: starstarstarstarstar / 4
February 14, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

In order to make the previous "Registry" class get its dependency via a service locator, it's necessary to introduce two changes into the whole registry library. The first one, logically, is to define the service locator (or a registry locator, to be more precise) and the second one is ... yes, to modify the class itself.

Since the definitions corresponding to the "Registrable" interface and its implementer "ArrayRegistry" will remain exactly the same, I'm not going to list them again, to keep the sample codes uncluttered.

With that said, here's the implementation of the service locator, which not surprisingly is called "RegistryLocator": 

(Registry/RegistryLocator.php)

<?php

namespace Registry;

class RegistryLocator
{
    /**
     * Private constructor
     */
    private function __construct(){}
     
    /**
     * Get the array registry
     */
    public static function getArrayRegistry()
    {
        return new ArrayRegistry;
    } 
}

That was easy to code and read, wasn't it? As seen above, this service locator is nothing but a static factory that spawns instances of the "ArrayRegistry" class and returns them to client code via its "getArrayRegistry()" method. Nothing less, nothing more.

With this service locator already defined, the last step is to tweak the source code of the "Registry" client class, so it can obtain its dependency through the locator. Here's the amended version of this class:  

(Registry/Registry.php)

<?php

namespace Registry;

class Registry
{  
    protected $_registryBackend;
   
    public function __construct()
    {
        $this->_registryBackend = RegistryLocator::getArrayRegistry();
    }
    
    /**
     * Save the specified element to the registry
     */
    public function set($key, $value)
    {
        $this->_registryBackend->set($key, $value);
        return $this;
    }

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

There you have it. Now the above client class fetches its dependency (in this case a single object, but it might be multiple ones) by calling the static factory method of the service locator. Of course, if you're anything like me at this point, some alarm bells should be ringing off in your head. But why?

First off, the class is no longer capable of working with multiple registry back-ends, unless a new factory method is added to the locator. And last but not least, testing it is much harder.

Aside from demonstrating how to implement a simple service locator in PHP, this trivial example also shows the pros and cons of using this approach. On one hand, the class using the locator effectively hides from the outside how it obtains its dependency; on the other one, though, it sacrifices flexibility and testability. That's why in many cases a service locator is considered a degradation of dependency injection.

But before you express your own judgment, first it's necessary to create an example that puts the registry locator to work, so you can see if it really functions as intended.

This will be done in the following segment. So go ahead and read the next few lines. 

The service locator in action

As I stated previously, below I coded an example that demonstrates how to use the "Registry" class, now that it gets its dependency through the array locator. Take a look at the following code fragment:

<?php

// example using a service locator
use RegistryRegistry as Registry;

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

// create an instance of the registry and save some data in it
$registry = new Registry;
$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 rather contrived, this example shows pretty clearly the impact produced by the implementation of the previous service locator. Effectively, once an instance of the "Registry" class is created, it's used to store and retrieve some data from the array registry, even though this dependency has been provided "behind the scenes."

This is in fact a double-edged sword: from the client code's point of view, using the registry is slightly simpler, as there's no need to perform any constructor or setter dependency injection. However, from a programmer's standpoint, testing the registry and even figuring out how the registry gets its dependency is definitely more difficult.

In my opinion, dependency injection is the way to go when building object graphs. This doesn't mean, however, that a service locator should be abandoned in a dark, isolated corner and condemned for its evil actions. As I said before, there's a number of cases where it can be useful, particularly when combined when inversion of control.

But I'm getting ahead of myself, since that is the topic that I plan to cover in the next installment.  

Final thoughts

In this first chapter of the series, I provided you with a humble introduction to the key concepts that surround the definition of a service locator, and also showed you how to use this approach during the development of a basic registry library. As you just saw, there are some serious drawbacks that make a service locator more inefficient than dependency injection, especially when it comes to constructing testable object graphs.

It's possible, though, to combine the best of both worlds and inject a service locator. This method is quite interesting, and deserves deep analysis. Therefore, in the upcoming tutorial I'm going to modify some of the source classes that comprise the earlier registry library, so it can use an injected registry locator.

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: