150
Php

Laravel – Using Repository Pattern

Laravel is one of the most popular PHP MVC frameworks and taking the Php community rapidly than any other frameworks probably couldn’t do and it’s because of a great combination of power, extensibility and easiness. The framework provides so many ways to a developer to develop an application using one or another, depending on the size of the project developer can use any possible way that Laravel provides and project of any size fits well in Laravel. One of the most popular ways for building an application using Laravel is the Repository Pattern and use of this pattern has a lots of benefits and most of the developers follow this pattern to build an application using Laravel.

The fundamental idea or the primary goal to use this pattern in a Laravel application is to create a bridge or link between application models and controllers. In other words, to decouple the hard dependencies of models from the controllers. In a typical Laravel application one may use some thing like this in a controller:

There is nothing new for a Laravel user, in that controller method, the User model is being directly used to get all the users from the database and this User model basically extends the Laravel’s Eloquent ORM which is a common approach in any Laravel application because models that interact with database extends the Eloquent.

So far, everything is good and this code is correct and will work as expected but still the code is not quite perfect and it’s using the User model directly from the controller and manual access to the data layer from a controller violates the law of good design. It’s bad and known as anti pattern because the controller has hard dependencies on the User model and hence it’s tightly coupled to each other and that’s why it’s hard to test (unit testing). To, overcome this problem, a repository comes in to the play and a repository is just a normal class with methods to access the data layer (User model here) and the controller uses this repository to interact with the model instead of directly using the model by itself. This is an example of a repository (UserRepository) that the UserController can use to interact with the User model:

This repository could be injected into the UserController during the initiation of the class using the __construct() method and this is possible by type hinting the UserRepository class like this:

This is the UserController class now and it has a dependency on UserRepository and this dependency would be injected into the class during initialization by the smart IoC container component of the framework automatically. While this will work and hard coded dependency is replaced using the repository but still now the UserController class is indirectly dependent on the User model because the UserRepository class depends on that model and testing is still hard. So, to overcome this situation, an Interface can come to the play. While the primary goal of an interface is to build a contract with the class that implements the interface and it’s a very commonly used approach, in most cases for public API to ensure the correctness of an application that uses the public API where an interface defines the behavior of a class by declaring methods and the class that implements the interface must implements all the methods declared in the interface.

An interface says, β€œThis is what all classes that implement this particular interface will look like.” Thus, any code that uses a particular interface knows what methods can be called for that interface, and that’s all. So the interface is used to establish a protocol between classes.

While this is true that an interface is like a contract but also there are other things an interface does. It is being used an abstraction layer between the consumer class (UserController that will use the interface) and the concrete class. Here, concrete class refers to the class that implements the interface (an abstraction of the concrete class). In other words an interface hides the details from the consumer class when the interface is used to type hint the data type as a dependency of the consumer class. Let’s see an example to make it clear. First, an interface for the UserRepository class which will be implemented by the repository:

Now we need to implement this interface in the UserRepository class using this:

So, this repository will be used in the UserController but with the type hint of the interface that this class implemented instead of the concrete impletation (this UserController class):

Now the UserController depends on the IUserRepository interface (abstract layer) instead of UserRepository (concrete class) and not tightly coupled with the User model so easily testable as well.

But still it’s not ready to use by the application because an interface is not a class and the IoC container can’t make an instance of this interface and it shouldn’t but the container will try to do it because of the type hint and will fail, so it’s necessary to tell the IoC container that, whenever the UserController class is getting instantiated, just pass an instance of the concrete UserRepository class which implemented the type hinted interface given in the constructor method. So, we need to bind the concrete class to the interface for the IoC container so it can supply the class to the controller and this could be done using this:

So, now the IoC is able to inject an instanse of UserRepository class into UserController class whenever the UserController is initialized. If the repository and interface both inside a sub-directory and has namespace something like namespace Repositories/User; then during the binding it should be used this way:

This could be placed in the global.php file or in another file (create one as app_bindings.php) where this code along with other code (for binding) could be placed and just include that file in the global.php file using require '/app_bindings.php' (assumed the file is in the same folder) or it’s also possible to create a Service Provider so Laravel will register this at the boot up process of the framework. To create a service provider, create a file in the same folder and save it as UserServiceProvider.php and use paste this code:

Then in the providers array in the app/config/app.php file, add this at the last:

Using a service provider is not necessary but a good way to organize things. So, by using an interface we just not created a contract but also the detail of the implementation is hidden (abstracted) from the controller so it doesn’t know anything bout the class is being used behind the scene and this is a plus point. According to the design principles (LSP in SOLID) “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program” which also relates to Design by contract and these rules or principles are obviously for good reason and one of the good reasons is that, now it’s possible to change the implementation of the concrete class of UserRepository with a different one which also implements the IUserRepository interface and hence the controller will work normally because it doesn’t know what is the concrete class is being used for that interface, it’s totally ignorant about that and that’s why we can also test our controller without using a real database because we can pass a mock object instead of original UserRepository class, only we have to implement the same interface and the controller will think it’s using the same thing.

So, for example to use a different implementation of the interface we may implement another repository by implementing the IUserRepository interface and just can change the class/repository binding for the container and we don’t need to touch our controller code. FOR example if we implement something like this:

Now, in the service provider we only need to change the binding:

That’s it, this is now more maintainable and easily testable because of the use of abstract layer (interface) instead of the concrete type.

Another thing we can do in our repository class to use the methods of Eloquent (User) model, for example, from our Usercontroller class we can’t use UserRepository::with() unless we declare that method in the class but it’s possible to use those non-existing methods (in the repository) using __call() magic method like this (also a constructor):

So, now we can use all the methods of User model from the UserController (if required) as if those methods are declared in the UserRepository while they are not. For example:

This may not required when we use the repository pattern but it’s just an idea to use model’s methods easily.

The Repository pattern is not limited to Laravel or PHP but it’s a widely used software architecture or design pattern used by developers using various languages.

So, finally, it’s not important that you must follow the rules and principles in every project but it’s a good practice but if you don’t use it, it’ll still work and it’s not a sin, you should decide what to do and how to do it and by following some rules blindly doesn’t makes any sense, it may create problems if applied inappropriately, so why not use your sense without blindly following some pro, some one said it’s good practice so I’ll do this, if this is the case then it’s not good at all. I always like to find alternatives and think as what if, Oops! it’s too much…

  • Very nice. I wish Laravel enforced developer to use repository pattern (and also Entities). It’s better for unit tests and responsibilities isolation.

    • @evaldojuniorbento:disqus , Thanks πŸ™‚

      • dammy

        I just recently started trying to work with repositories but I always had d question why, is it useful as its more time consuming than using models in controllers directly but Thanks for helping me understand the usefullness. Great article.

        • Glad to know that it really helped you, this was my goal πŸ™‚

  • Sean Mumford

    One thing I would advise against is to use the __call() function to access the user model directly – your abstraction isn’t just leaking, it’s a broken dam (http://en.wikipedia.org/wiki/Leaky_abstraction). If you want to swap out your storage method in the future, you can no longer rely on the interface to define the contract.

    At best, you have to hunt through your codebase looking for instances where Eloquent is called through your repositories. At worst, your new storage engine is simply incompatible with eloquent-specific functionality. At which point you’ve lost the majority of reason to use a repository in the first place.

    • @seanmumford:disqus, I think you missed this line This may not required when we use the repository pattern but it's just an idea to use model's methods easily. and it’s not recommended but an hecky idea but nothing else. I didn’t tell to use it.

  • Jose Manuel Marquez

    This may be a dumb question, but, for the repository I still need to make the Laravel model right?

    • @jose_manuel_marquez:disqus, Yes, You need to create models, a repository class is a bridge between your controller and model, you should use a model through a repository from your controller.

  • Shekar Siri

    Very well explained, thank you!

    • @shekarsiri:disqus ,Thank you for your interest πŸ™‚

  • Anam

    good read. one thing i don’t understand, how do you eager load the relationships with repositories?

    example:

    $user = User::with(‘posts’)->get();

    how can i load “posts” with user repository?

    • Welcome πŸ™‚ @disqus_nY70Wl4tGP:disqus ! You may use Post::with('user')->get() because in my case posts table has user_id.

    • I may be off here, but the methods don’t have to be the same.

      public function getUsersWithPosts(){
      return User::with(‘posts’)->get();
      }

  • Pratik Shah

    May be a silly one but if there’s a interface IUserRepository and it is implemented by two classes MongoUserRepository and UserRepository and we will bind both of them in container .Now when we use IUserRepository interface as object hinting in Usercontroller then how IOC will know whose instance to be created out of those two class when UserController is being instatiated..

    • You can bind only one class with one key name in the IoC container. In this case the key name will be the IUser interface, the binding is used to tell the IoC container which class should be injected when an interface is being used. Hope I made it clear @disqus_eimKQ7639S:disqus, all the best πŸ™‚

  • Guido Contreras Woda

    The repository pattern is an abstraction of the data access layer. I understand your example is pretty simple, but the use of the pattern is in no way a bridge between the controller and the model. That’s where you’re missing a DOMAIN layer.

    Application layer: Controllers, Views, all that refers to presentation.
    Domain layer: Domain logic. Entities, Value Objects, Services.
    Infrastructure layer: Data access. Repositories, Data mapping services, etc.

    If you skip your domain layer altogether, you’re probably putting domain logic either in your application layer (your controllers) or your infrastructure layer (your repositories). Both cases would weaken your domain model and be a pain to refactor and reuse.

    • Thank you for contributing and yes you are right but my goal was to clarify the use case of a repository class in Laravel application and i didn’t use these terms (Domain layer, Application layer etc) to simplify the presentation because to be honest the MVC pattern become a one of the popular pattern in WEB development and also one of the most misunderstood and confusing term all over the internet and books. So I kept it as easy as possible which may help anybody to practically apply the use of these. Thanks again πŸ™‚

      • Guido Contreras Woda

        Hey, a pleasure to contribute!

        I work on web as well, and I’m currently facing a huge change in development philosophy in my current job as a R&D dev, and one of the big steps towards better design is to forget what MVC forces upon you.

        We tend to talk about the Entities and Value Objects as our “Model”, and reduce our real Domain to a one-on-one relation between classes and tables. At least that’s how I usually see it.

        Cheers!

        • Can you share any reference of that, I’ll appreciate it πŸ™‚

          • Guido Contreras Woda

            The best reference I can think of is Domain driven design, by Eric Evans.
            A lot of online blogs are copying Laravel’s own documentation example (the one found in the IoC container). If you can get a hold of Evans’ book, you’ll find some examples of the Repository pattern within more complex applications.

          • Thanks! I’ll look for this book πŸ™‚

  • Hamid Alaei V.

    If we are using Repository to decouple Controller from Model, then why the repository is still returning Eloquent Models and Collections?

    • Then how would you get the result of that repository method in your controller ? After all your controller needs to be notified about the result, what do you expect in this case, any suggestions ?

      • Hamid Alaei V.

        I don’t know, maybe just returning an array using toArray() is good. Or maybe a presenter class, for which it does not matter whether Model is Eloquent or Doctrine or whatever.

        • Presenter would be fine but if it’s necessary to implement the presenter, otherwise I won’t do extra work, depends on project.

  • Filipe Moreira

    Hi

    Can you please help me?

    Hi have a SliderRepository when i implement this:

    public function save($data){

    $this->model->$descricao=$data[‘descricao’];

    $this->model->save();

    }

    and my controller is:

    public function showWelcome()

    {

    //return $this->slider->get();

    $this->slider->save($data);

    }

    But when i run i obtain the follow error: Undefined variable: data

    what i’m missing here?

    • @disqus_5G5nkqXw4g:disqus, In your showWelcome method there is no $data variable is available. At first You need to populate the variabbe then pass it. For example, $data = Input::all(); return $this->slider->save($data);.

  • Mamluki

    You’v discussesd this like a pro!! Accolades man

  • Keith Penderis

    Trying to understand this , thinking API within an API? my implementation class will manipulate or return original data , the repository class is just a gateway. So I can use it like I would use the view composer file?

    • You can think something like that @keithpenderis:disqus

  • Disappeared

    I’m a noob. Can you explain why you can’t just leave out the binding and instead just inject the repository itself into the constructor insteAd of the interface which requires that extra binding to be put in place.

    • You can do it if you want but it’s doesn’t implement the one of the principles of SOLID (Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion) programming. In SOLID:

      A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
      B. Abstractions should not depend on details. Details should depend on abstractions.

      One of the major advantages of dependency injection is that it can make testing lots easier and produces a manageable code base as well. You can chanhe the implementation easily even without changing the code in your client object, which is controller here.

      Read More about SOLID: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

  • codeatbusiness

    Hi Sheikh, I have a doubt.

    If you need a IUserRepository to not depend on a specific storage method, why not use an Entity StdClass or simple class to model the Domain business logic?

    Sometimes when I see as you show in your code, I think we disconnect from a storage method using the repository pattern but when we inject the Model into our Repositories we are connected based on a Eloquent Entity based model related with an intrinsic storage method. What is your oppinion about it? Is there any form to disconnect from the storage from the Entity class?

    Thanks in advanced.

    • It’s very simple. You don’t depend directly on your storage in your controller. Your controller should be ignorant of storage and according to the SOLID principles, both higher and low level modules should depend upon abstraction instead of concrete class.

      • codeatbusiness

        Many thanks Sheikh, but the question is related with the dependency of the Domain Entity that inherits from the Eloquent Model (directly related with a DB storage method) in the Domain Layer (this layer should not know about the storage method). How can we do to separate this dependency and use after in the DBRepository (located on the Infraestructure Layer)?

        Thanks in advanced and thanks newly for your reply.

        • Well, in this case the “Eloquent/ORM” is not a good choice because ORMs are designed in such a way that it maps a database table. If your Domain entity/model handles data storage then it’s not decoupled from the storage layer. So, IMO, you should use another layer between your Domain Classes and ORM. Instead of making an Eloquent model as an entity, create another class and inject the Eloquent/other storage handler into that class. It’s quite a big thing and not possible to discuss here. Actually, an Eloquent model is not suitable for a domain model in true sense, IMO.

          • codeatbusiness

            Many thanks, your reply is great! I thought about a gateway between them or use the Eloquent Model and the Entity injected into the Repository constructor to pass each parameter but your idea is better. Thanks for all!

  • hackel

    I’ve been thinking about this a lot, lately, and have been thinking the following. When using an ORM like Eloquent, wouldn’t it make more sense to make the Model a plain class that *does* get injected into the controllers, but then have the Repository (interface) injected into the model, which extends Eloquent, to perform all the actual DB work? Thoughts?

    • Sounds similar with different naming of services. We should just better follow the principles and doesn’t matter what we call a particular class and how we implement. Your idea sounds good but in this case, you can’t call it repository pattern tho.

  • Boudewijn Geiger

    If I for example want to fetch models which a users is related to. Should this happen in a separate repository or could the user repository also be used for this? For example: getUserComments()

    • @boudewijngeiger:disqus, Actually, getUserComments() sounds like you want to get comments by a user, so there you can use UserRepo and in this case the UserRepo will use a UserModel which could have a comments method which is a relation to the CommentModel. Read that as User hasMany Comment. That’s it. But it’s not the only way to achieve this. Just think alternatives and find what is best for you. Hope I made it clear.

      • Boudewijn Geiger

        In your opinion should this return only the comments or also the user model?

        • It depends πŸ™‚

          • Boudewijn Geiger

            My user models indeed has comments method, but how would this work? Something like this:

            public function getUserComments($user_id){
            $this->user->id = $user_id;
            return $this->user->comments;
            }

            Now $this->user->id is set to $user_id. I’m not sure if this would be a problem or not.

          • It should work and if it doesn’t then pass the user model, not a very big deal. Also, you can use a view/model presenter.

  • Cherif BOUCHELAGHEM

    I think it’s an anemic model, active record breaks SRP Eloquent is and active record it’s and the access data layer and the domain layer at the same time ,this example is just a layer around eloquent

    • Thanks for your valuable comment, yes it’s just a layer for Eloquent so data access layer is separated from Application logic.

  • Rui Silva

    I don’t understand why, but I can’t get rid of “syntax error, unexpected ‘::’ (T_PAAMAYIM_NEKUDOTAYIM)” after setting the Service Provider. Do you have any clue why this is happening?

    My ServiceProvider:

    namespace Repositories;
    use IlluminateSupportServiceProvider;
    class MainPageServiceProvider extends ServiceProvider {
    public function register()
    {
    $this->app::bind(‘MainPageInterface’, ‘MainPagesRepository’);
    }
    }

    • @disqus_1qaJXmrMqN:disqus, Actually $this->app::bind('MainPageInterface', 'MainPagesRepository'); should be $this->app->bind('MainPageInterface', 'MainPagesRepository');.

  • Roman KubiΕ‘

    Hi.

    I am new in Laravel and OOP and I am making API. I created Class ApiController with loading Larasponse in constructor. Then I created controllers like EventsController or PerformancesController that are extended from APIController. But I dont know how to code EventsController constructor with loading EventsRepositoryInterface because in ApiControllers constructor is not injected EventsRepositoryInterface.

    Thanks a lot for your answer.

    • This looks bad design but you may accomplish that by injecting the dependency in the child constructor, for example:

      class Child extends Base {
      protected $childDependency = null;
      public function __construct(ChildDependency $childDependency, ParentDependency $parentDependency)
      // call parent class’ constructor with it’s dependency
      parent::__construct($parentDependency);
      $this->childDependency = $childDependency;
      }
      }

  • SPeed_FANat1c

    Hi, I came to this, because I am trying to find out what is correct. Putting bussiness logic in models or in controllers? There are some poeple screeming that business logic should be in models. Ok them one guy says – how it will be – everything in one class – sql code and logic. Then he find out repository pattern. Ok so I am now trying to understand – logic should be in repository class? Like you wrote createOrUpdate function. This is just simple one. In real life applications there are much more logic. If this, do this, else do this, etc. But now as you say if there was another class implementing same interface like mongoDB repository of user – then all logic of application remanis the same and code gets duplicated? Or there is mock class which implements the interface of user repository. Actually I dont know much about mock classes, so not sure if we put duplicated code in them also. Or for business logic we should create another class which manipulates with data and uses the repository just to get data from database. But then again – business logic is no more in the models as some guys want. So I want to ask – where to put business logic?

    • Actually, model is not a single class, instead it’s the business model and may consists of more classes. It’s hard to explain everything here but all I can say that, think that you are building an API and it needs to be accessible from external web sites, using ajax or curl as well, so keeping that on mind organize your code. The controller is the HTTP layer which is just a way to reach your domain logic so don’t put anything in controller and keep the classes loosely coupled. All you should think of design principles and in this case read SOLID: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design).

      • SPeed_FANat1c

        Ok, will need to think again. Actually why we are learned things to do wrong from the start its interesting. When I had an internship and started learning mvc – the company gave example of with logic in controllers. Then when I found real job – also logic in controllers. THen in second job – logic in controllers. I dont get why frameworks do not give exmaple how it should be done. One of the reasons may be – to give programmers freedom. But whats the point of doing things wrong and be free.. Or maybe in the end its not wrong – its just prefered style?

        • It’s not recommended to put your business logic in controller but it’s not a seen if do this, just not the best practice but you are not bound to follow these blindly, choose wisely depending on your need. You may break a rule for your benefit but there must be good reason. Regarding MVC, don’t think about whether your following the rule of MVC or not, instead think about better maintainability and scalability of the application. Just think about SOC /http://en.wikipedia.org/wiki/Separation_of_concerns (Separation of Concerns), which is the main motivation of MVC.

          • SPeed_FANat1c

            I asked another guy about this – he says good reason to not use logic in controllers is that controller code is not reusable. If you want to reuse, you have to move out it of controller then, which takes time.

  • SPeed_FANat1c

    Another question: should I name repository class same as model? For example if model is User, then name repository UserRepository? Or name whatever I want because repository can be dependent on few models. And then name it by the business logic it does?

    • It’s just a personal preference.

      • SPeed_FANat1c

        thanks for answers.

        • @speed_fanat1c:disqus, You are welcome πŸ™‚

  • Yoshino

    Very interesting article! I finally understand repositories a bit more thanks!.

    Though for me there is 1 question remaining. Whats the best practice to place the files/folders? Where would you place it? Create a folder in App and place it all in there or? Whats the logical place?

    • Keep repositories in a repositories folder or what you think better fits for your project, just let autoloader load all for you.

  • P@tr1ck

    What could i have forgotten or have done wrong when i get the error “Call to a member function create() on null” ??

    When i diedump $this->user in my controller the ouput is null

    • Then check where you constructed the user, probably it was not injected.

  • SPeed_FANat1c

    Hello, another question – is it ok to generate html string – load view in repository? And then those generated views pass to main view which is loaded in controller? Otherwise there becomes logic in controller, for exmaple subviews of each row – need to run loop in controller to generate them. Also subviews can have their own subviews, so again more logic.

  • SPeed_FANat1c

    And actually in my project I have folder “libraries”. And I so far do not see the difference – in libraries is everything else what is not in controller or model. I was just not using interfaces, but I can start. And then the difference is – then name – repository vs library. Or I am missing something here?
    Usually in libraries I put the shared code which is used in multiple controller, because controller cannot use code from another controller.
    If there is no difference, then I should not even create another folder “Repositories” because if I do – there has to be something different from “libraries”.

  • Juan

    Hello Sheikh,

    I have a question about the repository pattern. I have 2 repositories (Patient and MedicalHistory) and I need know if a patient have and active medical history. I don’t want do this in the controller because I think I will need this in many parts of my app. So I was thinking add it in the Patient repository as a method hasMedicalHistory(), but i want to know if is ok use dependency injection for MedicalHistory in the Patient repository?

    I share part of code for clarity.

    http://goo.gl/s1oczx

    Thank you very much for taking the time to read. Greetings!

    • It’s okay but I would have used it as a relationship model so I could have used it something like this: $this->PaitentModel->medical_history, but looks good.

  • Naren Chitrakar

    How can I implement repository pattern for Events class?

    I have interface that I can use in controller.I use

    AppInterfacesIPost as Post;

    and because I have bind this to my eloquent model

    $this->app->bind(AppInterfacesIpost’, ‘AppModelsPost’);

    but I cannot seem to use this in Events Class it throws an interface cannot be instantiated error. How can I fix thsi?

    • You should bind a repository class not the model. The error is occurring because binding was not made perfectly. Create a class for example,

      namespace AppRepositories;

      use AppModelsPost;

      class PostRepository implements IPost {

      public function __construct(Post $post)
      {
      $this->post = $post;
      }

      public function index()
      {
      $posts = $this->post->all();
      // … return using view
      }

      // Implement all methods…
      }

      Put this class in AppRepositories folder and bind this repository class to the IPost interface, for example:

      $this->app->bind(‘AppInterfacesIpost’, ‘AppRepositoriesPost’);

      Also, run composer dump-autoload and make sure you have used right psr to autoload your classes in Composer.json file. Try to read the article, everything is clearly described. All the best πŸ™‚

      • Naren Chitrakar

        Thanks for the quick reply.

        My mistake I have done the same. it was my mistake in the question. I have used another class I have named it EloquentPost and bind that class to the interface. This is working perfectly in the controller when I use

        use AppInterfacesIPost as Post;

        but again get this error in event class.

        • You are welcome, sorry not sure what you are doing, kind of confused.

          • Naren Chitrakar

            Let me try to explain this in detail.

            I have modules

            The current module is post

            The folder structure is laravel 5 and caffeinated/modules, the folder structure and all working like a charm πŸ™‚

            modules/post

            --http

            ---controllers

            –postController.php

            —routes.php

            –interfaces

            —postInterface.php

            –repos

            —postRepo.php

            –events

            –postEvent.php

            –models

            —post.php

            –resourses

            My postController.php

            postInterface.php

            interface Ipost {

            function getPost( $postId );

            }

            postRepo.php

            use Modules/Post/Models/Post;

            function getPost(){

            return Post::find( $postId );

            }

            PostController.php

            use Modules/Post/Interfaces/Ipost as Post

            class PostController extends ….

            serviceProvider

            $this->app->bind( ‘Modules/Post/Interfaces/IPost’, ‘Moduels/Post/Repos/Post’ );

            Up until this everything is fit and fine. I can use the repository pattern in the controller and everything working like a charm.

            use use Modules/Post/Interfaces/Ipost as Post;

            class PostEvent {

            }

            it throws the interface cannot be instantiated error now.

            what am I doing wrong?

          • You are using the interface in your PostEvent so it may look like this:

            use Modules/Post/Interfaces/Ipost as Post;

            class PostEvent {
            protected $post = null;
            public function__construct(Post $post)
            {
            $this->post = $post;
            }
            }

            In this case, make sure you have the binding exactly using Modules/Post/Interfaces/Ipost as key.

  • Kornelius Satyagraha Ahimsa

    Mr. Sheikh, Thank You for stopping me to pull my hair. haha

    before i’ve problem with binding method :

    Instead of using this below

    $this->app->bind(‘Statistik\Repo\Community\CommunityInterface’,function($app){

    return new EloquentCommunity(new Community);

    });

    My code is like

    $this->app->bind(‘StatistikRepoCommunityCommunityInterface’,function($app){

    return new EloquentCommunity(new Community);
    });

    the second binding code above return Target .. Interface not instantiable on the browser

    • Glad to know it was helpful πŸ™‚

      • krishna

        Sheikh,
        Please put the package structure . or else a sample project which is downloadable. so that we can run the example and understand better

        • @kr@disqus_TDf5KTl694:disqus, I’ll try to create a sample project to download, thanks πŸ™‚

  • Perfect article! Thank you!

    • Glad it was helpful, you are welcome πŸ™‚

  • Andreescu Gabriel

    I was hunting for two days on info about repository pattern and models used with ORMs but I never found something that used Eloquent as the ORM. Your article really put order in my thoughts, and I finally fully understand what ORM>Model>Repo means, I don`t use Laravel but I do use Eloquent. Thank you!

    • Glad to know this was helpful, you are welcome πŸ™‚

  • Safoor Safdar

    Could you please update according to laravel-5.

    • I’ll try it very soon, just need a gap from my current work (for a client) but it works because I’ve upgraded one project (currently working) from this to new version and it just works without any errors but I’ve modified the code a bit for more flexibility without the new features the old one (this example) works with latest official version, so may use it same way, but I’ll upgrade it soon with a bootstrap 3 template and production ready code so taking time. All the best πŸ™‚

  • Kyslik

    Hello Sheikh Heera, thank you for this article in fact I’ve read many similar articles to this one and none answers few questions I have or many people might have.

    1. relations the most important thing Laravel provides out of box no example to be found – I am asking for an example lets say M to N relation – while using repository pattern of course.
    2. How can I pass messages between lets say UserRepository and RoleRepository. By message I mean how do I tie the two together. How does one use instance of UserRepository inside RoleRepository and vice versa.
    3. what about packages that are tied directly to the Eloquent? How do I force packages made by 3rd party use my Repos? – As I think about this it is invalid question, too specific and impossible to answer. So see 3b.
    3b. Is it possible to force L5 use my UserRepository instead Eloquent model? While not to reinvent the wheel – http://laravel.com/docs/5.0/authentication
    4. How can I use scopes with repositories?

    Thank you.

  • Hi @Kyslikk:disqus, sorry for the delay but unfortunately I didn’t understand what you asked, can you please re-phrase your question by spiting each questions? I’ll try to answer πŸ˜‰

    • Kyslik

      Please see edits if question is more understandable :). Thank you.

  • Q-1. A: http://laravel.com/docs/5.0/eloquent#relationship

    Q-2 A: Instead of using two repositories use one Repository and use models as it’s dependencies, i.e:

    use namespaced/classes….

    class UserRepository implements UserInterface {

    public function __construct(RoleIModel $role, User $user)
    {
    $this->role = $role;
    $this->user = $user;
    }
    }

    If you need to use authenticated user then you may use Request::user(), use Request contract instead of Request Facade.

    Q-3 A: Use your custom service providers to override the package’s dependencies.

    Q-5 A: Use method delegation instead, for example:

    class UserRepositoey implements UserInterface {
    public function __construct(UserModel $user)
    {
    $this->user = $user;
    }

    // Imagine you have a scopeMethod in UserModel, named active
    public function activeUsers()
    {
    return $this->user->active();
    }
    }

    I’ve tried to answer according to your question but this is really not possible to describe everything here. Also, don’t box yourself into a rule, you may always use app('someClass') and this is not a bad practice.

  • Basa Gabi

    Hello Sheikh Heera! I really find this article useful though I have a question. Is it possible for multiple repositories to implement the same interface? Base on your example given; class UserRepository implements IUserRepository in which class UserController uses IUserRepository via dependency injection, right? Now my question is:

    1. Could the interface be implemented on other repositories? Ex: I have GenderRepository that implements IUserRepository

    2. If #1 is possible, how would I do that if the interface is being used to be injected on the construct method of the UserController? How would we know what repository it is using?

    Thanks a lot!

    • Welcome! Yes, you can implement more than repository using same contract/interface but there is no way (unless you find out) to do this in Laravel-4 but in 5, you may use http://laravel.com/docs/5.0/container#contextual-binding for this. Probably, you may use a setter injection instead of constructor injection in case of version 4 and manually set the repository at runtime.

      • Basa Gabi

        Thanks you for the response! Where would I place the $this->app->when()…? On the service provider under the register method?

        Given the said code on the docs, if I translate it, is this correct?

        $this->app->when(‘AppControllersWelcomeController’)
        ->needs(‘AppRepositoriesInterfacesMyInterface’)
        ->give(‘AppRepositoriesUserRepository’);

        Thanks so much!

        • Just put it in your Service Provider’s register method, it doesn’t matter at all.

  • ahmed

    Hello Sheikh Heera! I finally found what i’m searching for and finally understood how to use Repository pattern and why to use it i’m not using laravel but you really explain it very well I want to thank you alot about this article thanks man.

    • Glad it was helpful, you are most welcome πŸ™‚

  • By returning an instance of User on getUserById isnΒ΄t your controller still coupled to the Model Class? It is fine using an interface but the return should be also an interface, right? Correct me if I’m wrong.

    • The Interface is switchable and that’s why you may change the implementation for a different object, for a generic result you may use another layer before returning to the client/consumer.

      • That’s what I thougth, somehow you could agree on a defined Domain Model not tied to Eloquent that can be returned, like a POJO in Java, that way it does not matter how the repository implementes fetching the data as long as it returns the defined Domain Model. Thanks for a fine article!

  • Sheikh, Why is it hard to unit test a tightly coupled Controller -> Model?
    Why is it easier when a Repository is in between?

    I create a base model that contains any reusable methods, like “getAll”, all models extend off that.
    Any user specific methods are entered at the bottom of User Model.
    “Repository” sounds like a “helper/library” + “contract”
    Can’t understand how it makes testing any easier. :-/

    • Probably you didn’t read the post properly, hard coded classes are dependencies to a top level module so it’s hard to swap at run time.

      • Thanks for the reply. I believe I need more experience testing to truly understand. πŸ™‚

    • waterloomatt

      One of the main reasons is during testing you usually want to use mock objects which don’t actually hit or modify the DB. You want to be able to run the test over and over again without worrying about duplicate constraints or contaminating your data. Ex. you’d switch out User for MockUser which also implements the IUserRepository and your controller would be none the wiser.

      • Btw, the repository also abstract away the persitant layer and useful for domain driven development. but this is not always the case. Here I only demonstrate the use exclusively for Laravel. Otherwise a repository should return native data types (array) instead of Eloquent/collections.

  • Rehana Chowdhury

    well

  • Fahim Durrani

    What a thoroughly descriptive article! Awesome work.

  • Николай Π™ΠΎΡ†ΠΎΠ²

    Hello !
    What about a generic repository.

    There is just 1 repository, and no interface because inside it we place a modelMap, so at the constructor of Repo we say as text the model name:

    Then we use the phalcon modelsManger to load the model and do operations.Also because of that every method returns “$this” , we can make a methodsChain.
    Ofc I need to setup an error’s handling but …

    I have never used repositories, so want to hear some opinions.
    The example that I’ll place here is with Phalcon:

    At the Controller:

    private $repository;

    public function initialize()
    {
    $this->view->disable();
    $this->repository = new GenericRepository(‘band’);
    }

    public function indexAction()
    {
    echo $this->repository->setCriteria(array(“band_id = ‘1’”))
    ->findAll()
    ->getMembers()
    ->returnAs(‘json’);
    exit;
    }

    Repo:

    class GenericRepository extends Component
    {
    private $model;
    private $results;
    private $criteria;
    private $modelMap = array(
    ‘Academy’ => ‘ModulesEngineModelsAcademy’,
    ‘Book’ => ‘ModulesEngineModelsBook’,
    ‘Band’ => ‘ModulesEngineModelsBandsBand’,
    );

    public function __construct($modelName)
    {
    $this->model = $this->modelMap[ucfirst($modelName)];
    }

    public function setModel($modelName)
    {
    $this->__construct($modelName);
    return $this;
    }

    public function setCriteria(array $criteriaData)
    {
    $this->criteria = $criteriaData;
    return $this;
    }

    public function findAll()
    {
    $loadedModel = $this->getDI()->getModelsManager()->load($this->model);
    $results = $loadedModel::find($this->criteria);
    $this->results = $results;
    return $this;
    }

    public function findFirst($makeChain = false)
    {
    $loadedModel = $this->getDI()->getModelsManager()->load($this->model);
    $results = $loadedModel::findFirst($this->criteria);
    $this->results = $results;
    return $this;
    }

    public function getMembers()
    {
    if (empty($this->results)) {
    return false;
    }

    foreach ($this->results as $obj) {
    $members = $obj->getRelated(‘members’);
    if ($members->count() > 0) {
    $resuts [] = $members;
    }
    }

    $this->results = $resuts;
    return $this;
    }

    /**
    * @param array , collection, resultSet, Json, Xml
    */
    public function returnAs($returnType)
    {
    $count = count($this->results);
    $arr = array();
    switch ($returnType) {
    case ‘array’:
    if (is_array($this->results)) {
    foreach ($this->results as $obj) {
    $arr = array_merge($arr, $obj->toArray());
    }
    return $arr;
    }
    return $this->results->toArray();
    break;
    case ‘collection’:
    break;
    case ‘resultSet’:
    break;
    case ‘json’:
    return json_encode($this->returnAs(‘array’));
    break;
    case ‘xml’:
    break;
    }
    }
    }

    • Thanks for your participation, anyways, regarding Generic

      repository, yes, that’s possible and sometimes it’s much better to use one generic class/repo to handle the common actions using different models. For example, check this Generic handler:

      class crudHandler {

      protected $model = null;

      public function setModel(Eloquent $model)
      {
      $this->model = $model;
      }

      public function getModel()
      {
      return $this->model;
      }

      public function index()
      {
      // …
      }

      public function createNewModel($inputs)
      {
      // …
      return $newModel;
      }
      }

      This is taken from one of my existing projects (truncated) and I’ve uses a setter to set the model instead of __construct method.

      In the Controller I just use something like this:

      use AppGenericcrudHandlerInterface;
      use Request;

      class MyController {

      public function __construct(crudHandlerInterface $crudHandler)
      {
      $this->handler = $crudHandler;
      }

      public function create(Request $request)
      {
      $this->handler->createNewModel($request);
      }
      }

      So, it depends on the context when to use what, that’s it. Use of an interface is always better than depending on a concrete class. All the best πŸ™‚

  • mak

    Thank you so much my friend.sheikh Heera You saved my life by sharing this wonderful concept about laravel.
    You did well.
    Thank you so much again.

  • Rhea Saade

    I’ve just started your tutorial and it’s really helpfull, but I need to ask,in the beginning, before starting with the interface: I did my controller with the repository file like you did it, but in this case what my route will be? before repositories it was: Route::get(‘/users’, ‘UserController@showUsers’);
    but now i am getting this error: Class AppHttpControllersUserController does not exist

    Your help is needed!! Thank you in advance.

    • It’s still the same, Controller’s will use repositories but route declarations are still the same.

  • Divo

    Gracias for this awesome article. Just from your introduction I see you have good understanding of software development principles and so I just had to come and comment even before reading the whole article. Laravel is awesome and make me enjoy development all the more. Keep sharing. Thank you.

    • Thanks @@disqus_UxCwaFi0Ha:disqus. Glad to know that you enjoy coding with Laravel. I just try to learn and share. All the best πŸ™‚

      • Divo

        Works well in Laravel 5 with a few modifications. Now suppose I have 2 or more interfaces and repositories with similar methods. What can I do to address such duplication so I don’t find my self implementing the same
        methods in separate repositories?

        • Hi @d@disqus_UxCwaFi0Ha:disqus! You can create an abstract base repository to store common methods so each repository may extend thee base repository, that’s one way I think you may go πŸ™‚

          • Divo

            Thanks. I gonna experiment with that.

          • You are welcome πŸ™‚

          • Divo

            Hello. I am advancing with my laravel project but I got stuck somewhere. I have a form which I am using to edit users information. During validation failure, all changes made to the form are lost because the form is repopulated with information from the database. When I used form model binding on another form, the edit form is repopulated with the changes the user has made and not with the info from the database. How can I implement this same logic on this other edit form. I am using raw html on this edit form. Something like

            name }}”
            id=”name” class=”form-control”/>

          • Divo

            I found the solution after asking on stack overflow. I needed to do:

            name) }}” id=”name” class=”form-control”/>

          • Glad to know that πŸ™‚

          • Divo

            Thanks to your post, I have been able to create repositories for my project and now appreciating how loosely coupled my code is. I have just two questions.
            1. I have a repository where I am doing something like Unit::method in about six functions. It is better to inject this in a constructor like
            public function __construct(Unit $unit){ $this->unit = $unit }. If yes? why?

            2. A maximum of how many methods would you want to see in a typical controller.

            Thanks

          • 1. Yes, use __constructor injection instead.
            2. I depends, 6/7 would be good, more methods may make your class messy.

          • Divo

            Thank you so much. Why is it better to use constructor injection?

          • If you need to use any object in more than one or two methods then you should use a constructor injection instead of multiple method injections.

          • Divo

            Creating an abstract base repository works well. Thank you so much.Your help has been phenomenal.

          • Wow! Really glad to know that πŸ™‚

  • karim

    Thank you for tutorial,

    i get confused about MongoUserRepository class, after biding, how could i inject this class into the UserController class. for example suppose the UserRepository and MongoUserRepository classes are required to be passed to the UserController, is the following code will be used to achieve this? How the IoC will know which concrete class to load since i pass to it IUserRepository interface?

    class UserController extends BaseController {

    public function __construct(IUserRepository $user, IUserRepository $mongo_user)
    {
    $this->user = $user;
    $this->mongo_user = $mongo_user;
    }

    }

    Thanks

    • Welcome @karim πŸ™‚

      Anyways, Basically you would bind only one implementation with the interface. Laravel 5 has contextual bindings available but that’s not available in Laravel 4. So, make sure you bind two different interfaces for both Repository or use a different approach, for example, you may use a trait or inheritance mechanism to add extra functionality into an existing UserRepository. Hope it helps. Check the documentation http://laravel.com/docs/4.2/ioc#basic-usage for more.

  • 1p0

    great article. My 2 cents… what about code navigability in IDEs like phpStorm, eclipse PDT, etc? if the controller does link to non injected classes without interfaces, as a direct dependency, you can control+click/cmd+click a method, and the IDE takes you directly to it’s implementation and you can repeat this several times. Now the abstraction does break navigability which is a problem in projects that are old or big or unknown, specially for people that just jump into the team. Yes you can use type hinting in comments to say
    /** @var UserModel $object */
    protected $user;
    And so on, which is a “soft comment default type hinting sort of a workaround”.
    But the most important thing to keep in mind for me on software architecture, is that it should work for us, and not the other way around. And that’s where your comment of “you need to evaluate in a per project basis” comes handy.
    So, great article, and let’s hope IDEs continue evolving to solve this problems for us πŸ˜€

  • mmosw

    Another thing we can do in our repository class to use the methods of Eloquent (User) model, for example, from our Usercontroller class we can’t use UserRepository::with() unless we declare that method in the class but it’s possible to use those non-existing methods (in the repository) using __call() magic method like this (also a constructor):…

    Why do you suggest doing this, it make your repository and controller fully coupled with Eloquent, which only support for certain SQL database? Then how do you implement the MongoUserRepository? Writing new Eloquent model that support mongodb? That is not easy.

    I think you should write this function in your repository rather than in controller.

    // Can access the methods of User model
    public function getUserWithPostsComments()
    {
    $user = $this->user->whereEmail(‘me@yahoo.com’)
    ->with(‘posts’)
    ->with(‘comments’)
    ->get();
    }

    Controller shouldn’t know about eloquent or database query object and repository shouldn’t return anything related to database query or eloquent.

  • Dmitriy Doronin

    Great article! I’m really understood why we should be use repository pattern.

  • Manish Shrestha

    Wonderful!

    • Thanks @@themanish:disqus , it’s too old tho πŸ™‚

      • Manish Shrestha

        Is it? I’ve just started to research on Repository Pattern to build my new SaaS project. Am I missing anything new that has already been introduced to the market?

        • It’s just another design pattern and it’s not the only pattern, use it wisely if needed but don’t make this design pattern a rule. Sometimes it might seem it’s just an extra wrapper but not helping you at all, instead it could be just a trap. Btw, this is an old article so you should research for new ideas for better code separation but it works fine.

          • void9

            Do you recommend some newer articles or tutorials on repository pattern? Btw your article is great !

          • Not really but I’m just telling you that, this is only a pattern to solve specific problem but don’t make it a rule.

          • void9

            I understand. But isn’t this specific problem present in every project? Its just up to us to choose how to handle it?

          • Exactly, it’s up to use how we chose to handle it and the decision should be made depending on the context (the problem domain). So one should not think to apply a design pattern because there is a good design pattern, instead one should think as, if we’ve this problem then we’ll use this approach and that approach could be a good known design pattern or not, just need to set the right direction to think πŸ™‚

          • void9

            Thank you so much πŸ™‚ Since I am beginner I will use your examples in my current project (selling cars and motors) and learn when is good to use them. I don’t have much experience so I don’t know when is some design pattern good and when is not but I hope I will learn soon to recognize when to use which design pattern πŸ™‚

  • Pingback: Unit Testing and Writing Testable Code - with PHPUnit - Manish Shrestha()

  • Pingback: What does it mean to "Program to an Interface"? - Manish Shrestha()

  • Hiển LΓͺ

    I tried many times with other guides which are similare to your post but not successful πŸ™

    In UserController, it always show error:

    Call to a member function all() on null, which means $this->user is null. Why your UserController doesn’t have instance $user, where do you get it? Please help me. Thanks.

    • Do you have bindings in place App::bind('Repositories\User\IUserRepository', 'Repositories\User\UserRepository');?

Latest Blog