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.

How to use Repository Pattern in Laravel

Spread the word! Share with your fellow developers.

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, Repositoriescreate 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, please post them below.

24 comments on “How to use Repository Pattern in Laravel

  1. 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 ? 🙂

    1. 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

    1. 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.

  2. 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

    1. 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

  3. 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.

  4. 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.

    1. 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.

      1. 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.

        1. 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.

  5. I have a question. Why you inject PostRepositoryInterface instead PostRepository on PostController? After all PostRepository implement PostRepositoryInterface

    1. 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

      1. 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.

  6. 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.

    1. 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

  7. 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?

    1. 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.

  8. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.