Laravel

Laravel Dependecy injection

The foundation of the Laravel framework is its powerful IoC container. To truly understand the
framework, a strong grasp of the container is necessary. However, we should note that an IoC
container is simply a convenience mechanism for achieving a software design pattern: dependency
injection. A container is not necessary to perform dependency injection, it simply makes the task
easier.
First, let’s explore why dependency injection is beneficial. Consider the following class and method:

class UserController extends BaseController {
    public function getIndex()
    {
        $users = User::all();
        return View::make('users.index', compact('users'));
    }
}

While this code is concise, we are unable to test it without hitting an actual database. In other
words, the Eloquent ORM is tightly coupled to our controller. We have no way to use or test this
controller without also using the entire Eloquent ORM, including hitting a live database. This code
also violates a software design principle commonly called separation of concerns. Simply put: our
controller knows too much. Controllers do not need to know where data comes from, but only how
to access it. The controller doesn’t need to know that the data is available in MySQL, but only that
it is available somewhere.

So, it will be beneficial for us to decouple our web layer (controller) from our data access layer
completely. This will allow us to migrate storage implementations easily, as well as make our code
easier to test. Think of the “web” as just a transport layer into your “real” application.

Imagine that your application is like a monitor with a variety of cable ports. You can access the
monitor’s functionality via HDMI, VGA, or DVI. Think of the Internet as just a cable into your
application. The bulk of a monitor’s functionality is independent of the cable. The cable is just a
transport mechanism just like HTTP is a transport mechanism for your application. So, we don’t
want to clutter up our transport mechanism (the controller) with application logic. This will allow
any transport layer, such as an API or mobile application, to access our application logic.
So, instead of coupling our controller to the Eloquent ORM, let’s inject a repository class.

Build a Contract

First, we’ll define an interface and a corresponding implementation:

interface UserRepositoryInterface {
    public function all();
}
class DbUserRepository implements UserRepositoryInterface {
    public function all()
    {
        return User::all()->toArray();
    }
}

Next, we’ll inject an implementation of this interface into our controller:

class UserController extends BaseController {
    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }
    public function getIndex()
    {
        $users = $this->users->all();
        return View::make('users.index', compact('users'));
    }
}

Now our controller is completely ignorant of where our user data is being stored. In this case,
ignorance is bliss! Our data could be coming from MySQL, MongoDB, or Redis. Our controller
doesn’t know the difference, nor should it care. Just by making this small change, we can test our
web layer independent of our data layer, as well as easily switch our storage implementation.

Featured image courtesy : http://codeanchor.net