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?
A repository can be defined as a layer of abstraction between the domain and data mapping layers, one that provides an avenue of mediation between both, via a collection-like interface for accessing domain objects.
Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.
In Laravel, an interface is a contract for what methods will be used in a specific class. Actually, interfaces are not specific to Laravel, or even native PHP for that matter.
A repository provides an interface to access data stored in the database or external resources. Data is returned in the form of objects. Repositories act as a bridge between the models and the controller. By using Repository Pattern we can decouple the hard dependencies of models from the controllers.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With