Repositories Layer and Criteria Files
In This Document
Introduction
In Laravel development, the Repositories layer and Criteria files serve as a powerful combination for managing data retrieval and manipulation. The andersao/l5-repository package is commonly employed to implement the Repositories layer, providing a convenient way to separate database operations from the rest of the application.
Using repositories helps maintain a clean separation between your business logic and data access layer, making your code more maintainable and testable.
Why Repositories?
Repositories help abstract the data access layer, allowing for better code organization and maintenance. The andersao/l5-repository package extends Laravel's Eloquent ORM, providing a set of tools to create, read, update, and delete records in a consistent manner.
Installation of andersao/l5-repository
To get started with andersao/l5-repository, you need to install the package using Composer:
composer require andersao/l5-repository
After installation, you can set up repositories for your models.
Implementation Guide
- Creating Repositories
- Using Repositories
- Criteria Files
- Applying Criteria
Creating Repositories
Repositories are classes that encapsulate the logic for interacting with the database. They provide a clean and consistent API for data access.
Step 1: Create Repository Interface
<?php
namespace App\Repositories;
use Prettus\Repository\Contracts\RepositoryInterface;
interface UserRepository extends RepositoryInterface
{
// You can add custom methods here
}
Step 2: Create Repository Implementation
<?php
namespace App\Repositories;
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use App\Models\User;
class UserRepositoryEloquent extends BaseRepository implements UserRepository
{
public function model()
{
return User::class;
}
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
}
Step 3: Register in AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
\App\Repositories\UserRepository::class,
\App\Repositories\UserRepositoryEloquent::class
);
}
}
Utilizing Repositories in Services or Controllers
Once you have created your repositories, you can use them in services or controllers to perform database operations.
In a Service Class
<?php
namespace App\Services;
use App\Repositories\UserRepository;
class UserService
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function getUserById($id)
{
return $this->userRepository->find($id);
}
public function getAllUsers()
{
return $this->userRepository->all();
}
public function createUser(array $data)
{
return $this->userRepository->create($data);
}
}
In a Controller
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
use Illuminate\Http\Request;
class UserController extends Controller
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function index()
{
return response()->json([
'data' => $this->userRepository->all()
]);
}
public function show($id)
{
return response()->json([
'data' => $this->userRepository->find($id)
]);
}
}
Criteria Files
Criteria files are classes that define specific conditions or filters to be applied to database queries. They allow for dynamic and reusable query building.
Creating a Criteria Class
<?php
namespace App\Criteria;
use Prettus\Repository\Contracts\RepositoryInterface;
use Prettus\Repository\Contracts\CriteriaInterface;
class ActiveUsersCriteria implements CriteriaInterface
{
public function apply($model, RepositoryInterface $repository)
{
return $model->where('status', 'active');
}
}
Creating a Criteria with Parameters
<?php
namespace App\Criteria;
use Prettus\Repository\Contracts\RepositoryInterface;
use Prettus\Repository\Contracts\CriteriaInterface;
class UsersByTypeCriteria implements CriteriaInterface
{
protected $type;
public function __construct($type)
{
$this->type = $type;
}
public function apply($model, RepositoryInterface $repository)
{
return $model->where('type', $this->type);
}
}
Applying Criteria to Repositories
You can apply criteria to repositories to filter or modify query results.
In a Controller
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
use App\Criteria\ActiveUsersCriteria;
use App\Criteria\UsersByTypeCriteria;
class UserController extends Controller
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function getActiveUsers()
{
$this->userRepository->pushCriteria(new ActiveUsersCriteria());
return response()->json([
'data' => $this->userRepository->all()
]);
}
public function getAdminUsers()
{
$this->userRepository->pushCriteria(new UsersByTypeCriteria('admin'));
return response()->json([
'data' => $this->userRepository->all()
]);
}
public function getActiveAdmins()
{
$this->userRepository
->pushCriteria(new ActiveUsersCriteria())
->pushCriteria(new UsersByTypeCriteria('admin'));
return response()->json([
'data' => $this->userRepository->all()
]);
}
}
Temporarily Skipping Criteria
// Skip all criteria
$users = $this->userRepository->skipCriteria()->all();
// Skip specific criteria
$users = $this->userRepository->skipCriteria(ActiveUsersCriteria::class)->all();
Common Repository Methods
The andersao/l5-repository package provides several built-in methods for common operations:
| Method | Description | Example |
|---|---|---|
all() | Get all records | $repository->all() |
find($id) | Find by ID | $repository->find(1) |
findByField($field, $value) | Find by field | $repository->findByField('email', 'user@example.com') |
findWhere(array $where) | Find with conditions | $repository->findWhere(['status' => 'active', 'type' => 'admin']) |
create(array $attributes) | Create new record | $repository->create(['name' => 'John', 'email' => 'john@example.com']) |
update(array $attributes, $id) | Update record | $repository->update(['status' => 'inactive'], 1) |
delete($id) | Delete record | $repository->delete(1) |
orderBy($column, $direction) | Order results | $repository->orderBy('created_at', 'desc')->all() |
with($relations) | Eager load relations | $repository->with(['posts', 'comments'])->find(1) |
paginate($limit) | Paginate results | $repository->paginate(15) |
Advanced Features
Caching Results
The package supports caching repository results to improve performance:
// In your repository class
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
$this->setCacheLifetime(60); // Cache for 60 minutes
}
Be careful with caching when your data changes frequently. You may need to implement cache invalidation strategies.
Presenter Layer
You can use presenters to format your data before returning it:
<?php
namespace App\Presenters;
use App\Transformers\UserTransformer;
use Prettus\Repository\Presenter\FractalPresenter;
class UserPresenter extends FractalPresenter
{
public function getTransformer()
{
return new UserTransformer();
}
}
// In your repository
public function presenter()
{
return UserPresenter::class;
}
Conclusion
Implementing the Repositories layer with andersao/l5-repository and Criteria files in Laravel promotes a clean separation of concerns in your application. Repositories abstract database operations, while Criteria files provide a flexible way to dynamically filter or modify query results.
Explore the capabilities of andersao/l5-repository to handle more complex scenarios, such as caching, pagination, and eager loading, for efficient data retrieval in your Laravel projects.