Dependency Injection

It seems like very PHP ZF2 blog has an article about Dependency Injection, so here's mine. I hope it's clear, or at least helps corroborate what you're reading on other sites.

What is a Dependency?

A dependency is what you have when one class or object needs to call another class or object.

Suppose you have two classes, Formatter and Lister. Formatter formats the data that Lister returns. Formatter is dependent on Lister. Here's what formatter might look like:

class Formatter {

  function __construct( $config ) {
     $this->lister = new Lister( $config['pointer'] );
  }
  
  function toString() {
     $o = '';
     while( $line = $this->lister->next() ) {
       $o .= "$line\n";
     }
     return $o;
  }
}

And, for this discussion, let's say that Lister implements the Iterator interface.

class Lister implements Iterator { ... }

Now, suppose you're being real clever, and think "I can swap out Lister with something else, like DirectoryLister.

class Formatter {

  function __construct( $config ) {
     $this->lister = new DirectoryLister( $config['dir'] );
  }
...

Heh heh. Yeah. Nice, except you rewrote the definition of Formatter. Now you can watch all the objects using Formatter to act weird.

Obviously, you want to do something like this, where you can swap in a different kind of lister, and Formatter now works with anything that implements the Iterator interface:

class Formatter {

  function __construct( $lister ) {
     $this->lister = $lister;
  }
...more code...
}
// and then in some other part of the program.
$l = new Lister( $config['pointer'] );
$f = new Formatter( $l );
...

It adds an extra line of code, but you get a lot of flexibility and reusability.

What that last example demonstrated was Dependency Injection. The dependency was the Lister. The Lister, $l, was injected into the Formatter.

3 types of Injection

The first example was of Constructor Injection. There are two other forms: Setter Injection and Interface Injection.

I don't really get Interface Injection. See Interface Injection at Martin Fowler's site. It's kind of odd, I'll have to read it again.

The Setter Injection pattern is simple. The new code is.

    function setLister( $lister ) {
        $this->lister = $lister;
    }

If you use setter injection, your code looks more like this:

class Formatter {

  function __construct() {
  }
...more code...
}
// and then in some other part of the program.
$l = new Lister( $config['pointer'] );
$f = new Formatter();
$f->setLister( $l );
...

Hey, that last line is new!

So, "DI" is really pretty simple. It's just a name for a pattern we have all used.

Next: DI in Zend Framework 2.