DEV Community

Naster Blue
Naster Blue

Posted on

Implement Repository Design Pattern in Laravel

# The Repository Pattern

Use case

  • We have Post resource
  • Need to implement controller to support APIs for these features :

Get all posts
Paginate posts
Find posts with condition
Find post by id
Caching APIs to improve performance

Preparation

  • Post model (database driver can be MySQL/ PostgreSQL/ SQLite/ SQL Server)
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $table = 'posts'; } 
Enter fullscreen mode Exit fullscreen mode
  • Contract
<?php namespace App\Http\Contracts; interface RepositoryInterface { /** * Retrieve all data of repository * * @param array $columns * * @return mixed */ public function all($columns = ['*']); /** * Retrieve all data of repository, paginated * * @param null $limit * @param array $columns * * @return mixed */ public function paginate($limit = null, $columns = ['*']); /** * Find data by multiple fields * * @param array $where * @param array $columns * * @return mixed */ public function findWhere(array $where, $columns = ['*']); /** * Find data by id * * @param $id * @param array $columns * * @return mixed */ public function find($id, $columns = ['*']); } 
Enter fullscreen mode Exit fullscreen mode

Implementation Details

Newbie/Beginner/Fresher/Intern level

<?php namespace App\Http\Controllers; use App\Http\Contracts\RepositoryInterface; use App\Post; class PostController extends Controller implements RepositoryInterface { protected $post; public function __construct(Post $post) { $this->post = $post; } public function all($columns = ['*']) { return $this->post->all($columns); } public function paginate($limit = null, $columns = ['*']) { return $this->post->paginate($limit, $columns); } public function find($id, $columns = ['*']) { return $this->post->find($id, $columns); } public function findWhere(array $where, $columns = ['*']) { foreach ($where as $field => $value) { if (is_array($value)) { list($field, $condition, $val) = $value; $this->post = $this->post->where($field, $condition, $val); } else { $this->post = $this->post->where($field, '=', $value); } } return $this->post->get($columns); } } 
Enter fullscreen mode Exit fullscreen mode

Database Repository/ Junior Level

<?php namespace App\Http\Controllers; use App\Http\Contracts\RepositoryInterface; use App\Post; class DbPostRepository implements RepositoryInterface { private $post; public function __construct(Post $post) { $this->post = $post; } public function all($columns = ['*']) { return $this->post->all($columns); } public function paginate($limit = null, $columns = ['*']) { return $this->post->paginate($limit, $columns); } public function findWhere(array $where, $columns = ['*']) { foreach ($where as $field => $value) { if (is_array($value)) { list($field, $condition, $val) = $value; $this->model = $this->post->where($field, $condition, $val); } else { $this->model = $this->post->where($field, '=', $value); } } return $this->post->get($columns); } public function find($id, $columns = ['*']) { return $this->post->find($id, $columns); } } class DbPostController extends Controller { private $dbPostRepository; public function __construct(DbPostRepository $dbPostRepository) { $this->dbPostRepository = $dbPostRepository; } public function all($columns = ['*']) { return $this->dbPostRepository->all($columns); } public function paginate($limit = null, $columns = ['*']) { return $this->dbPostRepository->paginate($limit, $columns); } public function findWhere(array $where, $columns = ['*']) { return $this->dbPostRepository->findWhere($where, $columns); } public function find($id, $columns = ['*']) { return $this->dbPostRepository->find($id, $columns); } } 
Enter fullscreen mode Exit fullscreen mode

Caching Repository/ Senior Level

<?php namespace App\Http\Controllers; use App\Http\Contracts\RepositoryInterface; use Illuminate\Contracts\Cache\Repository as CacheRepository; class CachePostRepository implements RepositoryInterface { private $dbPostRepository; private $cacheRepository; public function __construct(DbPostRepository $dbPostRepository, CacheRepository $cacheRepository) { $this->dbPostRepository = $dbPostRepository; $this->cacheRepository = $cacheRepository; } public function getCacheMinutes() { return config('repository.cache.minutes', 30); } public function getCacheKey($method, $args = null) { $request = app('Illuminate\Http\Request'); $args = serialize($args); $criteria = $this->serializeCriteria(); $key = sprintf('%s@%s-%s', get_called_class(), $method, md5($args . $criteria . $request->fullUrl())); return $key; } public function all($columns = ['*']) { $key = $this->getCacheKey('all', func_get_args()); $minutes = $this->getCacheMinutes(); return $this->cacheRepository->remember($key, $minutes, function () use ($columns) { return $this->dbPostRepository->all($columns); }); } public function paginate($limit = null, $columns = ['*']) { $key = $this->getCacheKey('paginate', func_get_args()); $minutes = $this->getCacheMinutes(); return $this->cacheRepository->remember($key, $minutes, function () use ($limit, $columns) { return $this->dbPostRepository->paginate($limit, $columns); }); } public function findWhere(array $where, $columns = ['*']) { $key = $this->getCacheKey('findWhere', func_get_args()); $minutes = $this->getCacheMinutes(); return $this->cacheRepository->remember($key, $minutes, function () use ($where, $columns) { return $this->dbPostRepository->findWhere($where, $columns); }); } public function find($id, $columns = ['*']) { $key = $this->getCacheKey('find', func_get_args()); $minutes = $this->getCacheMinutes(); return $this->cacheRepository->remember($key, $minutes, function () use ($columns) { return $this->dbPostRepository->all($columns); }); } } class CachePostController extends Controller { private $cachePostRepository; public function __construct(CachePostRepository $cachePostRepository) { $this->cachePostRepository = $cachePostRepository; } public function all($columns = ['*']) { return $this->cachePostRepository->all($columns); } public function paginate($limit = null, $columns = ['*']) { return $this->cachePostRepository->paginate($limit, $columns); } public function findWhere(array $where, $columns = ['*']) { return $this->cachePostRepository->findWhere($where, $columns); } public function find($id, $columns = ['*']) { return $this->cachePostRepository->find($id, $columns); } } 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)