How to use Repository Pattern in Laravel
The Repository Pattern in Laravel is a very useful pattern with a couple of great uses. The first use is the abstraction that it provides. Meaning, it adds another layer between your application logic and your database.
Laravel Design Patterns ( 2 Lessons )
There are various ways to structure the code and project for your web application. But it is usually a good idea to follow common design patterns because it will make your code easier to manage and easier for others to understand.
see full series- How to use Repository Pattern in Laravel
- How To Use Adapter Pattern in Laravel
Many people must have heard the buzz about Repository Pattern in Laravel, in this post we will make it damn easy to understand why this is an important pattern and when to use it.
When tackling the separation of concerns, this is very important. Another benefit is how easy it makes it swap out your backend technology.
For instance, let’s say you are using MySQL and want to change to MongoDB. Since the Repository Pattern uses interfaces as contracts, your application logic will remain the same and all you have to do is change out the repository. Sounds easy, right?
Let’s dive in with a simple example.
Creating the Repository Interface
We need an interface to act as a contract for our repositories. What do I mean by contract?
Just like a written contract which describes the confines of a specific obligation, an interface is the same for our code.
It says that any class implementing the interface must perform specific actions. Or, in our case, must contain specific methods… Right.
I will use the blog scenario and create a post repository, as well as a comment repository. So, create a folder inside of the app
folder and name it Repositories
.
Then, create a file and name it PostRepositoryInterface.php
. This will be our interface. Within that interface, you will want to add this code:
namespace App\Repositories; interface PostRepositoryInterface { }
Now, we will need the contracts, or methods, that we want our toPostRepository
implement. It will look something like this:
namespace App\Repositories; interface PostRepositoryInterface { /** * Get's a post by it's ID * * @param int */ public function get($post_id); /** * Get's all posts. * * @return mixed */ public function all(); /** * Deletes a post. * * @param int */ public function delete($post_id); /** * Updates a post. * * @param int * @param array */ public function update($post_id, array $post_data); }
Notice how there are no opening and closing curly braces. That is because no logic is stored in the interface – only the methods or declaration that we want our class to implement.
Creating the Repository
Now, we need to create our class. Within the same folder, Repositories
create a file and name it PostRepository.php
. For this class, we will use the implements
keyword to specify that we want to implement our interface. It should look like this:
namespace App\Repositories; class PostRepository implements PostRepositoryInterface { }
We must create the methods that declared in our interface. If we don’t, we will get an error at runtime and we will not be able to use our class. Go ahead and add the logic that we will use to work without posts. For this, I will include our Eloquent model Post
.
namespace App\Repositories; use App\Post; class PostRepository implements PostRepositoryInterface { /** * Get's a post by it's ID * * @param int * @return collection */ public function get($post_id) { return Post::find($post_id); } /** * Get's all posts. * * @return mixed */ public function all() { return Post::all(); } /** * Deletes a post. * * @param int */ public function delete($post_id) { Post::destroy($post_id) } /** * Updates a post. * * @param int * @param array */ public function update($post_id, array $post_data) { Post::find($post_id)->update($post_data); } }
Our class is now happy because it is using all of the methods defined by our interface. Now that we have our class and our interface created, we need to register our repository with Laravel’s container.
Registering our Repository with Laravel’s IoC Container
Create a file called BackendServiceProvider.php
within the same folder – Repositories
. This file will serve as a connector to Laravel’s IoC Container and allow us to use dependency injection to inject our repository interfaces. More on that in a second …
Here is the BackendServiceProvider.php
:
namespace App\Repositories; use Illuminate\Support\ServiceProvider; class BackendServiceProvider extends ServiceProvider { public function register() { $this->app->bind( 'App\Repositories\PostRepositoryInterface', 'App\Repositories\PostRepository' ); } }
The one thing to notice here is the order in which the interface and the class are bound. If you try and bind App\Repositories\PostRepository
before App\Repositories\PostRepositoryInterface
, you will get an error. You must bind the interface first.
Still with me?
Just to make sure you’re following along, you should have a folder structure like this:
- app --- Repositories ------ BackendServiceProvider.php ------ PostRepositoryInterface.php ------ PostRepository.php
Of course, there will be other folders and files within the app directory, I hope you get the point.
Using the Repository in a Controller
It’s time to use our shiny, new repository. The place to use this is our controller. I will assume that you have a PostController.php
class and that is your controller that handles everything to do with your posts. If you use some other controller, that is fine too.
What we want to do is inject our interface into the controller through its constructor when the controller gets instantiated. That way we can use the repository for all of our interactions with our posts model. Check it out:
namespace App\Http\Controllers; use App\Http\Requests; use App\Repositories\PostRepositoryInterface; class PostController extends Controller { protected $post; /** * PostController constructor. * * @param PostRepositoryInterface $post */ public function __construct(PostRepositoryInterface $post) { $this->post = $post; } /** * List all posts. * * @return mixed */ public function index() { $data = [ 'posts' => $this->post->all() ]; return view('templates.posts', $data) } }
The first thing that we did is inject oursPostRepositoryInterface
into our constructor.
Then, we set our instance$post
variable to an instance of our objectPostRepository
through our interface. This allows us to call the methods in our classPostRepository
like we did in the methodindex()
. Now we can do something like this:
$this->post->update($data_array); $this->post->delete($post_id); $this->post->get($post_id);
This keeps us from directly accessing our model like Post::find$id);
which adds another layer of abstraction to our application. Don’t forget, should we stop using MySQL and start using MongoDB, or some other backend technology, all we have to do is swap out our logicPostRepository
. This works because we are accessing the repository through our interface.
This means that the code in our controller would not change at all. That’s a big win!
More than one Repository? Sure
So, you need to create another repository because just having one repository is lame. Right? All you need to do is create an interface and then create a repository. Then, register them with Laravel’s IoC Container in our backend service provider file. I’ll use a Comment
model to show you how.
Our directory would now look like this:
In app folder
- Repositories --- BackendServiceProvider.php ------ PostRepositoryInterface.php ------ PostRepository.php ------ CommentRepositoryInterface.php ------ CommentRepository.php
You would create the comment repository interface the same exact way as we did the post repository interface:
CommentRepositoryInterface.php
namespace App\Repositories; interface CommentRepositoryInterface { // Define all methods here but remember not to use curly braces. public function all(); // Like this.. }
And our CommentRepository.php
namespace App\Repositories; use App\Comment; class CommentRepository implements CommentRepositoryInterface { // Must use all methods that were defined in the CommentRepositoryInterface here public function all() { return Comment::all(); } }
The last thing that you will need to do is register it with the IoC Container in our BackendServiceProvider.php
. That file will now look like this…
namespace App\Repositories; use Illuminate\Support\ServiceProvider; class BackendServiceProvider extends ServiceProvider { public function register() { $this->app->bind( 'App\Repositories\PostRepositoryInterface', 'App\Repositories\PostRepository' ); $this->app->bind( 'App\Repositories\CommentRepositoryInterface', 'App\Repositories\CommentRepository' ); } }
Again, pay attention to the order in which you list your interface and class.
Finished. Doesn’t that feel good? You should have a fully functional repository design pattern implemented with Laravel 5.
If you have any questions or comments about repository pattern in Laravel, please post them below.
Great text, thank you and continue with good work.
My question about Repository pattern is about data (response) mapper. How much is necessary to define data structure since we know that technologies (mysql, mongodb …) have different data structure.
What is best practice for this problem?
or I misunderstood pattern ? 🙂
Thanks for the compliment.
To my knowledge, Laravel take care of data structure compatibility based on the database engine you are using when creating migrations. You also have to write some custom exceptions which you can throw in your repository.
Thanks
Very nice Article to read. but I have a Question in my mind that, Is it good that we use repositories for Models as well? the same you did for controllers?
Use DTO to return from repository instead of model. Since your app shouldn’t care where your data come or what structure it has. That way your data will be consistent on app layer.
Manually in your repository method you can build DTO from model data and return it.
Unfortunately with Eloquent it is very hard to accomplish automatically, but not impossible. Doctrine is working better with this approach.
Why repository bind with loc container, can you explain briefly
Ravindra Lande when you try to use interface, container is trying to instantiate the interface. Thats why we fix that by creating a specific binding for our interface.
Nice Article for those how are learning by themselves (freelancers like me). Most of the opensource don’t follow this. they access Model in controller which is difficult to maintain. I possess only half knowledge on service layer (Accessing Multiple Repository thro Service) .. If you do have detail article please share it. thanks
Thanks hariharan for reading my post. You are right most of people write whole logic in the controller which is not good and also not recommended. We should move our logic from controller to model, repositories, services and traits. A good example is, any event-based logic or model’s functionality can be moved to a trait. Any thridparty service like paypal payements etc. can be dropped into a service to make it reuseable and all database transactions can be done in a repository.
I will write a detailed post on how we should refactor our controller.
Thanks
Hello,
Thanks for this explanation. By chance have you written a blog post yet about refactoring your controller to use traits, like mentioned above? Thanks.
Thanks for reading. I have couple of posts about design pattern lone up for this week, in which I will be explaining how we can refactor our code. Please keep checking this blog or like our facebook page so you will be updated.
I read somewhere that we shouldn’t use Repository pattern if we are sure we will use only one (db) technology in. But I think RP is nice way to have clear and good structured code.
You are right Dizni. It depends on your requirements and business nature.
Hi,
Thanx for the article, I had an issue with registering IoC Container, it didn’t work and kept producing
““
Illuminate \ Contracts \ Container \ BindingResolutionException
Target [App\Repositories\PostRepositoryInterface] is not instantiable while building [App\Http\Controllers\PostController].
““
I registered the Repository directly inside `AppServiceProvider` `register` method and worked fine.
Thanks Bashar. Have you created a separate backend or repository service provider. If you have then you need to add that service provider in the providers array in config/app.php file.
If you add the service provider in that array Laravel will instantiate your provider on app boot.
Hope that will help.
Thanx for the tip it worked, but I thought of the providers will be registered automatically and no need to register them in app config.
You are welcome. When you create a laravel package we can register the providers automatically. But for custom providers which are within our main application needs to be added to that array.
Hope I answer your question.
thanx
I have a question. Why you inject PostRepositoryInterface instead PostRepository on PostController? After all PostRepository implement PostRepositoryInterface
Hi Pablo,
If you inject the class directly, then in future you may have more classes to inject using __construct manually.
For example, if you have LogToFileRepository and you inject it in __constructor. But what if you want to write log to the database then you have to inject LogToDatabaseRepository class.
If you are using interface then you write the signature of an interface called LogInterface and then implement in LogToFile and LogToDatabase repository.
When you want to use it you can pass the which repository you want to use and it will work.
So by using interface If you have multiple classes and swap from one class to another class you will get the same result without changing any class references.
Hope answer the question. You can find a very simple example here PHP Interface.
Thanks
Hi ,in this case, should i bind both LogToFile and LogToDatabase to LogInterface ?
Yes you are right!
Thank you so much, now how to switch between LogToDatabase and LogInterface ?
For some situation i need a log file and in other situation log to database.
i also had this confusion, If both are needed at the same time its better to have two interfaces. This idea is more for using one OR the other i.e. easier switching based on requirement changes ( or maybe you want to make a LogToDatabase2.0 implementation)
Hi! I have a question. How can I pass parameters into register() method?
Hi Oleg,
What exactly you trying to achieve. Can you please explain a bit more.
Thanks
I would like to change the class instance which return my Container when I call some Interface into __construct of my class.
For example I have UsersRepositoryInterface and 2 classes: LocalUserRepository and ExternalUserRepository. When I pass parameter $needUseLocalStorage = true, I will be work with LocalUserRepository and if $needUseLocalStorage = false I will work with ExternalUserRepository.
Hi. Thanks for post.
But as I think using repository pattern variant like this with eloquent models is not a good idea.
RP is about decoupling DB and business-logic of an app. But your repository methods returns Eloquent models, that have DB connection themselves.
So I can do something like this:
$user = $userRepository->getUser($userId);
$otherUsers = $user->all();
And this will break the whole idea.
You can return $user->toArray() instead of $user, but this will ruin all Eloquent magic.
Hi Sergey,
Thanks for reading our post. I personally use the repository to decouple as you said above. I create an abstract repository and then implement them in my down level repository and write my business logic in there.
In this post, I just tried to show the way to implement it in Laravel for newbies but what you will add into the repository totally depends on you.
I totally agree with what you have said.
Thanks
It’s important to understand that in every project you will create Repos is not necessary. Say you’re making CMS. Do you need all those additional classes? I think you don’t. What about KISS?
Janis you are right. As I said in my comments earlier, its entirely up to you how you want to structure your code.
Thanks for reading.
I get a lot of questions about why to use an interface. I think this article will explain it very well.
Understanding use of Interface and Abstract class
Thanks for a great post. I think it’s important to understand the repository pattern other than just using interfaces. I wish you could write more about this in the article.
Consider that a case can not be refactored out and you have to use more than 5 repositories in a single controller… What are your thoughts about this? The code will looks bulkier to me under the _construct method, and most of my few devs would say that it’s not pretty at all…
Wouldn’t it be a better idea to set the model inside your constructor, what if you refactor the model, you’d still have to update it across all your repository methods?
“`
namespace App\Repositories;
use App\Comment;
class CommentRepository implements CommentRepositoryInterface
{
// Must use all methods that were defined in the CommentRepositoryInterface here
public function all()
{
return Comment::all(); // Move comment to constructor and use `$this->comment->all()` ?
}
}
“`
Yes, that will be a nice approach. Everyone has a different version of implementation. It’s totally up to you how you want to use it.
I normally create a BaseRepository and pass the model to the constructor. Then I extend BaseRepository and inject the model in it.
So great and clear explanation. Hope to see more posts about other design patterns.
I have create a package to generate files as repository patterns structure
https://github.com/mshamaseen/laravel-repository-pattern which make follow repository pattern easy.
All contributors are welcome
It’s great! Super simple to understand and described step by step. Thank you
It’s hard to read the post. because of the following.
“`
$this->post->update($data_array);
$this->post->delete($post_id);
$this->post->get($post_id);
“`
I have one confusion in post controller, when you injected the PostRepositoryInterface in constructor and then used the functions of PostRepository class.
We used the interface in the controller which was implemented in the repository. Through this, we got access to repository functions.
Please read more about Dependency Injection.
Thanks
We have built a PHP package for Laravel and use it for our projects.
Please check it out!
https://github.com/awes-io/repository
In order to work this, we need to register the service provider. in app/config.php
[
/*
* Laravel Framework Service Providers…
*/
…
App\Repositories\BackendServiceProvider::class,
…
],
Thanks for the greate tutorial,
This helped me to understand the whole repository pattern and you explained it in simple way. Thanks alot.
But now can you help me on how to include database transactions when users post form data and operations are to be perfomed in more than one table.
For me i think we don’t inject the interface , but we inject the Class who implements the interface cause by default we can not instantiate an interface
So it should be like this
public function __construct(PostRepository $post)
not
public function __construct(PostRepositoryInterface $post)
Classes that implement PostRepositoryInterface have as parent PostRepositoryInterface so you neet to write:
public function __construct(PostRepositoryInterface $post)
and assign the repository you need in a Service Container.
Hello, thanks for a great article. I am new to repository pattern and this article has helped me understand a lot.
I have one confusion though. If I understood correctly, the PostRepositoryInterface and CommentRepositoryInterface is basically doing the same thing, no? In that case can PostRepository and CommentRepository perhaps implement the same interface? Maybe both implement a generic RepositoryInterface? Is there a reason to keep both interfaces separate?
Thanks so much.
You should also add in the article that you need to register the BackendServiceProvider in AppServiceRegister, else it won’t work.
Could you please fix your php arrows in your code examples, thanks.
Will update that. Thanks for pointing out.
Very good article and easy to understand. My only question is, do you know any disadvantages using repositories? Is it possible being any scenario when highly not recommended using it?
Thank you for this article!
I have a question if i may: why did you first create the contract and then implement it ? couldn’t you just create the class directly since that contract interface won’t be implemented by any other repository class ?
What’s the benefit of making an interface? Coz for me its like an extra work.
This seems more delegation than an implementation of the repository pattern. It is also highly repetitive. Also, a class that accesses more of its dependency data than its own, suffers from Feature Envy Smell.
It’s great. For the third month now I’m going to write my application and your lessons are just perfect. Thanks for the work! Do not stop!)
maybe forget to give the post id parameter.
Hey,
Wonderful read.
Just one thing that I noticed, isn’t your update method expecting two parameters?
public function update($post_id, array $post_data)
{
Post::find($post_id)->update($post_data);
}
.
.
$this->post->update($data_array);
Sorry if I am wrong. It might be my limited knowledge of PHP.
which package is used for artisan command for this repository??
No package, manually creating repositories.
And if I want to create a BaseRepository that implements and interface and this BaseRepository use it in 3-4 repositories, how can I do? If I create a BaseRepository that implements the interface, and in this BaseRepository inject the Model Class, the project crushes telling “Target [Illuminate\Database\Eloquent\Model] is not instantiable while building”
And I don’t want to create one interface and one repository for every model, isn’t a good practice and you’re not avoiding the DRY principle
What’s the use of interface? Why don’t use just the repository classes?
Hi excellent explanation about laravel repository …can you please explain with the contracts and facades
Awesome article, can you please add other design patterns as well.