Dependency Injection Containers
Although the previous example is a significant improvement, it still requires the implementer to know something about the instantiation requirements, including the fact that the Account
class requires a construction parameter containing a database handler in the first place. Presuming accounts are managed throughout your application, this will require you to consistently instantiate the mysql
class ahead of the Account
class, thereby creating a higher-level dependency that although not embedded in the class, is nonetheless embedded throughout the application. Recognizing this drawback, you’ll commonly encounter the use of a dependency container in dependency injection implementations. A dependency container is merely an object that happens to know all about the dependency requirements of other objects, thereby allowing you to invoke the dependent object’s container rather than the dependent object itself. Consider this example:
class Container {
... host, user, pswd, db, port pulled in via registry or similar
private function getDatabase() {
return new mysqli($this->_host, $this->_user,
$this->_pswd, $this->_db, $this->_port);
}
public function createAccount() {
$account = new Account($this->getDatabase());
}
}
$container = new Container();
$account = $container->createAccount();
This approach is particularly useful when you need to resolve multiple class dependencies, because you’ll be able to encapsulate three, four, five, or more dependencies into the container, allowing you to simply call the createAccount()
method.
Because dependency management can quickly become a complex matter, a great deal of work has been put into general purpose dependency injection containers. Part of the Symfony project, the Symfony Dependency Injection library is often cited as the gold standard within the PHP community, and is certainly worth a look if you plan on making DI part of your standard toolbox. I also suggest checking out the rather oddly-named Pimple, a PHP 5.3-specific dependency injection container that also happens to be written by the Symfony project leader Fabien Potencier.
Further Reading
Dependency injection has been discussed at great length within many programming communities, with Martin Fowler offering a lengthy dissertation on the matter some years ago. I also suggest learning more about DI solutions available within other languages, notably Java (see Guice and Spring for two notable implementations).