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.

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.

Using Repository Pattern with Laravel 5

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:

Repository - Directory StructureBut it can be different, for example if component have configuration options, or migrations, etc.

Inside  src  directory I have three other directories: ContractsEloquent 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:

Repository PatternOf course, each concrete child repository should extend our abstract repository, which implements RepositoryInterface contract. Now, how would you implement this contract? Take a look at first method. What can you tell about it just by looking at it?

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  $columnswhich 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 Repositoryclass 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 Repositoryclass:

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.

Criteria Structure

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