Repository Design Pattern in Laravel

Repository Design Pattern in Laravel


The repository design pattern is one of the design patterns in Software design pattern paradigm. As far as we know, Software design patterns are the some best practices for designing & maintain code in a better and reusable way. It makes software development easier. The design patterns are language-independent. Each design pattern will guide us to follow best practices during software development in PHP, C++, Python, C#, Java or any other languages. In this article, I'll discuss Repository design pattern in Laravel with question-answer way. So, it will be well understood for you and help you to implement it in your project if needed. Here I'll answer the following questions given below to describe & show you the implementation of Repository design pattern in Laravel.

 

Table of Contents

  • What is the Repository design pattern?
  • What are the benefits?
  • How to implement the repository design pattern in Laravel?
  • Why interface needed in repository design pattern?
  • Should I use the repository design pattern in my project?

 

What is the Repository design pattern?

The repository design pattern is an abstraction of the data layer, it acts as a middleman or middle layer between the data and access logic.

 

What are the benefits?

  • It makes code reusable, clean & maintainable.
  • A single place to make changes the data access.
  • It's an abstraction, so it hides the details of how exactly the data is being fetched/persisted from/to the database.
  • It makes code easily testable (It is easy to replace a repository with a fake implementation for testing, so you don't need to have a database available to your unit tests)

 

How to implement the repository design pattern in Laravel?

Scenario: Suppose, We have a Post model and a PostController. In a typical development process, we follow the codes given below.

For getting the list of post and getting a single post by its unique id.

<?php namespace App\Http\Controllers;

use App\Http\Requests;
use App\Http\Controllers\Controller;


class PostController extends Controller
{
	public function index(){
		$data = Post::all();
		return view('posts.index')->with('data', $data);
	}

	public function show($id){
		$data = Post::findOrFail($id);
		return view('posts.show')->with('data', $data);
	}
}

Problem

If we have another few controllers where we need single post by id or the post list then we repeat exactly the same code there. Look, In this example, we are fetching data from our database using the eloquent model. In future, If our project needs to change the data source which not support by eloquent that time we have to change that places manually which are very hard to keep the application unbreakable. Sometimes it quite impossible to do and it's also not unit-testable because the model and the controller are tightly coupled. The post controller is dependable to post model.

Solution

In this scenario, we can easily solve this type of problem using the repository pattern in our Laravel project. We'll use the repository interface to our controller to access the data. So our controller will be loosely coupled, independent and it doesn't need to know where the data comes from and how the logic implemented behind the sense. So, In future, if we change our data driver that time we don't need to change our controller code for adapting the changes. That's cool! Let implement the repository pattern in a certain case.

 

Step 01: Make an interface

Make an interface name with PostRepositoryInterface in app\Repositories directory.

<?php namespace App\Repositories;

interface PostRepositoryInterface{
	
	public function getAll();

	public function getPost($id);

	// more
}

 

Step 02: Make repository class

Now make a repository class name with PostRepository by implementing PostRepositoryInterface in app\Repository directory.

<?php namespace App\Repositories;

use App\Post;

class PostRepository implements PostRepositoryInterface
{
	public function getAll(){
		return Post::all();
	}

	public function getPost($id){
		return Post::findOrFail($id);
	}

	// more 

}

 

Step 03: Make the controller

Our interface and repository class finished. Now we'll use it in our PostController class. Let's do that.

<?php namespace App\Http\Controllers;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Repositories\PostRepositoryInterface;

class PostController extends Controller
{
	private $repository;

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

	public function index(){
		$data = $this->repository->getAll();
		return view('posts.index')->with('data', $data);
	}

	public function show($id){
		$data = $this->repository->getPost($id);
		return view('posts.show')->with('data', $data);
	}
}

 

Step 04: Register the repository.

We just finished our Post repository module. Our post controller used it but Laravel doesn't know our interface which implementation used. To register the post repository module add these in AppServiceProvider.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    
    public function register()
    {
        $this->app->bind(
            'App\Repositories\PostRepositoryInterface',
            'App\Repositories\PostRepository'
        );
    }

   
    public function boot()
    {
        //
    }
}

 

Our implementation finished! If today or tomorrow we need to use different data source for our post then we don't need to change our PostController or any other controller were the PostRepositoryInterface used. It could be 10 or 100 more places depending on project size.

For example, In the future, if we use data source as firebase instead of an eloquent model for MySQL database (Here PostRepository used eloquent model). That time we just need to change two places! First, add new class implementing the PostRepositoryInterface and update the binding at AppServiceProvider in register method. The example is given below.

<?php namespace App\Repositories;


class PostRepositoryFirebase implements PostRepositoryInterface
{
	public function getAll(){
		// example: http request to get all the post data and return;
	}

	public function getPost($id){
		// example: http request to get specific post data and return;
	}

	// more 

}

now we just have to change the bindings in AppServiceProvider. That's it!

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    
    public function register()
    {
        $this->app->bind(
            'App\Repositories\PostRepositoryInterface',
            'App\Repositories\PostRepositoryFirebase'
        );
    }

   
    public function boot()
    {
        //
    }
}

 

Why interface needed in repository design pattern?

Here interface comes to the picture because it enables us to make more implementation as we like. We just change in two places for a new data source Implementation rather than change manually every place where it has been used.

 

Should I use the repository design pattern in my project?

My recommendation, It's not necessary to use repository pattern in our small project because as a simple project keep it simple as like that. For large scale project, it makes code more readable, maintainable and reusable. If you do not develop any large scale project, Even then, It's necessary to you learn this design pattern for understanding other projects and contributing any favourite open-source project if they use repository pattern. Also, it might be helpful for a job interview and work with the team.

 

In the entire article, I have tried my best with my own knowledge to describe the Repository design pattern and its implementation in Laravel. If you think this is helpful for you then share this article with others so that they can be helped.

 

Share on


sidebar ad


Related Post


Laravel Barcode generation tutorial

Laravel PDF generation tutorial

Laravel 7 Http facade

Laravel Validation Cheat Sheet

PEST - Make Laravel test easier

Laravel Google reCaptcha without package