IoC stands for Inversion of Control, and it is effectively just a fancy way of describing a concept in Object Oriented programming where the logic behind how you instantiate a class is abstracted into a class itself, often referred to as a "container". In languages like Java and C#, this means that creating instances of classes is moved from compile time to run time, as instead of using the language itself to directly create an instance of a class e.g. "object = new Class()", you are telling your IoC container to do it, e.g. "object = ioc.get('Class')". Of course, this compile time vs run time effect of IoC isn't all that relevant for PHP, but it is nonetheless just as useful a concept in PHP.
Why is this a benefit? After all, using a language's "new" keyword to create an instance seems technically shorter, and possibly more efficient. The benefit comes when you design your OO code around the principles of Dependency Injection. I won't go into a lengthy dialogue about DI here, so if you're not familiar with the concept of DI you may want to go do some Googling, but in its most simple form, DI means writing classes that depend on instances of other classes in a manner which means they are not tightly coupled to those other classes. In other words, instead of creating instances of other classes inside a class, you feed instances into the class, typically via its constructor, but also possibly through setter methods. This means classes can be unit tested far easier, and it's generally just a better design in the 'separation of concerns' world of OO programming.
Say we have a Photo controller and injected its related DB in rather than the static way:
class Photo {
/**
* @var PDO The connection to the database
*/
protected $db ;
public function __construct() {}
/**
* Sets the database connection
* @param PDO $dbConn The connection to the database.
*/
public function setDB( $dbConn ) {
$this ->db = $dbConn ;
}
}
$photo = new Photo;
$photo ->setDB( $dbConn );
There's one problem with using DI in this way: it makes the class considerably more difficult to work with. The user now must be fully aware of the class's dependencies, and must remember to set them, accordingly. Consider, down the line, when our fictional class requires a couple more dependencies. Well, following the rules of the dependency injection pattern, we'd have to do:
$photo = new Photo;
$photo ->setDB( $dbConn );
$photo ->setConfig( $config );
$photo ->setResponse( $response );
Yuck. The class my be more modular, but we've also piled on confusion and complexity. Before, the user could simply create a new instance of Photo, but, now, he has to remember to set all of these dependencies. This is where a IoC container comes in - the object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis. This is much nicer.
An IoC could be like this:
class IoC {
/**
* @var PDO The connection to the database
*/
protected static $registry = array ();
/**
* Add a new resolver to the registry array.
* @param string $name The id
* @param object $resolve Closure that creates instance
* @return void
*/
public static function register( $name , Closure $resolve ) {
static :: $registry [ $name ] = $resolve ;
}
/**
* Create the instance
* @param string $name The id
* @return mixed
*/
public static function resolve( $name ) {
if ( static ::registered( $name ) ) {
$name = static :: $registry [ $name ];
return $name ();
}
throw new Exception( 'Nothing registered with that name, fool.' );
}
/**
* Determine whether the id is registered
* @param string $name The id
* @return bool Whether to id exists or not
*/
public static function registered( $name ) {
return array_key_exists ( $name , static :: $registry );
}
}
When the user calls the IoC::register method, they're adding an id, such as photo, and its associated resolver, which is just a lambda that creates the instance and sets any necessary dependencies on the class.
Now, we can register and resolve dependencies through the IoC class, like this:
// Add `photo` to the registry array, along with a resolver
IoC::register( 'photo' , function () {
$photo = new Photo;
$photo ->setDB( '...' );
$photo ->setConfig( '...' );
return $photo ;
});
// Fetch new photo instance with dependencies set
$photo = IoC::resolve( 'photo' );
So, we can observe that, with this pattern, we're not manually instantiating the class. Instead, we register it with the IoC container, and then request a specific instance. This reduces the complexity that we introduced, when we stripped the hardcoded dependencies out of the class.
// Before
$photo = new Photo();
// After
$photo = IoC::resolve( 'photo' );
Back to Laravel 4. Not only does "L4" as it is referred to by its faithful offer a IoC container out of the box, but it basically encompasses the entire framework. In fact, if you check out the L4 code on Github , the Application class that the framework operates within extends from the Container class, so the ability to bind a class instance implementation is absolutely core to the Laravel 4 framework. So what's the typical usage of it ?
Laravel 4 introduces the ruby-on-rails-like resource controller for handling all of the http request. If a user hit /resource url, the controller would serve him the resources through index() method for example. So the resource controller is responsible for public user requests.
What if we want to add some of the methods for handling the resource Model and do not want it to be public to the users ? Instead of defining these methods within the controller itself, it is suggested to use a Repository contains these internal methods and inject it into resource controller:
1. we should define an interface that contains all of the internal methods we need:
interface SomeRepositoryInterface {
public function method1( $arg );
public function method2( $arg1, $arg2 );
public function method3( $arg1, $arg2, $arg3 );
public function method4( $arg1, $arg2, $arg3, $arg4 );
public function method5( $arg1, $arg2, $arg3, $arg4, $arg5 );
});
2. make the SomeRepository to implements all of these contracts:
class SomeRepository implements SomeRepositoryInterface {
public function method1( $arg ) {
// I promise to implement it.
}
public function method2( $arg1, $arg2 ) {
// I promise to implement it.
}
public function method3( $arg1, $arg2, $arg3 ) {
// I promise to implement it.
}
public function method4( $arg1, $arg2, $arg3, $arg4 ) {
// I promise to implement it.
}
public function method5( $arg1, $arg2, $arg3, $arg4, $arg5 ) {
// I promise to implement it.
}
});
3. inject it into the constructor of our resource controller:
class SomeController implements BaseController {
protected $thing ;
public function __construct( SomeRepositoryInterface $thing ) {
$this ->thing = $thing ;
}
public function index() {
return $this ->thing->method1( /* arguments */ );
}
public function create() {
return $this ->thing->method2( /* arguments */ );
}
public function store() {
return $this ->thing->method3( /* arguments */ );
}
public function show( $id ) {
return $this ->thing->method4( /* arguments */ );
}
/* some other resources methods here... */
});
Here the constructor is like to say, anyone who implements the SomeRepositoryInterface would be injected into myself.
4. Within the routes.php, use the App IoC container to bind our SomeRepository to our SomeRepositoryInterface:
App:: bind ( 'SomeRepositoryInterface' , 'SomeRepository' );
And the IoC container would smartly know that every time we say to instantiate the SomeRepositoryInterface, we want instantiate the SomeRepository actually.
Now, we've got a more flexible codebase structure:
1. separate the concern of internal methods from public APIs gracefully. Whenever we want some entirely new implementations of SomeRepositoryInterface, we can just define SomeOther RepositoryInterface and bind it to the SomeRepositoryInterface .
2. dependency injection make it easier for unit testing.
[References]: http://net.tutsplus.com/tutorials/php/dependency-injection-huh/
http://www.nathandavison.com/posts/view/16/
Why is this a benefit? After all, using a language's "new" keyword to create an instance seems technically shorter, and possibly more efficient. The benefit comes when you design your OO code around the principles of Dependency Injection. I won't go into a lengthy dialogue about DI here, so if you're not familiar with the concept of DI you may want to go do some Googling, but in its most simple form, DI means writing classes that depend on instances of other classes in a manner which means they are not tightly coupled to those other classes. In other words, instead of creating instances of other classes inside a class, you feed instances into the class, typically via its constructor, but also possibly through setter methods. This means classes can be unit tested far easier, and it's generally just a better design in the 'separation of concerns' world of OO programming.
Say we have a Photo controller and injected its related DB in rather than the static way:
class Photo {
/**
* @var PDO The connection to the database
*/
protected $db ;
public function __construct() {}
/**
* Sets the database connection
* @param PDO $dbConn The connection to the database.
*/
public function setDB( $dbConn ) {
$this ->db = $dbConn ;
}
}
$photo = new Photo;
$photo ->setDB( $dbConn );
There's one problem with using DI in this way: it makes the class considerably more difficult to work with. The user now must be fully aware of the class's dependencies, and must remember to set them, accordingly. Consider, down the line, when our fictional class requires a couple more dependencies. Well, following the rules of the dependency injection pattern, we'd have to do:
$photo = new Photo;
$photo ->setDB( $dbConn );
$photo ->setConfig( $config );
$photo ->setResponse( $response );
Yuck. The class my be more modular, but we've also piled on confusion and complexity. Before, the user could simply create a new instance of Photo, but, now, he has to remember to set all of these dependencies. This is where a IoC container comes in - the object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis. This is much nicer.
An IoC could be like this:
class IoC {
/**
* @var PDO The connection to the database
*/
protected static $registry = array ();
/**
* Add a new resolver to the registry array.
* @param string $name The id
* @param object $resolve Closure that creates instance
* @return void
*/
public static function register( $name , Closure $resolve ) {
static :: $registry [ $name ] = $resolve ;
}
/**
* Create the instance
* @param string $name The id
* @return mixed
*/
public static function resolve( $name ) {
if ( static ::registered( $name ) ) {
$name = static :: $registry [ $name ];
return $name ();
}
throw new Exception( 'Nothing registered with that name, fool.' );
}
/**
* Determine whether the id is registered
* @param string $name The id
* @return bool Whether to id exists or not
*/
public static function registered( $name ) {
return array_key_exists ( $name , static :: $registry );
}
}
When the user calls the IoC::register method, they're adding an id, such as photo, and its associated resolver, which is just a lambda that creates the instance and sets any necessary dependencies on the class.
Now, we can register and resolve dependencies through the IoC class, like this:
// Add `photo` to the registry array, along with a resolver
IoC::register( 'photo' , function () {
$photo = new Photo;
$photo ->setDB( '...' );
$photo ->setConfig( '...' );
return $photo ;
});
// Fetch new photo instance with dependencies set
$photo = IoC::resolve( 'photo' );
So, we can observe that, with this pattern, we're not manually instantiating the class. Instead, we register it with the IoC container, and then request a specific instance. This reduces the complexity that we introduced, when we stripped the hardcoded dependencies out of the class.
// Before
$photo = new Photo();
// After
$photo = IoC::resolve( 'photo' );
Back to Laravel 4. Not only does "L4" as it is referred to by its faithful offer a IoC container out of the box, but it basically encompasses the entire framework. In fact, if you check out the L4 code on Github , the Application class that the framework operates within extends from the Container class, so the ability to bind a class instance implementation is absolutely core to the Laravel 4 framework. So what's the typical usage of it ?
Laravel 4 introduces the ruby-on-rails-like resource controller for handling all of the http request. If a user hit /resource url, the controller would serve him the resources through index() method for example. So the resource controller is responsible for public user requests.
What if we want to add some of the methods for handling the resource Model and do not want it to be public to the users ? Instead of defining these methods within the controller itself, it is suggested to use a Repository contains these internal methods and inject it into resource controller:
1. we should define an interface that contains all of the internal methods we need:
interface SomeRepositoryInterface {
public function method1( $arg );
public function method2( $arg1, $arg2 );
public function method3( $arg1, $arg2, $arg3 );
public function method4( $arg1, $arg2, $arg3, $arg4 );
public function method5( $arg1, $arg2, $arg3, $arg4, $arg5 );
});
2. make the SomeRepository to implements all of these contracts:
class SomeRepository implements SomeRepositoryInterface {
public function method1( $arg ) {
// I promise to implement it.
}
public function method2( $arg1, $arg2 ) {
// I promise to implement it.
}
public function method3( $arg1, $arg2, $arg3 ) {
// I promise to implement it.
}
public function method4( $arg1, $arg2, $arg3, $arg4 ) {
// I promise to implement it.
}
public function method5( $arg1, $arg2, $arg3, $arg4, $arg5 ) {
// I promise to implement it.
}
});
3. inject it into the constructor of our resource controller:
class SomeController implements BaseController {
protected $thing ;
public function __construct( SomeRepositoryInterface $thing ) {
$this ->thing = $thing ;
}
public function index() {
return $this ->thing->method1( /* arguments */ );
}
public function create() {
return $this ->thing->method2( /* arguments */ );
}
public function store() {
return $this ->thing->method3( /* arguments */ );
}
public function show( $id ) {
return $this ->thing->method4( /* arguments */ );
}
/* some other resources methods here... */
});
Here the constructor is like to say, anyone who implements the SomeRepositoryInterface would be injected into myself.
4. Within the routes.php, use the App IoC container to bind our SomeRepository to our SomeRepositoryInterface:
App:: bind ( 'SomeRepositoryInterface' , 'SomeRepository' );
And the IoC container would smartly know that every time we say to instantiate the SomeRepositoryInterface, we want instantiate the SomeRepository actually.
Now, we've got a more flexible codebase structure:
1. separate the concern of internal methods from public APIs gracefully. Whenever we want some entirely new implementations of SomeRepositoryInterface, we can just define SomeOther RepositoryInterface and bind it to the SomeRepositoryInterface .
2. dependency injection make it easier for unit testing.
[References]: http://net.tutsplus.com/tutorials/php/dependency-injection-huh/
http://www.nathandavison.com/posts/view/16/