How can I use "Dependency Injection" in simple php functions, and should I bother?

Viewed 28680

I hear people talking about dependency injection and the benefit of it all the time, but I don't really understand it.

I'm wondering if it's a solution to the "I pass database connections as arguments all the time" problem.

I tried reading wikipedia's entry on it, but the example is written in Java so I don't solidly understand the difference it is trying to make clear. ( http://en.wikipedia.org/wiki/Dependency_injection ).

I read this dependency-injection-in-php article ( http://www.potstuck.com/2009/01/08/php-dependency-injection/ ), and it seems like the objective is to not pass dependencies to an object directly, but to cordon off the creation of an object along with the creation of it's dependencies. I'm not sure how to apply that in a using php functions context, though.

Additionally, is the following Dependency Injection, and should I bother trying to do dependency injection in a functional context?

Version 1: (the kind of code that I create, but don't like, every day)

function get_data_from_database($database_connection){
    $data = $database_connection->query('blah');
    return $data;
}

Version 2: (don't have to pass a database connection, but perhaps not dependency injection?)

function get_database_connection(){
    static $db_connection;
    if($db_connection){
        return $db_connection;
    } else {
        // create db_connection
      ...
    }
}

function get_data_from_database(){
   $conn = get_database_connection();
   $data = $conn->query('blah');
   return $data;
}

$data = get_data_from_database();

Version 3: (the creation of the "object"/data is separate, and the database code is still, so perhaps this would count as dependency injection?)

function factory_of_data_set(){
    static $db_connection;
    $data_set = null;
    $db_connection = get_database_connection();
    $data_set = $db_connection->query('blah');
    return $data_set;
}

$data = factory_of_data_set();

Anyone have a good resource or just insight that makes the method and benefit -crystal- clear?

5 Answers

None of your examples look like dependency injection, version one is the closest though. Dependency injection is a technique used in object oriented programming, where the constructor of an object has arguments for the service objects it needs, and those service objects are passed in by the creator of the instance (which could be a factory, a test, or a dependency injection framework).

To get around your 'always passing the connection object' problem you may want to consider the template pattern. The template pattern is basically an abstract base class with the common part of a repeated code block, and abstract methods to allow for the variation between the instances of those repeated code blocks. Basically the base is a template of a block of code, and the abstract methods are the blanks to be filled in. I personally use the template method pattern to do my database resource control in Java.

I have done much searching on this topic myself (PHP Dependency Injection) and haven't found much to my liking. A lot has been written on the subject for other languages (Google Guice - http://code.google.com/p/google-guice/ ; Java Spring), but I couldn't find much available for PHP. Regardless of the language, however, the challenges are similar.

The three versions you list in your question are the typical approach. Version 3 is the closest to the direction in which I have seen the industry going. By shifting the responsibility of creating your dependent objects outside of your class, you are free to manipulate them as you please in your test code. However, the problem that I encountered with that approach is that you end up with long chains of dependent objects in your constructor that can potentially not even be used by the receiving object, but get passed through to an secondary dependent object. It gets messy and you lose knowledge of what is coming from where.

The Dependency Container example by @Arkh and @mmmshuddup is a great start, but I nonetheless found limitations with that approach as well. The final solution upon which I arrived was a custom built solution modeled somewhat after the Cake Pattern popular in Scala. It allows you to pass a single dependency into each of your constructors AND it lets you define the default construction of the dependent objects per class. This frees you from long dependency chains as well as losing control of the default implementations of your dependencies.

I called the system Diesel and I've been really happy with it. I published the code on github for anyone interested. You can get to it from the blog I wrote on the subject, which describes the basic usage as well as goes into more detail on your question. http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/

Related