Using Repository Pattern in Laravel 5

https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/

Using Repository Pattern in Laravel 5

These days there is a lot of buzz about software design patterns, and one of the most frequently asked questions is “How can I use some pattern with some technology“. In the case of Laravel and the Repository pattern, I see often questions like “How I can use repository pattern in Laravel 4” or nowadays “..in Laravel 5”. Important thing you must remember is that design patterns do not depend on specific technology, framework or programming language.

Contents [hide]

Introduction

If you have really understood Repository Pattern then it does not matter what framework or programming language you are going to use. What is important is that you understand the principle behind the Repository pattern. Then you can implement it in whatever technology you want. With that in mind, let’s start with the definition of the Repository pattern:

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes.

Repository pattern separates the data access logic and maps it to the business entities in the business logic. Communication between the data access logic and the business logic is done through interfaces.

To put it simply, Repository pattern is a kind of container where data access logic is stored. It hides the details of data access logic from business logic. In other words, we allow business logic to access the data object without having knowledge of underlying data access architecture.

The separation of data access from business logic have many benefits. Some of them are:

  • Centralization of the data access logic makes code easier to maintain

  • Business and data access logic can be tested separately

  • Reduces duplication of code

  • A lower chance for making programming errors

It’s all about interfaces

Repository pattern is all about interfaces. An interface acts like a contract which specify what an concrete class must implement. Let’s think a little bit. If we have two data objects Actor and Film, what are common set of operations that can be applied to these two data objects? In most situations we want to have the following operations:

  1. Get all records

  2. Get paginated set of records

  3. Create a new record

  4. Get record by it’s primary key

  5. Get record by some other attribute

  6. Update a record

  7. Delete a record

Can you see now how much duplicated code would we have if we implement this for each data object? Sure, for small projects it’s not a big problem, but for large scale applications it’s a bad news.

Now when we have defined common operations, we can create an interface:

Directory structure

Before we continue with creating concrete repository class that will implement this interface, let’s think a bit how we want to organise our code. Usually, when I create something, I like to think component way since I want to be able to reuse that code in other projects. My simple directory structure for the repositories component looks like this:

Inside src directory I have three other directories: Contracts, Eloquent and Exceptions. As you can see, the folder names are pretty convenient for what we want to put there. In Contracts folder we put interfaces, or contracts as we call them earlier. Eloquent folder contains abstract and concrete repository class that implements contract. In Exceptions folder we put exceptions classes.

Since we are creating a package we need to create composer.json file where we define a mapping for namespaces to specific directories, package dependencies and other package metadata. Here is the content of composer.json for this package:

As you can see, we mapped namespace Bosnadev\Repository to the src directory. Another thing, before we start to implement RepositoryInterface, since it is located in the Contracts folder, we need to set correct namespace for it:

We are now ready to start with the implementation of this contract.

A Repository Implementation

Using repositories enables us to query the data source for the data, map the data to a business entity and persist changes in the business entity to the data source:

First method in our contract is conveniently named all() . It’s duty is to fetch all records for the concrete entity. It accepts only one parameter $columns which must be an array. This parameter is used, as its name suggests, to specify what columns we want to fetch from the data source, and by default we fetch them all.

For specific entity, this method could look like this:

But we want to make it generic, so we can use it wherever we want:

In this case $this->model is an instance of Bosnadev\Models\Actor . Thus, somewhere in the repository we need to create a new instance of the given model. Here is one solution how you can implement this:

Since we declared class as abstract, it means it must be extended by concrete child class. By declaring model() method as abstract we force the user to implement this method in the concrete child class. For example:

Now we can implement the rest of the contract methods:

Pretty easy, right? Only thing left now is to inject ActorRepository in the ActorsController, or our business side of application:

Criteria Queries

As you can imagine, these basic actions are just enough for simple querying. For larger applications you’ll most definitely need to make some custom queries to fetch more specific data set defined by some criteria.

To achieve this, we begin with defining what child (clients) criteria must implement. In other words, we’ll create an abstract non instantiable class with just one method in it:

This method will hold criteria query which will be applied in the Repository class on the concrete entity. We also need to extend our Repository class a bit to cover criteria queries. But first, let’s create a new contract for the Repository class:

Now we can extend functionality of our Repository class by implementing CriteriaInterface contract:

Creating A New Criteria

With criteria queries, you can now organise your repositories more easily. Your repositories do not need to be thousands of lines long.

Your criteria class can look like this:

Using Criteria In The Controller

Now when we have simple criteria, let’s see how we can use it. There is a two ways how you can apply the criteria on the repository. First is by using pushCriteria() method:

This method is useful if you need to apply multiple criteria, you can stack them as you wish. However, if you need to apply just one criteria, you can use getByCriteria() method:

Package Installation

You can install this package by adding this dependency in your composer require section:

and just run composer update afterwards.

Conclusion

Using repositories in your application have multiple benefits. From basic things like reducing code duplication and preventing you to make programming errors to making you application easier to extend, test and maintain.

From architectural point of view you managed to separate concerns. Your controller doesn’t need to know how and where you store the data. Simple and beautiful. Abstract.

You can find this package on Github, where you can check for latest updates and bug fixes. I also plan to add new features like eager loading, caching and some configs so stay tuned by staring the repository. However, if you want to contribute in the development just fork the repository and send PR.

If you have any thoughts or suggestions, please let me know in the comment section bellow. See ya.

Credits

This package is largely inspired by this great package by @andersao. Here is another package I used as reference. Also, I find these articles very helpful:

Creating flexible Controllers in Laravel 4 using Repositories Laravel Repository Pattern The Repository Pattern in Action Laravel – Using Repository Pattern

Full Stack Developer at OLXWeb Developer. Geek. Systematic. Dreamer

SHARE THIS:

LIKE THIS:

Deploy your Laravel 4 application on HerokuSeptember 16, 2014In "Laravel"

Using Repository Pattern In Laravel 5 - Eloquent Relations And Eager LoadingMarch 26, 2015In "Laravel"

Install Elasticsearch on Laravel HomesteadSeptember 12, 2014In "Laravel"

Posted onMarch 7, 2015AuthorMirza PasicCategoriesLaravelTagsdesign patterns, laravel

  • Anderson Andrade

    Great article! I think you drew in my package http://bit.ly/1EuZWyu 😉 . I liked the changes you made .

  • Spir

    What about adding a dynamic finder to the Repository class? ie, something like this: http://laravel.io/bin/Deyv9

  • Andreas Baader

    How do I install this ?

  • Alen Abdula

    Mirza svaka cast!!!

  • Pinoy Camper

    How do you cater a join table?

    • Mirza Pasic

      I’m working on the part two of this tutorial which will cover eager loading, request criteria queries etc.

  • Tomasz Sawicki

    Thanks for the article.

    To fix: – Movie vs Film – “Only thing left now is to inject ActorRepository in the ActorsController” – the screen show FilmsController, and you’re not injecting repository, but model – “Using Criteria In The Controller” – you’re not injecting repository, but model

    • Mirza Pasic

      Thanks for the reply. My logic dictated me to use Movie as name of the Model, and I did at the beginning. But later I used Sakila sample DB to test queries, and they call it Film. That’s the conflict you see 🙂 I’ll update the article accordingly 😉

  • kowal

    What about case if we need joins? You are using relation: one eloquent model to one repo…

  • ovcharenkovv

    Please tell me why the project is positioned as a “fresh air in the PHP” need same enterprise approaches? What benefits we get using the repository pattern with active record?

  • codextends

    How do you deal with Aggregates ? I’ve been trying to make Eloquent fit in an abstract repository pattern for more than a year. Ended up having Service class embedding several Repository classes, one for each model, which felt quite over engineered. Never found a satisfactory solution. Repository pattern is great, Eloquent is an awesome ORM, but I just feel the two don’t fit.

    • Jack

      TL:DR – Most Laravel implementations of the Repository pattern are fundamentally flawed, and it rarely brings any actual benefit.

      Got to agree with this, I’ve always struggled with relationships when trying to use the repository pattern – Something thats easy with Eloquent out of the box.

      I’ve also ended up building services utilising multiple repositories when relationships are involved. In it’s simplest form, if in your application you want to create a movie, and when when creating it, you want to add relationships to the Movie model, (adding gene, actors etc…) I end up with a MovieRepositoryService, that injects MovieRepository, ActorRepository and GeneRepository and end up using each of their individual create methods inside the MovieRepositoryService’s create method, to create what from a Domain or Business perspective is a “complete” movie.

      However this always felt like reinventing the wheel.

      Another issue I’ve always had with most peoples implementation of the repository pattern in Laravel is it neglects one of the main goals of the Repository Pattern. Your application logic should not be tied to your data source’s implementation.

      In the package described in the article an Eloquent object, or a collection of Eloquent objects is returned on all the ‘getters’. This ties our application logic to Eloquent if we use any of it’s specific features.

      What if we wanted to move to Doctrine, or one of our data sources changes to a web API supplying json or XML, or any other source not using Eloquent?

      One of the goals of the repository pattern is to enable you to swap out your data source, without needing to adjust your application logic for greater flexibility. To active this you can’t return implementation specific objects. You need raw data, either an array, or better yet, explicitly defined Entities that your repository populates from it’s specific implementation.

      Data source -> Repository -> Entity -> Application uses entity

      At most an Entity should know what Repository to use to get any of it’s relationships, however, again, we arrive at the conclusion of reinventing the wheel, Eloquent already knows this, and can already do this – So for the most part, we’re just duplicating Eloquent’s functionality, again.

      If I have an Eloquent Movie objects, I can go Movie->actors(); and Eloquent it get the actors for me, to use the repository pattern correctly, I’d have to create a MovieEntity object, which has no direct ties to the data source (Is not a Eloquent object, or contains an Eloquent object) That contains the Repository for Movie, and each of it’s relationship’s repositories, to achieve the same results as Eloquent, it’s all already there…

      Eloquent also provides the equivalent of the “Criteria” concept described in the articles package in the form of query scopes. In Eloquent, I can define a scopeHighestRated() method on my Movies model, and then use it like so: $moviesEloquentObject->highestRated()->get();

      So we’re reinventing existing functionality, again…

      Simply put, I’ve found most peoples implementation of the repository pattern in Laravel to be a fundamentally flawed exercise in trying to shove a large square through a small round hole. A design pattern is support to work for you, and solve your specific problems. If you find yourself questioning the pattern, or failing to see how you could implement it, or what benefit it’s going to give you, then the chances are it’s not the correct solution to your specific problem.

      What does implementing the repository pattern actually get you? Okay you get to resolve dependancies out of the IOC container via an Interface, which everyone is telling you is a good thing and how it should be done. By WHY is that how it should be done? Because it makes your application loosely coupled. You can change the object injected without touching the classes it’s injected to, but whats the point if the object it’s self ties you to an implementation? You’ve not loosely coupled your application at all, cause as soon as you inject anything other than an Eloquent object, and you’ve used an Eloquent specific feature anywhere in your application (Just once!), it’s broke, so what was the point?

      Theres an awful lot of buzz around repositories at the moment – I’d encourage people not use it just because it’s the “in thing” to do, and actually think about what it’s going to do for you, cause in most cases, with Laravel at least, I believe the answer will: Nothing.

      /rant

      • budhajeewa

        I find myself wondering the same.

        How would you implement an actually loosely-coupled repository pattern, allowing for swapping – for an example – MySQL+Eloquent with MongoDB+?

        • Jack

          Hi budhajeewa

          Thanks for you response, whilst it’s been a while since my original comment now, my overall opinion remains the same.

          Laravel as a framework is not suited to the Repository Pattern, and this basically comes down to a decision of Taylor’s when he designed and built the framework.

          Eloquent is an implementation of the Active Record design pattern, and is one that does not complement the Repository Pattern by definition. An Active Record implementation tightly couples your entities with your data layer, the concept in Laravel, is that Eloquent it’s self is your abstraction layer, as it allows a common interface to several database base solutions: http://laravel.com/docs/5.1/database#configuration

          The Doctrine library (Especially when bundled with Symfony2) is an excellent example of a properly implemented Repository Pattern, but this is due to the underlying differences in design. Doctrine is a Data Mapper implementation of an ORM, fundamentally different to Eloquents Active Record implementation. The Data Mapper pattern strongly complements the Repository Pattern, and Repository generation comes as standard with the Doctrine package as a result.

          I’m not saying one is better than an other, they each have their pro’s and con’s, but Laravel is an opinionated framework, Taylor would be the first to say so, and it comes bundled with an Active Record ORM (An excellent one infact!) However, this is not a suitable environment for the Repository pattern. (You can however, swap it out should you really want to)

          There are ton’s of useful articles on Data Mapper vs Active Record for ORM’s if you want to learn more about the differences.

          Let me know if you have any more specific queries!

  • Guido Contreras Woda

    TL;DR:

    I’d strongly suggest not using RepositoryInterface nor an abstract Repository class.

    Here’s why…

    Let’s talk abstraction through classification first. When you declare a RepositoryInterface, you are saying that all children of that interface (either abstract or concrete) will “be a Repository”. But Repository is a pattern, not a classification. So being a pattern has no real meaning but the motivation behind the pattern itself, that will be communicated through the name or namespace anyway. In other words, “being a Repository” could be conveyed by naming a class “FilmRepository” without the need for a classification, as being a Repository is fullfilling a certain pattern’s motivation, not being part of a certain group of things.

    Now, let’s talk about abstraction through generalization. The way your blog post starts, it’s clear that you don’t have a real motivation of generalizing: you start off with a general idea, an interface, but you don’t really have use cases where this general idea came from. You assume that all children of this interface will need to provide at least those behaviors, and that’s where everything starts to fall apart. Generalization – or any kind of abstraction – shouldn’t start through assumption, it should (as Kent Beck says in XP) be used when it provides simplicity. By adhering to your interface, I’m forcing myself to some specific behavior, assuming I’ll need it in every Repository I ever need, and in exactly the way you created it. The comments you received are a strong hint towards that: people start wondering how they’ll solve their specific problems whilst also adhering to your contract. That’s because they don’t really need your contract, but they’re forcing their minds to it, and that created unnecesary complexity.

    Now, let’s talk about your abstract class Repository. Here you decided to provide some implementation to the mix, because Eloquent behaves pretty much the same way in every class that inherits from it. This will bring a plethora of problems, and I can speak of them with confidence: I’ve done multiple projects with base Repository abstractions and Eloquent, and I’ve moved away from both.

    First off, and I think this is the most important one, you’re missing the point of using an Active Record. AR brings a lot of power, flexibility and speed at the cost of having multiple responsibilities in those objects. If you use AR in its full potential, you’ll be able to access your data in a more flexible way, and you can build over it without the need for collaborators. Now, this is not againt the Repository pattern per se, but against a generic abstract Repository that does some things out-of-the-box.

    The next thing that worries me is reuse through inheritance. Although we do it in Eloquent context, I strongly advice against any code reuse through inheritance: Always reuse through composition and collaboration. What if I need to do something slightly different on find() ? You’ll probably call parent::find. Then, if you add up a layer (say, cache, for example), you may end up doing multiple parent calls, and tracing that will be horrid. And don’t get me started on testing it!

    A “common way to access Eloquent models” could be abstracted out to its own class (not abstract). This could help CRUD app makers in having standard access to any Eloquent model without worrying about exactly what it does. A FilmRepository could use this CrudQueryBuilder (I’m just throwing names here) as a collaborator to have generic access, without being coupled to it (or it’s methods’ signatures) through inheritance.

    I do recommend declaring interfaces for each specific repository implementation. a FilmRepository could be implemented by an EloquentFilmRepository, and declare only what the app really needs from films: maybe you don’t list them all, as that would kill your server, and you only have a paginate and a find method.

    Hope it helps! Cheers 🙂

    • Cătălin Georgescu

      Any sample code to drive your point home? You made me curious.

      • Guido Contreras Woda

        Hey! I’m back from vacations and swamped with work. I’ll make a gist when I get some free time!

        In the meantime, what are you interested in exactly? My point was that reusability through inheritance and sharing types between Repositories wasn’t necessary, but if I were to make some sample code (like suggested maybe with the CrudQueryBuilder), it would look similar to the abstract Repository class implemented here. It’s not that much about the code itself, but about how and when you choose your abstractions, and how you reuse your code.

        Cheers!

        • Cătălin Georgescu

          I’m fairly familiar with the pattern implemented here, but I would be interested in a more flexible way to do this, because being constrained to always implement the methods when you create a new repository for a new entity is not very cool, though Mirza’s implementation helps a lot. So when you have some time an example would be welcome. And thanks for answering.

        • Will

          Just replying here so I get notified if/when you post an example, thanks 🙂

          • Chu Quang Tu

            One year ago and still no example =))) Talking is always the easiest part

          • ghostme

            lol

          • Nguyễn Hiệp

            strongly agree =))

          • Aldrin Marquez

            ikr lmao

        • Bill Garrison

          I would also be extremely interested in seeing an example of this. I’m still wrapping my head around repository pattern and examples help me a LOT

        • Naren Chitrakar

          So what you are saying basically is that the inheritance should never be used to reuse stuff and be solely used to represent something totally non-generic..in the case above..not to query database. And it seems like you are suggesting to let eloquent classes do what they do best in the concrete class in itself. But does not that makes the whole point of replacable data access layer a moot point?

          • Guido Contreras Woda

            That’s a great question! It always depends on context. If we use inheritance to reuse code, we are coupling very hard to that code: we statically couple to a concrete class by inheriting, and we dynamically adhere to represent its parent because Liskov. How awkward could it be to receive an instance of ActorRepository when you were expecting a FilmRepository? Of course this gets solved by type hinting the concrete child where you need it, which makes evident my initial point: there is no real use for the shared type.

            Now, when I said Eloquent does this best, what I meant is that you don’t need the common ground, because if you look at the proposed abstract Repository, all methods act as a proxy to the Eloquent instance. This is what I also meant when I analyzed abstraction through generalization: this is not a generalization at all. There is no real use case, you are just building Repositories imagining what you’ll probably need from them. And, guess the acronym? Right! YAGNI.

            If you aim to go the full RAD, fast development lane with no care for architecture and testing, then you’re better off just using Eloquent through Facades, it will get you there faster. If you aim to use the Repository pattern to abstract your data access layer, my point is: you don’t need common ground between your repositories. Implement data access methods only when you need them, and avoid overuse of inheritance when you actually want to decouple.

            And, if you want to go a step beyond, check out http://www.laraveldoctrine.org and hit me at our Slack channel, maybe I get you interested in trying something different than Eloquent. 😉

    • rocketshipinspace

      Absolutely agree with you here. I am terrible at putting my thoughts to words, but you’ve just described my personal opinion/findings perfectly.

    • chown

      it would be good if you can show us some proper way then like how writer described his point of view in details above?

    • Davide Pugliese

      I was looking for info on this pattern and symfony and I read this post. I partially agree with you about simplicity, the idea here however, is more to put together blocks of code that have a common topic. So we are gonna have with files FrontControllers in my case that just redirect calls from the view to the Repository and then to the Model (Entity). Now, I get your point that in some cases this might not be needed and we add one more “layer of complexity” sort to speak. However, think of an application as big as Facebook like the one I am working on right now, and I can guarantee you that having the code as well organized as possible is a desirable thing. The code ends up being more reusable. You end up with more cohesive blocks of code.

      • Guido Contreras Woda

        Hi, Davide! This is a two year old response, so I’ll try and remember what I was thinking back then.

        I would never argue against using the Repository pattern, it’s a proven practice that helps projects organize their data access while also representing something in your domain. If used correctly, a repository can actually simplify interaction between domain services and entities.

        What I argued back then, and I still believe in, is that you shouldn’t take these kind of generalizations and bake them into any project. You should know about them and you should be watching over your code so you can abstract if and when you need to.

        Most frameworks provide these abstractions anyway, so maybe I’m just being picky. But in my experience, I’d rather postpone writing all of this code until I need it. The best decision you can make depends on the amount of information you have, and being early in the project, you know nothing. Don’t assume you’ll need it.

        • Albert Cloete

          The way this article explains it is very similar to how Symfony implements it out of the box for you.

          I agree with not writing things until you need them, but some basic things are very unlikely not be be used, like findById(), findAll(), etc. And even if you don’t initially put them in an interface, I’d suggest putting it in the interface as soon as you do create those methods, just to make sure all your repositories stay uniform, and act predictably.

          My feeling is that repositories become a mess without contracts.

  • Tim Sims

    Hi, how can you cache result (I’m adding a Cache layer on Repository ) with criteria queues?

    Without criteria, I can easily generate a cache key by the params, so next time when I pass the same params I can generate the same key to fetch data from cache

    But with criteria, I can’t access to those addiction params

  • thbt

    These kinds of articles should really start with a note that explains that the Repository pattern isn’t something everyone should use in all their projects without thinking whether it’s beneficial for their particular situation. There is a tendency for some devs to try to apply every pattern they learn to every situation.

    So keep in mind that using a repository adds a significant amount of complexity above simply using something like Eloquent directly, especially if you try to completely isolate the model so that all interactions have to be done through the repository. There are situations where you need that separating barrier and you really want a layer of isolation between your business logic and the data source. And the Repository is something that web devs should at least be aware of so they know to use it when they need it. But if your app doesn’t need that separation, adding it for no reason can make a simple app far more complicated than it needs to be.

    • Jay Official

      Very True! couldn’t agree more

    • Mateus Gomes

      I do agree that using Eloquent directly is far more simple. But it gets really bad when you decide to change from Eloquent to another ORM or don’t use an ORM at all. Please keep that in mind. Personally I prefer make things a little bit harder first so I won’t (possibly) waste a lot of time later.

  • isaackearl

    Hi. I’m working on an API and realized recently that we need an abstraction layer for complex queries so we don’t have to use the models directly in our controller. Your repository package has caught my eye and I’ve started to work on implementing it.

    I’m wondering if there is a way with criteria to pass in parameters? I want to create criteria but I want them to be a bit more flexible, and I don’t understand from the examples if this is possible.

    For example I’m currently using eloquent scope queries to handle custom criteria. I want to move that logic to my repository through criteria… and I’m not sure if it is possible.

    public function scopeBeforeId($query, $id) { if ($id > 0) { return $query->where(‘id’, ‘<', $id); } return $query; }

    in the example I see a way to make a similiar criteria with a hardcoded $id… is it possible to pass variables to the criteria when you apply them?

    second quesiton: Is it possible to load certain criteria on every load of a particular repository? To do that do I just override the constructor and add criteria there?

    thanks! and great work.

    • tooleks

      Yes, you can pass parameters into the criteria constructor method.

      class LengthOverHours implements CriteriaInterface { private $hours;

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

      public function apply($model, Repository $repository) { $query = $model->where(‘length’, ‘>’, $this->hours); return $query; } }

      $this->film->pushCriteria(new LengthOverHours(2)); // Passing variable into the criteria. $films = $this->film->all();

  • Luddinus

    So, in this case, what would you need “MovieRepository” instead of use always a BaseRepository passing a model?

  • Sanmen1593

    Hey… I’m just reading your article and trying to learn. Just have some question… The laravel ORM is not the same thing? What are the differences? What adventages que have of using this or directly use the ORM in our controllers?

    Thanks!

  • Ngoc Phan

    Perfect article

    a little bug

    LengthOverTwoHours implements CriteriaInterface

    should be

    LengthOverTwoHours extends Criteria

    • Teej Ten

      Thank you soooooooo much Ngoc! I couldn’t get an error when I used this code just a bunch of html output gibberish so it was super hard to debug. It is so obvious now why things were not working! Thanks once again, best regards! Tim

  • Partoo Huang

    Thanks for your great post! I use the pattern but found a weird issue,here is the link on laravel.io:

    http://laravel.io/forum/06-26-2015-weird-query-results-when-using-repository-pattern

    Looking forward to your reply.

  • jrean

    Hey @mirzap:disqus, fantastic article and package implementation.

    “Eloquent folder contains abstract and concrete repository class that implements contract…”

    But:

    “class ActorRepository extends Repository {”

    Is within the “<?php namespace AppRepositories;"

    It should be in "<?php namespace AppRepositoriesEloquent;" isn't it?

    It's a bit confusing to me.

    • Mirza Pasic

      You can set whatever namespace you want for the child class of concrete repository implementation. It doesn’t matter. You only need to follow PSR-4 guidelines. For example, if you use this repository package in your own package, you will probably have namespace something like this: ComponentNameRepositoriesComponentRepository

  • Midix

    Thanks, this is great, although I tend to agree with Guido Contreras Woda.

    Also, I too miss request criteria helpers for cases when our business analyst goes crazy and demands that we have a filter for each column in a grid, and then also total count of records before and after filtering. This means running COUNT(*) before filtering, then applying filters dynamically, then adding one more COUNT(*) query. Yack… but business analysts are always right, therefore developers have no much choice.

    Actually, I have implemented criteria builder in my controller helpers for sending simple “a = b” and “a like b” queries from Javascript JSON API and then on the server extracting query expressions from GET and dynamically adding them to Eloquent query builder, and also applying pagination over the filtered records.

    But my solution seems like a quick&dirty hack. It would be great to have some out-of-the box solution done right way with repository pattern.

  • Cuong Duc

    Just a small question: Why does your LengthOverTwoHours class does not implement all methods of CriteriaInterface?

  • developerbmw

    “In other words, we allow business logic to access the data object without having knowledge of underlying data access architecture.”

    Yet your Repositories return Eloquent objects.

    • Mateus Gomes

      There is a difference between business logic and application logic. Could not find any business login in the above examples.

      And, the Eloquent model is returned because it is injected in the repository class. It could return anything we want.

      • developerbmw

        If your repositories return Eloquent objects then code that uses the repository can easily become reliant on Eloquent. For example (taken from the code above):

        public function index() { $criteria = new LengthOverTwoHours(); return Response::json($this->film->getByCriteria($criteria)->all()); }

        It calls the all() method which is Eloquent-specific. What happens if you decide to change your repository to, for example, one that does raw SQL queries and returns POPOs or arrays? Suddenly your calls to all() won’t work.

        • Mateus Gomes

          The repository should return anything that is injected to it. If I am using Eloquent ORM, I will inject an eloquent model on it and use it within my repository.

          In your example, in fact the all() method is an known method from eloquent, but I cant easily implement it on my repository so I can do this:

          $this->filmRepository->getByCriteria($criteria)->all();

          class FilmRepository {

          public function getByCriteria() }

      • Nguyễn Hiệp

        so if using Repository DP, we need to handle business logic completely beyond the application layer (in controller ?)

  • budhajeewa

    Repository::find() returns an Eloquent model object. If I wanted to update that model, why shouldn’t I directly call -> save() on that model? Why should I pass that model to Repository::update()? Should we never touch Eloquent Models directly?

    • Mateus Gomes

      Yes! We should never touch Eloquent Models directly. And that’s why you pass it as dependency injection. For example:

      actor = $actor;

      }

      public function save()

      {

      // here is where you implement the logic to save.

      // since Eloquent ORM already does this, we’ll use it.

      $actor->save();

      }

      }

      Later on you decide that your Actor shouldn’t be save on an RDBMS using Eloquent ORM but instead, you want to save in a .txt in your system. You simple do:

      class ActorRepository {

      private $actor;

      function __construct(Actor $actor)

      {

      $this->actor = $actor;

      }

      public function save()

      {

      // here is where you implement the logic to save on a .txt file

      }

      }

  • LazyLoaded

    Procrastination kept me from reading this for a very long time while I built something similar, a lot of useful insights here. My approach was a little bit different though. I have this idea that REST Controllers should behave like these Repositories. I used annotations and something similar to this pattern to build a generic abstract controller that a concrete controller can extend. The abstract controller comes with generic routes like find, findById, store, count, delete, … (the usual REST actions) Like this pattern, the concrete controller is required to define a model, but in addition to that using annotations, define a url prefix. Your insights are definitely going to help me improve my implementation.

    I particularly like the criteria. My approach uses url parameters to apply criteria like sort, pagination, selection. I basically use this and hack it onto the Builder class. The criteria interface looks much cleaner Cheers, great post

    EDIT: One question though – How would you deal with relationships using this pattern?

  • Eden Chen

    Hi, I’m now trying to use the repository mode in laravel, but I’m wondering what if I use multiple models in one repository, for instance, by default the PostRepository would only be related to the Post model, but if I would try to fetch a certain user’s posts in the PostRepository, clearly I would need to use the User model to make the query condition, so should I just add a function like getUserPosts() in the PostRepository class and inject the User model to achieve my purpose(fetch a certain user’s posts) or there’re other better ways?

    • ghostme

      I think you can communicate between repositories. So basically after defining both the PostRepository and UserRepository class, you can call the getUserPost() method of the UserRepository class from the PostRepository

  • Janzen Zarzoso

    I have questions:

    1. Shouldn’t the LengthOverTwoHours extend the Criteria and not implement the CriteriaInterface because it’s defining the “apply” method from Criteria and not defining any from CriteriaInterface?

    2. In Criteria you declared “apply” method with params but when declared in LengthOverTwoHours the $repository isn’t used anywhere. Shouldn’t that method omit the reference to the $repository instead? If not, why do you need the reference to that object?

    • Alex Muller de Jesus Sousa

      I do not know if this answers one of your questions, but the ‘applyCriteria’ and ‘getByCriteria’ methods use the second parameter of the ‘apply’ method of the ‘Criteria’ classes.

  • P3terSoft

    I want to do a query like this

    Select * From Users Where state IN ‘Miami, California’ Order By id limit 12

    for example, how can do with this repo in my controller ?

  • René

    At the makeModel() method in your abstract Repository class you start typing this at some point:

    return $this->model = $model->newQuery();

    This doesn’t work and needs to be:

    return $this->model = $model;

    Like you do in the beginning. (this is also the way it is in your github package)

  • Jordan Plamondon

    Hi, why should I use your package instead of this one? https://github.com/andersao/l5-repository

  • bhaskar

    Hi guys,

    Can we call pushCriteria() two times in controller function? I want reports filtered by message and notification respectively. function index() { $this->mnr->pushCriteria(new FilterMnrByMessage()); $msg_reports = $this->reports->all();

    $this->mnr->pushCriteria(new FilterMnrByNotification()); $notification_reports = $this->reports->all(); } Thanks in advance. BJ

    • Liam Andrew Maddison

      CHANGE TO:

      function index() { $this->mnr->pushCriteria(new FilterMnrByMessage()); $this->mnr->pushCriteria(new FilterMnrByNotification()); $notification_reports = $this->reports->all(); }

    • Dave

      I got also this problem. Don’t know the fix either.

  • Miguel Stevens

    Very nice article! But why is the $app variable needed?

  • Majd Alhayek

    Great package! Just cerious, why would you need Repository passed to the apply method in the Criteria abstract class? Also, I recommend extracting the pagenate methout out of the RepositoryIntrface. I would make a new interface and put that method by itself in there “i.e RepositoryPagenateInterface”. Not all implementation need pagination.

  • Alex Muller de Jesus Sousa

    Hello friends,

    I followed all the steps but in the end worked only the classes of repositories. The criteria classes did not work, so I discovered that the ‘LengthOverTwoHours’ class was implementing the ‘CriteriaInterface’ interface when it should extend the ‘Criteria’ class. I noticed that the ‘Criteria’ class is an abstract class that represents the ‘Criteria’ class types that are passed by parameter in the ‘getByCriteria’ and ‘pushCriiteria’ methods of the ‘Repository’ class, so I changed the ‘LengthOverTwoHours’ class and It worked. I followed the same logic for the other criteria classes I created and everything works perfectly.

  • Ivana Momcilovic

    Hi, I have a specific situation where I need to execute one Criteria over the Repository and after that I need to get some results and call different SearchCriteria over the same Repo. Is there any chance to add something like removeCriteria as oposite of pushCriteria?

  • Roman Fandeev

    Thanks! Very informative!

  • Preetam

    I have used your pattern is my project, its really very fantastic an time saving. I have a doubt, can you tell me how can i use join queries using this repository?

    • Manish Shrestha

      You can use criteria for that.

  • Bishal Paudel

    Do you actually require Criteria Interface and its implementations? I would go by creating a bunch of criterias which are simple functions. I may need to group them by class, which is still unnecessary, especially when PHP does not require us to be pure OO, and provides plenty of room for functional programming.

  • Sergej Fomin

    Hello! Thank you for this article! Where can I can i read about this method “find” you are using here: “return $this->model->find($id, $columns);” ?

  • Francis Rodrigues

    There are some problems with your code. The “apply()” method has been added in “Criteria” class and not in “CriteriaInterface” class, so it is not possible to implement Criteria ” class.

  • Francis Rodrigues

    Could you please help me develop a relationship search for another model (related table)? I think we could do more sophisticated searches using “with ()” method, etc.

  • Firman Taruna Nugraha

    your presentation is good man, thanks

  • Rob Bennett

    Hi, just came across this, great pattern, thanks!

    Just a quick question, shouldn’t the resetScope method of the repository set the criteria collection to an empty collection? Doing this allows for the query scope to be reset on the model instance within a session.

  • Connor Leech

    Do you have any more resources available to understand how eager loading works within the repository pattern?

  • discadaniel

    class LengthOverTwoHours implements CriteriaInterface must become ===> class LengthOverTwoHours extends Criteria

  • Sonar

    very inspired article.

    But how can i do for updating multiple data with Repository Pattern ?

  • Max Sky

    Hi, I translated this article into Chinese, can I post to my blog?

  • Deep Dhaliwal

    Hello sir, I need your help,

    I implemented the repository pattern like suggested in this tutorial, I am getting a problem.

    $current_candidateList = $this->candidateListRepository->find($request->get(‘current_candidate_list_id’)); $new_candidateList = $this->candidateListRepository->find($request->get(‘new_candidate_list_id’)); //

    * return $current_candidateList works * return $new_candidateList does not works * if i remove logic to retrieve $current_candidateList, $new_candidateList start working

    In other words, find is not working once it is used twice in single method

Post navigation

PREVIOUS

Last updated