Can’t Imagine Life without Dependency Injection – Part One

Tweet about this on TwitterShare on LinkedInShare on Google+Share on FacebookEmail this to someone

There are two types of programmers in the world of PHP. The first is the curious, the knowledge-seeking type attempting the most elegant and clean solutions of development issues, who strive to create a harmonic picture of code that evokes admiration, and not an infinite torture of the soul. The second is the indolent type, always pressed for time, who experience coding as if it were a sort of mining activity. In the source code, however, quantity != quality. In time, I have realized that in this realm the moment never comes when you can say “I am ready! There’s nothing more I can learn!” New methods and approaches are continuously developed that aim to make life easier for the programmer.

Recently, there’s been more and more talk in the PHP community about Dependency Injection (DI) – and there’s a reason why. In my own judgment, the development of Zend Framework 2 and Symfony 2 has significantly increased the popularity of Dependency Injection (in PHP) and has shed light on the importance and great advantages of this design pattern. Despite the numerous blog articles, PHP coders still seem to shun this approach. Below, I will try to explain my understanding and implementation of DI.

So, what exactly is Dependency Injection?

Dependency Injection is a design pattern. A lot of people are unable to tell the difference between Dependency Injection and Dependency Injection Container. Now I will try to elucidate DI, and I will discuss DI Containers further down.

Just like most other design patterns, DI can be best clarified by providing examples. Let’s take two classes – Keyboard and PersonalComputer.

<?php
class Keyboard
{

}
class PersonalComputer
{

protected $keyboard = null;

public function __construct(Keyboard $keyboard)
{
$this->keyboard = $keyboard;
}

public function getKeyboard()
{
return $this->keyboard;
}

}
<?php
$keyboard = new Keyboard;
$pc = new PersonalComputer($keyboard);

As we can see from the example, first we instantiate the Keyboard class and then we create an object of the PersonalComputer type. When instantiating PersonalComputer, we pass the instance of Keyboard as an argument to the constructor. In turn, the PersonalComputer constructor encapsulates the resulting object inside a protected $keyboard.

Note that we specify the type of object we require in the PersonalComputer constructor – an instance of Keyboard. This way, we make sure that the PersonalComputer class will be successfully instantiated only when the $keyboard argument being passed is an object of the Keyboard type.

The above example illustrates the so called constructor injection. In this case we say that PersonalComputer consumes Keyboard.

DI Containers

Dependency Injection containers are libraries which automatically inject dependency instances.

Phemto is a DI container for PHP. Here is how we can apply Phemto to the above example.

<?php
$injector = new Phemto;
$pc = $injector->create('PersonalComputer');

The container analyzes the PersonalComputer class (utilizing Reflection) and then automatically injects a new instance of Keyboard.

Configuring DI

The automatic generation of instances is the most fundamental of DI container capabilities. In many cases, programmers need to control these instances. The universal solution is to use an external file configuration.

Some of the key options to be included in the configuration of most DI containers are as follows:

  • Defining the parameters to pass to the constructor of a given class while instantiating.
  • Defining the shared option for a class – if true, this means that a given class will be instantiated just once and each time it is generated by the container, the same instance will be returned.
  • The setting (traditionally referred to as “call”) to automatically call setter method following the instantiation of a setter injection class is an approach similar to the previously mentioned constructor injection but instead of a constructor, setter methods are utilized.
  • Defining configurations of instances, which are generated within the context of a class (hierarchical configuration of instances)

In the next part we will discuss DI configurations in much greater depth. We will also consider some other topics that are DI-related (such as the Service Locator design pattern).

Tweet about this on TwitterShare on LinkedInShare on Google+Share on FacebookEmail this to someone

Joan-Alexander Grigorov

Joan-Alexander is a Zend Certified Engineer and dedicated expert in the field of Zend Framework, Design Patterns and reusable object-oriented software design in general. He enjoys writing short articles discussing the solutions to problems he encounters in his daily activities. Most of his articles are written in Bulgarian and can be read on his personal blog at: http://bgscripts.com/ A responsible personality and developer, he has a highly critical attitude towards his own work. His biggest priority is the creation of high-quality code which is easy to test and maintain. His presence in our office really matters as he shares his know-how and contributes to a positive working environment. In our personal observations, he mentions “Dependency Injection” at least once a day. In our opinion, and according to his friends, Joan-Alexander is a Zend Framework and Design Patterns evangelist. Every now and then, the office staff witnesses short beatbox improvisations for in the recent past, Joan-Alexander used to be a professional beatbox and hip hop performer.

More Posts - Website

  • Nana

    Well, i read and read again for understand de concept, i have one question, in magento when we create extension that override magento methods, that is dependency injection?

  • good post lad

    Nice, informative and short post, Alexander.
    Also good to see there is a local company with such outstanding approach to the OOP side of PHP, w/o even mentioning your company’s team, apparent proficiency in Zend, Mage and related technologies…

    Keep the good job, lads.