salehhashemi/laravel-repository
Installation:
composer require salehhashemi/laravel-repository
Publish the config (optional):
php artisan vendor:publish --provider="SalehHashemi\LaravelRepository\LaravelRepositoryServiceProvider"
First Use Case:
Define a repository for a model (e.g., User):
php artisan make:repository User
This generates:
Repositories/UserRepository.php (base repository)Repositories/UserRepositoryEloquent.php (Eloquent implementation)Basic Usage:
// In a controller or service
$users = app(\App\Repositories\UserRepository::class)->all();
$user = app(\App\Repositories\UserRepository::class)->find(1);
app/Repositories/Contracts/ – Define interfaces for your repositories.app/Repositories/ – Extend BaseRepository or BaseRepositoryEloquent.app/Repositories/Criteria/ – Define reusable query filters (e.g., ActiveUsers, Search).Repository Layer:
// Controller
public function index(UserRepository $repository)
{
$users = $repository->scope(['active'])->paginate();
return view('users.index', compact('users'));
}
AppServiceProvider:
$this->app->bind(
\App\Repositories\Contracts\UserRepository::class,
\App\Repositories\UserRepositoryEloquent::class
);
Criteria-Based Filtering:
ActiveUsers):
namespace App\Repositories\Criteria;
use SalehHashemi\LaravelRepository\Criteria\Criteria;
class ActiveUsers extends Criteria
{
public function apply($model)
{
return $model->where('is_active', true);
}
}
$activeUsers = $this->scope(['active'])->get();
$users = $this->scope(['active', 'search:name=John'])->paginate();
Presenter Layer:
$user = $this->presenter()->make($userModel);
app/Repositories/Presenters/.Events and Observers:
$this->create($data); // Fires `creating`, `created`, etc.
$users = $this->presenter()->collection($this->all());
$this->mock(UserRepository::class)->shouldReceive('find')->andReturn($user);
repository()->transaction() for multi-repository operations:
$this->repository()->transaction(function () {
$this->userRepository->create($userData);
$this->orderRepository->create($orderData);
});
N+1 Queries:
with() sparingly.presenter()->make() with lazy-loaded relationships for APIs.Over-Abstraction:
Criteria Performance:
DB::enableQueryLog().$this->scope(['active'])->remember(60)->get();
Model Binding:
AppServiceProvider).DB::enableQueryLog();
$users = $repository->all();
dd(DB::getQueryLog());
dd($this->getModel()) in a criteria’s apply() method to inspect the query builder.Custom Repository Methods:
public function findByEmail($email)
{
return $this->findWhere(['email' => $email])->first();
}
findWhere, findOneWhere, or findWhereIn for common queries.Dynamic Scopes:
BaseRepository to add dynamic scopes:
public function scopeTrashed($query)
{
return $query->whereNull('deleted_at');
}
$trashedUsers = $repository->trashed()->get();
Repository Events:
repository.creating):
Event::listen('repository.creating', function ($repository, $attributes) {
$attributes['created_by'] = auth()->id();
return $attributes;
});
Testing Repositories:
RepositoryServiceProvider for testing:
$this->app->register(\SalehHashemi\LaravelRepository\RepositoryServiceProvider::class);
Mockery or Laravel’s built-in mocking.model key in config/repository.php sets the default model for repositories. Override per-repository if needed.presenter_path to change where presenters are stored (default: app/Repositories/Presenters/).App\Repositories\Criteria or update the criteria_namespace config.How can I help you explore Laravel packages today?