orkhanahmadov/eloquent-repository
Installation:
composer require orkhanahmadov/eloquent-repository
Publish the config (optional):
php artisan vendor:publish --provider="Orkhanahmadov\EloquentRepository\ServiceProvider"
Define a Repository:
Create a repository class (e.g., app/Repositories/UserRepository.php):
namespace App\Repositories;
use Orkhanahmadov\EloquentRepository\EloquentRepository;
use App\Models\User;
class UserRepository extends EloquentRepository
{
public function model()
{
return User::class;
}
}
First Use Case: Inject the repository into a controller/service and use it like Eloquent:
use App\Repositories\UserRepository;
class UserController extends Controller
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function index()
{
$users = $this->userRepository->all(); // Equivalent to User::all()
return response()->json($users);
}
}
Key Files to Review:
config/eloquent-repository.php (for customizations).app/Repositories/ (your repository classes).Orkhanahmadov\EloquentRepository\EloquentRepository (base class).Basic CRUD Operations:
// Create
$user = $this->userRepository->create(['name' => 'John', 'email' => 'john@example.com']);
// Read
$user = $this->userRepository->find(1);
$users = $this->userRepository->all();
// Update
$user = $this->userRepository->update(1, ['name' => 'Jane']);
// Delete
$this->userRepository->delete(1);
Query Scoping:
// Scope a query (e.g., active users)
$activeUsers = $this->userRepository->scopeQuery(function ($query) {
return $query->where('is_active', true);
})->all();
// Or use named scopes (if defined in the model)
$activeUsers = $this->userRepository->scopeActive()->all();
Eager Loading:
$users = $this->userRepository->with(['posts', 'roles'])->get();
Pagination:
$users = $this->userRepository->paginate(10);
Transactions:
$this->userRepository->transaction(function ($repository) {
$repository->create(['name' => 'Alice']);
$repository->create(['name' 'Bob']);
});
Dependency Injection:
Bind repositories in AppServiceProvider for global access:
public function register()
{
$this->app->bind(
\App\Repositories\UserRepository::class,
function ($app) {
return new \App\Repositories\UserRepository(new \App\Models\User);
}
);
}
Service Layer: Use repositories in a service layer to decouple business logic from controllers:
class UserService
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function registerUser(array $data)
{
return $this->userRepository->create($data);
}
}
API Resources: Combine with Laravel's API Resources for consistent JSON responses:
$users = $this->userRepository->all();
return UserResource::collection($users);
Events and Observers: Trigger model events via repositories:
$this->userRepository->create($data, ['fireEvents' => true]);
Caching: Cache repository results using Laravel's cache:
$users = $this->userRepository->remember(60, function () {
return $this->userRepository->all();
});
Model Binding:
model() method in your repository returns the fully qualified class name of the Eloquent model (e.g., App\Models\User).Class 'User' not found errors.Query Builder vs. Eloquent:
selectRaw) may not work as expected. Use Eloquent's fluent methods instead:
// Works
$this->userRepository->select(['id', 'name'])->get();
// May fail or behave unexpectedly
$this->userRepository->selectRaw('id, name')->get();
Mass Assignment:
$fillable or $guarded properties. If you need to bypass this, use:
$this->userRepository->create($data, ['fillable' => true]);
Performance with Complex Queries:
// Bad: Too many eager loads
$this->userRepository->with(['posts', 'roles', 'comments'])->get();
// Good: Split into smaller queries
$users = $this->userRepository->all();
$users->load(['posts', 'roles']);
Transactions:
transaction method requires a closure that accepts the repository instance. Forgetting to pass the repository to the closure will result in no transaction:
// Wrong: Repository not passed to closure
$this->userRepository->transaction(function () {
$this->userRepository->create(...); // No transaction!
});
// Correct
$this->userRepository->transaction(function ($repository) {
$repository->create(...);
});
Enable Query Logging:
Add this to AppServiceProvider to log all repository queries:
public function boot()
{
\DB::enableQueryLog();
}
Then inspect queries via:
\DB::getQueryLog();
Check for Soft Deletes: If using soft deletes, ensure your queries account for it:
$this->userRepository->withTrashed()->get(); // Include soft-deleted records
Validate Repository Methods: Override methods in your repository to add custom logic or logging:
public function find($id)
{
\Log::debug("Finding user with ID: {$id}");
return parent::find($id);
}
Custom Scopes: Add reusable scopes to your repository:
public function scopeActive($query)
{
return $query->where('is_active', true);
}
Use them like:
$this->userRepository->scopeActive()->get();
Repository Events:
Listen for repository events (e.g., creating, created) by binding to the model's events:
\App\Models\User::created(function ($user) {
\Log::info("User created: {$user->id}");
});
Dynamic Attributes: Extend the repository to handle dynamic attributes or relationships:
public function getFullName($id)
{
$user = $this->find($id);
return "{$user->first_name} {$user->last_name}";
}
Repository Interfaces: Define interfaces for your repositories to enforce contracts:
interface UserRepositoryInterface
{
public function findByEmail($email);
}
Then implement them in your repository:
class UserRepository extends EloquentRepository implements UserRepositoryInterface
{
public function findByEmail($email)
{
return $this->scopeQuery(function ($query) use ($email) {
return $query->where('email', $email);
})->first();
}
}
Repository Factories: Use repository factories to dynamically create repositories based on conditions:
class RepositoryFactory
{
public static function make($modelClass)
{
$repositoryClass = "App\\Repositories\\" . class_basename($modelClass) . "Repository";
return new $repositoryClass(new $modelClass);
}
}
How can I help you explore Laravel packages today?