26
votes

After developing a few projects using Codeigniter since 2 years, I stared to learn Laravel.

I downloaded a few projects lo learn how they are coded. As I understood, many of them are using only models, views and controllers which is same as Codeigniter.

But one project has used repositories and interfaces. It is really hard to understand whats going on that project. So what is the usage of repositories and interfaces in Laravel? When should I use them?

5
Interfaces and/or repositories has different usage requirements, and they are not specific to Laravel. It's an architecture decision and you should to take this kind of decision within your team, if you have one. Aside that, in Laravel, you should not implement repositories if you're planning to stay with Eloquent, the Laravel ORM.Ricardo Vigatti
I personally do not agree on the repository thing. Repositories abstracts even the way you use Eloquent, making the controller super lightweight, highly maintainable and simple to understand also for non-backend developers if you're working with a medium team. Repositories also can facilitate the process of multi-version API for example.Desh901

5 Answers

22
votes

I will try to explain as clearly as possible the two concepts.

Interfaces\Contracts

In general OOP interfaces are used to describe which methods/functionalities the class that implements that interface is offering without caring about the actual implementation.

Laravel uses Contracts mainly to separate a service from the actual implementation. To be more clear let's make an example

<?php

namespace App\Orders;

class OrdersCache
{

    protected $cache;

    public function __construct(\SomePackage\Cache\Memcached $cache)
    {
        $this->cache = $cache;
    }


    public function find($id)
    {
        if ($this->cache->has($id))    {
            //
        }
    }
}

As you can see in this class the code is tightly coupled to a cache implementation (i.e. \SomePackage\Cache\Memcached) so if the API of that Cache class changes our code also must be changed accordingly. The same thing happens if we want to change the Cache implementation with another one (e.g. redis).

Instead of doing that, our code could depend on an interface that is agnostic from the implementation:

<?php

namespace App\Orders;

use Illuminate\Contracts\Cache\Repository as Cache;

class OrdersCache
{

    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }


    public function find($id)
    {
        if ($this->cache->has($id))    {
            //
        }
    }
}

Now our code is not coupled with any specific implementation because Cache is actually an interface. So basically in our class we are requiring an instance of a class that behaves like described in the Cache interface, but we are not really interested in how it works internally. Doing that if we want to change the cache implementation we could write a class that implements the interface Cache without changing any line of code in our OrdersCache class. Doing that our code is easier to understand and maintain and your packages are a lot more reusable. See the section Loose Coupling in the Laravel documentation for further examples.

Interfaces and Service Container

One of the main features of Laravel is its Service Container, it is used to manage dependencies and performing dependency injection. Please take a look at Service Container definition from Laravel documentation.

Dependency Injection is widely used by Laravel also to bind interfaces to implementation. Let's make an example:

$app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');

And let our class be

<?php

namespace App\Http\Controllers;

use App\Contracts\EventPusher;

class EventsController extends Controller 
{

    protected $pusher;

    public function __construct(EventPusher $pusher) 
    {

        $this->pusher = $pusher;        

    }

}

Without declaring anything else we are basically saying everytime that someone need an EventPusher instance, please Laravel, provide an instance of RedisEventPusher class. In this case everytime that your controller is instantiated, Laravel will pass an instance of RedisEventPusher to your controller without specifying anything else.

You can dig into that by looking at Binding Interfaces to Implementation section on the Laravel documentation.

Repositories

Repositories is a concept applicable to the MVC pattern independently from any specific framework. Typically you have your Model that is the data layer (e.g. interacts with the database directly), your Controller that handles the access logic to the data layer and your View that shows the data provided by the Controller.

Repositories instead could be defined as follows:

To put it simply, Repository pattern is a kind of container where data access logic is stored. It hides the details of data access logic from business logic. In other words, we allow business logic to access the data object without having knowledge of underlying data access architecture.
Soruce: https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5

To know how to use them within Laravel please take a look at this great article.

That's all, i hope it helps to clear up your mind.

11
votes

Interfaces are what any implementing class should call.

interface CanFlyInterface
{
    public function fly();
}

Think of it like programming without bothering with logic.

if ($object instanceof CanFlyInterface) {
    $obj->fly();
}

Now we could have passed a Bird object, or an Aeroplane object! PHP DOESN'T CARE, so long as it implements the interface!

class Bird implements CanFlyInterface
{
    public function fly()
    {
        return 'flap flap!';
    }
}

class Aeroplane implements CanFlyInterface
{
    public function fly()
    {
        return 'roar! whoosh!';
    }
}

Your other question, what a Repository class is. It's just a class that keeps all your DB queries in the one place. Check this interface as an example:

interface RepositoryInterface
{
    public function insert(array $data);
    public function update(array $data);
    public function findById($id);
    public function deleteById($id);
}

Hopefully this should clear things up for you! Good luck with all your PHP coding :-D

5
votes

Let's start with the easier one, the interface:

You normally use interfaces to implement classes with required methods: http://php.net/manual/en/language.oop5.interfaces.php

Laravel's Contracts are a set of interfaces that define the core services provided by the framework. For example, a Illuminate\Contracts\Queue\Queue contract defines the methods needed for queueing jobs, while the Illuminate\Contracts\Mail\Mailer contract defines the methods needed for sending e-mail. https://laravel.com/docs/5.4/contracts#introduction

When Laravel is running it can check if a class implements a special interface:

if ($cls instanceof IInterface) {
    $cls->interfaceFunction();
}

Since Laravel is able to work with queues it will check if the event should be queued or not by checking for an exiting interface.

To inform Laravel that a given event should be broadcast, implement the Illuminate\Contracts\Broadcasting\ShouldBroadcast interface on the event class. https://laravel.com/docs/5.4/broadcasting#defining-broadcast-events

Repository:

I didn't found that much about this:

Our repository should not have so much knowledge regarding who is providing them data or how they are providing it. https://laravel.com/docs/5.4/contracts#loose-coupling

But I found some other information on a webpage:

a Repository will connect Factories with Gateways https://code.tutsplus.com/tutorials/the-repository-design-pattern--net-35804

The link will give you more information about the the details.

Hope I could help you :)

5
votes

First of all, using Repository and Interface in larger application is not only beneficiary in Laravel but in all technology for coding standard as well as for separation of concern.

According to Microsoft (I found best explanation here)

Why to use Repository:

Use a repository to separate the logic that retrieves the data and maps it to the entity model from the business logic that acts on the model. The business logic should be agnostic to the type of data that comprises the data source layer. The repository mediates between the data source layer and the business layers of the application. It queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source.
A repository separates the business logic from the interactions with the underlying data source or Web service. The separation between the data and business tiers has three benefits: It centralizes the data logic or Web service access logic. It provides a substitution point for the unit tests. It provides a flexible architecture that can be adapted as the overall design of the application evolves. There are two ways that the repository can query business entities. It can submit a query object to the client's business logic or it can use methods that specify the business criteria. In the latter case, the repository forms the query on the client's behalf. The repository returns a matching set of entities that satisfy the query.

For Interface, you have a lot of answers above, hope you have understand.

2
votes

First of all, repositories and interfaces are not specific to Laravel but common coding standards in most of the languages.

Below Laracasts videos will be useful to understand the basics if you don't mind spend few dollars.

https://laracasts.com/lessons/repositories-and-inheritance

https://laracasts.com/series/object-oriented-bootcamp-in-php