Architecture & DesignThe Repository Pattern in PHP

The Repository Pattern in PHP

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
<?php
namespace AppRepositoriesContracts;

interface ProductRepositoryInterface
{
   public function search($name);

   public function getAllByUser($user_id);

   public function getAllByCategory($category_id);
}

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

<?php
namespace AppRepositoriesEloquent;

use AppRepositoriesContractsProductRepositoryInterface;
use AppEntityProduct;

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:

<?php
namespace AppRepositoriesProviders;
use IlluminateSupportServiceProvider;
class ProductRepositoryServiceProvider extends ServiceProvider
{
   public function register()
   {
      $this->app->bind(
         'AppRepositoriesContractsProductRepositoryInterface',
         // To change the data source, replace this class name
         // with another implementation
         'AppRepositoriesEloquentProductRepository'
      );
   }
}

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

<?php
...
'providers' => [

   /*
    * Laravel Framework Service Providers...
    */
   IlluminateAuthAuthServiceProvider::class,
   IlluminateBroadcastingBroadcastServiceProvider::class,
   IlluminateBusBusServiceProvider::class,
   IlluminateCacheCacheServiceProvider::class,
   IlluminateFoundationProviders
      ConsoleSupportServiceProvider::class,
   IlluminateCookieCookieServiceProvider::class,
   IlluminateDatabaseDatabaseServiceProvider::class,
   IlluminateEncryptionEncryptionServiceProvider::class,
   IlluminateFilesystemFilesystemServiceProvider::class,
   IlluminateFoundationProvidersFoundationServiceProvider::class,
   IlluminateHashingHashServiceProvider::class,
   IlluminateMailMailServiceProvider::class,
   IlluminatePaginationPaginationServiceProvider::class,
   IlluminatePipelinePipelineServiceProvider::class,
   IlluminateQueueQueueServiceProvider::class,
   IlluminateRedisRedisServiceProvider::class,
   IlluminateAuthPasswordsPasswordResetServiceProvider::class,
   IlluminateSessionSessionServiceProvider::class,
   IlluminateTranslationTranslationServiceProvider::class,
   IlluminateValidationValidationServiceProvider::class,
   IlluminateViewViewServiceProvider::class,

   /*
    * Application Service Providers...
    */
   AppProvidersAppServiceProvider::class,
   AppProvidersEventServiceProvider::class,
   AppProvidersRouteServiceProvider::class,

   AppRepositoriesProviders
      ProductRepositoryServiceProvider::class,
],

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

<?php
namespace AppHttpControllers;

use IlluminateRoutingController as BaseController;
use IlluminateHttpRequest;
use AppRepositoriesContractsProductRepositoryInterface;
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]);
   }
}
Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.
Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.

Latest Posts

Related Stories