In an earlier article I described how to start moving away from singletons in favor of dependency injection. It occurs to me that the process for moving away from Service Locator is almost exactly the same, except that we use the container outside the class instead of inside it.

Let's say we have a class that uses a Service Locator. First we examine the class for all uses of the locator. Then, we create constructor parameters for the dependencies it extracts from the locator, and add setter code for those dependencies in the constructor body. For example, we can convert the above Service Locator example classes to these dependency-injected variations:

<?php
class FooClass
{
    protected $db;
    public function __construct(Database $db)
    {
        $this->db = $db;
    }
}

class BarClass
{
    protected $db;
    public function __construct(Database $db)
    {
        $this->db = $db;
    }
}
?>

Finally, any time we instantiate one of these dependency-injected classes, we use the locator outside the class to retrieve the dependencies. We then pass them to the new call for the class. For example:

<?php
// for FooClass
$db = $container->get('db');
$foo = new FooClass($db);

// for BarClass
$db = StaticContainer::get('db');
$bar = new BarClass($db);
?>

Now the class dependencies are explicit and predictable, instead of implicit and unpredictable (i.e., the class might depend on any combination of dependencies hidden inside the container). It is also somewhat easier to build a test, since we only have to build the dependencies themselves, not the container that holds the dependencies.

Afterword

Are you overwhelmed by a legacy PHP application? Have you inherited a spaghetti mess of code? Does it use globals everywhere, so that a fix in one place causes a bug somewhere else? Does every feature addition feel like slogging through a swamp of includes?

It doesn’t have to be that way. "Modernizing Legacy Applications in PHP" gives you step-by-step instructions on how to get your legacy code under control by eliminating globals and separating concerns. Each chapter shows you exactly one task and how to accomplish it, along with common questions related to that task.

When you are done, you will come and go through your code like the wind. Your application will have become autoloaded, dependency injected, unit tested, layer separated, and front controlled. And you will have kept it running the whole time.

Buy the book today!


Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving you codebase, all while keeping it running the whole time.