Michael Budd

Tutorial on Dependcy Injection and Lazy Initialisation using Pimple

This tutorial scratches the surface of dependency injection and how to use Pimple as a way of implementing it.

So why do you want to you dependency injection?

Do you ever find yourself writing constructors with what you consider too many paramaters? i.e. something like:


class Claire {
	
	public function __construct($cheese1, $cheese2, $cheese3, $cheese4, $cheese5) {

		$this->cheese1 = $cheese1;
		$this->cheese2 = $cheese2;
		$this->cheese3 = $cheese3;
		$this->cheese4 = $cheese4;
		$this->cheese5 = $cheese5;
	}
}

This soon becomes very messy and furthermore, you may have some files that instantiate Clair without all those params and then you need to make provisos for them.

Then there's another issue... let's say for example that all those constructor vars are objects.... what happens if we for some files we don't end up needing some of them. We've then instantiated classes that we don't need and hit ourselves with a potentially expensive performance hit for no reason.

This is where dependcy injection can help us. Firstly, we can clean up that messy constructor by simply passing in a Dependcy Injection Container... like so:


class Claire {
	
	public function __construct($dic) {

		$this->dic = $dic;
	}
}

Even better than this though, we can now use what is known as Lazy Initialisation. Simply put, using something like Pimple, or another dependcy injection manager, our manager can simply check whether there is an existing object instance and deliver us that. If not it can create a new instance for us.

If we need multiple instances, we can achieve this too by using:


$dic['multipleInstanceHuman'] 	= $dic->factory(function ($c) {
    return new Human();
});

Using the factory method, Pimple makes sure we get a new instance each time we assign $dic['multipleInstanceHuman'] to a new variable. This will make more sense when viewing my full code at the end of this tutorial.

To see this in action, look at my method below and then replace $this->dic['multipleInstanceHuman'] with $this->dic['singleInstanceHuman'] and you'll see that suddenly when you reload the page you'll get the same name spat out three times.

To use Pimple check out Pimple's website, there's a very good tutorial on how to install using Composer. If you have a problem with Composer recognising Pimple, try using the below instead in your composer.json file:

{
    "require": {
        "pimple/pimple": "~2.1@dev"
    }
}

So that's it from me, here's my full code below. There are 3 main files I use, index.php, human.php, and test.php, all shown below.

I also recommend this great video on advanced OO patterns, which covers the use of DIC


/***** index.php **********/

require_once('classes/test.php');
require_once('classes/human.php');
require_once('vendor/pimple/pimple/src/Pimple/Container.php');
require_once('vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php');
require_once('vendor/pimple/pimple/src/Pimple.php');


$dic = new Pimple();

$dic['dateOne'] = function() {
	return new DateTime();
};

$dic['singleInstanceHuman'] 	= function() {
	return new Human();
};

$dic['multipleInstanceHuman'] 	= $dic->factory(function ($c) {
    return new Human();
});



$test 			= new Test($dic);
$single 		= $test->singleInstanceSetGetName();
$multiple 		= $test->multipleInstanceSetGetName();

echo $single->getName() . "
"; echo $multiple['jim']->getName() . "
"; echo $multiple['garry']->getName() . "
"; /********* end of index.php ***********/ /********* test.php ***********/ class Test { public function __construct($dic) { $this->dic = $dic; } public function singleInstanceSetGetName() { $this->dic['singleInstanceHuman']->setName("Dave"); return $this->dic['singleInstanceHuman']; } public function multipleInstanceSetGetName() { $garry = $this->dic['multipleInstanceHuman']; $jim = $this->dic['multipleInstanceHuman']; $garry->setName("garry"); $jim->setName("jim"); return array( 'garry' => $garry, 'jim' => $jim ); } } /********** end of test.php **********/ /********** human.php ****************/ class Human { public function __construct() { $this->name = ""; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } }

As always, thanks for reading!

Author:

comments powered by Disqus