Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - Using the Repository Pattern

I am trying to learn the repository pattern, and seem to have got myself a tad confused with how I can use this repository pattern when eager loading relationships and keep db logic out of my controller.

A quick overview of my repository / application structure.

app/
  Acme/
    Repositories/
      RepositoryServiceProvider.php
      Product/
        EloquentProduct.php
        ProductInterface.php
      Category/
        EloquentCategory.php
        CategoryInterface.php

Example ProductInterface.php

<?php namespace GD\Repositories\Product;

interface ProductInterface
{
    public function all();

    public function find($id);

    public function findBySlug($slug);
}

Example CategoryInterface.php

<?php namespace GD\Repositories\Category;

interface CategoryInterface
{
    public function all();

    public function find($id);

    public function findBySlug($slug);
}

Ok, so the easy part is using DI to inject model dependencies into the controller.

listing all categories with associated products is more difficult as I am no longer working with an eloquent model. I am working with an interface which has not exposed all the eloquent methods.

This won't work without me implementing a with method within my EloquentCategory class...

public function show($slug)
{
  return Response::json($this->category->findBySlug($slug)->with('products'), 200);
}

Should I create a separate service class to glue the two repositories together? e.g. allowing the following

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

public function show($slug)
{
  return Response::json( $this->shop->getProductsInCategory($slug), 200 );
}

Or alternatively, should I be implementing the with method in my Category Repository?

public function with($relation)
{
  return Category::with($relation);
}

Finally, is my understanding of the usage of the Repository Pattern Correct?

like image 474
Gravy Avatar asked Feb 16 '14 01:02

Gravy


People also ask

What is the use of repository pattern?

The Repository pattern allows you to easily test your application with unit tests. Remember that unit tests only test your code, not infrastructure, so the repository abstractions make it easier to achieve that goal.

What design pattern does Laravel use?

The Bridge pattern is a structural design pattern in PHP that's used to vary an implementation of an object or class. If you've used Laravel even a little you'll have seen evidence of the Bridge pattern and the sort of flexibility we're aiming for in the central services of the framework.

What is repository pattern?

Repository Pattern is an abstraction of the Data Access Layer. It hides the details of how exactly the data is saved or retrieved from the underlying data source. The details of how the data is stored and retrieved is in the respective repository.

What is repository pattern in PHP?

According to Edward Hieatt and Rob Mee, a repository mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. A more straightforward way includes creating one layer rather than writing the function at the controller right away.


2 Answers

You are over thinking, repository is just a link/bridge between your controller and model and hence controller uses repository class instead of the model directly and in that repository you may declare your methods using the model from there, for example:

<?php namespace GD\Repositories\Category;

interface CategoryInterFace{

    public function all();

    public function getCategoriesWith($with);

    public function find($id);
}

Now implement the interface in the repository class:

<?php namespace GD\Repositories\Category;

use \EloquentCategory as Cat; // the model
class CategoryRepository implements CategoryInterFace {
    public function all()
    {
        return Cat::all();
    }

    public function getCategoriesWith($with)
    {
        return Cat::with($with)->get();
    }

    public function find($id)
    {
        return Cat::find($id):
    }
}

To use it in your controller:

<?php

use GD\Repositories\Category\CategoryInterFace;

class CategoryController extends BaseController {

    public function __construct(CategoryInterFace $category)
    {
        $this->cat = $category;
    }

    public function getCatWith()
    {
        $catsProd = $this->cat->getCategoriesWith('products');
        return $catsProd;
    }

    // use any method from your category
    public function getAll()
    {
        $categories = $this->cat->all();

        return View::make('category.index', compact('categories'));
    }

}

Note: Omitted the IoC binding of the repository because this is not your problem and you know that.

Update: I've written an article here: LARAVEL – USING REPOSITORY PATTERN.

like image 186
The Alpha Avatar answered Sep 21 '22 10:09

The Alpha


There is a really easy way to do this and it is explored in depth in this link

http://heera.it/laravel-repository-pattern#.U6XhR1cn-f4

I was looking for the exact solution and it is working well so far

so the idea for you would be to declare this in your repository code

public function __construct(\Category $category)
{
    $this->category = $category;
} 
public function getAllUsers()
{
    return $this->category->all();
}

public function __call($method, $args)
{
    return call_user_func_array([$this->category, $method], $args);
}

forcing the Model to be called when some functions are missing

like image 45
Germain Avatar answered Sep 22 '22 10:09

Germain