Install the Package
composer require madulinux/repository-pattern
Register the service provider in config/app.php under providers:
Madulinux\RepositoryPattern\Providers\RepositoryServiceProvider::class,
Generate a Repository
php artisan make:repository User
This creates:
app/Repositories/UserRepository.php (implementation)app/Repositories/Interfaces/UserRepositoryInterface.php (contract)First Use Case: Fetch All Users
use App\Repositories\UserRepository;
use App\Models\User;
$repository = new UserRepository(new User());
$users = $repository->all(); // Returns Collection
First Use Case: Create a User
$user = $repository->create(['name' => 'Alice', 'email' => 'alice@example.com']);
app/Repositories/Interfaces/ for available methods.Madulinux\RepositoryPattern\Repository for core functionality.php artisan make:repository and php artisan make:repository-interface for scaffolding.// Find
$user = $repository->find(1);
// Create
$user = $repository->create(['name' => 'Bob']);
// Update
$repository->update(1, ['name' => 'Robert']);
// Delete (soft or hard)
$repository->delete(1); // Soft delete if model uses SoftDeletes
$repository->forceDelete(1); // Hard delete
// Chainable queries
$activeUsers = $repository->scopeQuery(function ($query) {
return $query->where('active', true);
})->get();
// Or use predefined scopes
$repository->scope('active')->get();
$users = $repository->paginate(10); // Returns LengthAwarePaginator
$users = $repository->simplePaginate(10); // Returns SimplePaginator
// Bulk create
$users = $repository->createMany([
['name' => 'User1'],
['name' => 'User2'],
]);
// Bulk update
$repository->updateMany([1, 2], ['status' => 'inactive']);
$repository->transaction(function ($repo) {
$repo->create(['name' => 'UserA']);
$repo->create(['name' => 'UserB']);
// Rolls back on exception
});
Bind repositories in AppServiceProvider:
public function register()
{
$this->app->bind(
\App\Repositories\Interfaces\UserRepositoryInterface::class,
\App\Repositories\UserRepository::class
);
}
Then inject via constructor:
public function __construct(UserRepositoryInterface $userRepository) {
$this->userRepository = $userRepository;
}
Extend the base class for global behavior:
namespace App\Repositories;
use Madulinux\RepositoryPattern\Repository as BaseRepository;
class CustomRepository extends BaseRepository
{
public function boot()
{
$this->applyScopes(['active']);
$this->enableCache();
}
}
Listen to repository events in EventServiceProvider:
protected $listen = [
'Madulinux\RepositoryPattern\Events\Creating' => [
\App\Listeners\LogCreating::class,
],
];
Configure cache drivers in config/repository-pattern.php:
'cache' => [
'driver' => 'redis',
'prefix' => 'repo_',
'default_ttl' => 60,
],
Enable/disable per repository:
$repository->enableCache(); // Uses config defaults
$repository->enableCache('memcached', 300); // Custom driver/TTL
Ensure your model uses SoftDeletes trait:
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
Then use:
$repository->withTrashed()->get(); // Include soft-deleted
$repository->onlyTrashed()->get(); // Only soft-deleted
Cache Invalidation
find(), all(), get(), etc., but not for create(), update(), or delete().$repository->create([...]);
$repository->clearCache();
enableCache(false) for repositories that don’t need caching.Model Binding
// ❌ Wrong
$repository = new UserRepository();
// ✅ Correct
$repository = new UserRepository(new User());
Soft Deletes + Cache
withTrashed() in your scope:
$repository->scopeQuery(function ($query) {
return $query->withTrashed();
});
Transaction Scope
// ❌ Avoid
$repository->transaction(function ($repo) {
$repo->transaction(function ($repo) { ... }); // Fails
});
// ✅ Do
$repository->transaction(function ($repo) { ... });
Bulk Operations and Events
createMany, updateMany) skip Creating, Updating, etc., events by default.$repository->fireEvents(true)->createMany([...]);
Query Logging Enable Laravel’s query logging to inspect generated queries:
\DB::enableQueryLog();
$repository->all();
\DB::getQueryLog(); // Inspect queries
Event Debugging Dump events in listeners:
public function handle(Creating $event)
{
dd($event->repository, $event->attributes);
}
Cache Debugging Check cached keys:
$repository->getCacheKey(); // Shows current cache key
\Cache::getStore()->get($repository->getCacheKey());
Custom Scopes Add reusable scopes to the base repository:
// In a service provider
$this->app->afterResolving(\Madulinux\RepositoryPattern\Repository::class, function ($repository) {
$repository->scope('archived', function ($query) {
return $query->where('archived', true);
});
});
Custom Events Extend the event system:
// Fire a custom event
event(new \App\Events\UserCreated($user));
// Listen in EventServiceProvider
'App\Events\UserCreated' => [
\App\Listeners\SendWelcomeEmail::class,
];
Model Observers Combine with Eloquent observers for additional logic:
class UserObserver
{
public function saved(User $user)
{
// Sync with external API, etc.
}
}
Register in AppServiceProvider:
User::observe(UserObserver::class);
Repository Decorators Decorate repositories for cross-cutting concerns (e.g., logging, auth):
class LoggingRepositoryDecorator
{
protected $repository;
public function __construct(UserRepositoryInterface $repository)
{
$this->repository = $repository;
}
public function find($id)
{
\Log::info("Finding user {$id}");
return $this->repository->find($id);
}
// Delegate other methods
public function __call($method, $args)
{
return $this->repository->$method(...$args);
}
}
**Dynamic Repository
How can I help you explore Laravel packages today?