Repository pattern in PHP and Laravel

profile picture

Repository pattern in PHP and Laravel

TL;DR

A repository is an interface-signed class that encapsulate all SQL queries in specific methods. The repository class is then injected into your controller methods using dependency injection. You use the class methods instead of running sql queries inside the controller logic.

In laravel, the advantage of such pattern is limited because Eloquent's Query builder is already doing all the hard -repetition- work.

What is the Repository Pattern?

A repository represents an architectural layer that handles communication between the application and data source. It is a widely used pattern whose main point is that the application does not have to know which data source is implemented and how it is implemented. This makes it easier to switch to another data source or implement structural changes to the existing data source.

The repository pattern introduces a repository interface, which defines how the application and the data sources should communicate. Each data source has its own class which implements the repository interface. The controller class will call the methods defined in the repository interface and will not know how and from where the data is being fetched from.

Implementation in Laravel

First, we will create a repository interface. It can be located anywhere, but in this example, we will use the following directory structure:

  • app/Repositories/Contracts: All repository interfaces will be stored here
  • app/Repositories/Eloquent: All interface Eloquent implementations can be found here
  • app/Repositories/Providers: Service providers for repositories are saved in this folder
namespace App\Repositories\Contracts;

interface ProductRepositoryInterface
{
   public function search($name);

   public function getAllByUser($user_id);

   public function getAllByCategory($category_id);
}

Note that each model will have its own repository interface. This example shows a repository interface for a product model and its implementation with Eloquent:

namespace App\Repositories\Eloquent;

use App\Repositories\Contracts\ProductRepositoryInterface;
use App\Models\Product;

class ProductRepository implements ProductRepositoryInterface
{

   public function search($name)
   {
      return Product::where('title', 'LIKE', '% ' . $name . '%')
         ->get();
   }

   public function getAllByUser($user_id)
   {
      return Product::where('user_id', '=', $user_id)
         ->get();
   }

   public function getAllByCategory($category_id)
   {
      return Product::where('category_id', '=', $category_id)
         ->get();
   }
}

To be able to use these classes in the framework, we need to register the service provider:

namespace App\Repositories\Providers;

use Illuminate\Support\ServiceProvider;

class ProductRepositoryServiceProvider extends ServiceProvider
{
   public function register()
   {
      $this->app->bind(
         'App\Repositories\Contracts\ProductRepositoryInterface',
         // To change the data source, replace this class name
         // with another implementation
         'App\Repositories\Eloquent\ProductRepository'
      );
   }
}

Finally, the service provider needs to be added to the configuration file:

'providers' => [
    // ...
    App\Repositories\Providers\ProductRepositoryServiceProvider::class,
    // ...
],

At this point, the repository can be injected into controller classes. An example controller would look like this:

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use Illuminate\Http\Request;
use App\Repositories\Contracts\ProductRepositoryInterface;

class ProductController extends BaseController
{
   protected $productRepository;

   // $productRepository will call the methods from the
   // class defined above in the service provider
   public function __construct(ProductRepositoryInterface $productRepository)
   {
      $this->productRepository = $productRepository;
   }

   public function search(Request $request)
   {
      $name = $request->input('name');
      $products = $this->productRepository->search($name);
      return view('home.index', ['products' => $products]);
   }
}

Code in copied from this article, but was corrected and improved.

laravel
php
repository
pattern

about me

profile picture

I consider myself as an IT Business Artisan. Or Consultant CTO. I'm a self-taught Web Developper, coach and teacher. My main work is helping and guiding digital startups.

more about me

follow me

newsletter

A weekly email with the latests articles

support my work

Start trading on binance
  • BTC

    BTC

    18SY81ejLGFuJ9KMWQu5zPrDGuR5rDiauM

  • ETH

    ETH

    0x519e0eaa9bc83018bb306880548b79fc0794cd08

  • Monero

    XMR

    895bSneY4eoZjsr2hN2CAALkUrMExHEV5Pbg8TJb6ejnMLN7js1gLAXQySqbSbfzjWHQpQhQpvFtojbkdZQZmM9qCFz7BXU

2024 © My Dynamic Production SRL All rights Reserved.