Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Repository Laravel Package

arafat69/laravel-repository

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require arafat69/laravel-repository
    
  2. Publish the stubs (optional but recommended for customization):

    php artisan vendor:publish --provider="Arafat69\Repository\RepositoryServiceProvider" --tag="repository-stubs"
    
  3. Generate a repository for your first model (e.g., User):

    php artisan make:repository UserRepository --model=User
    

    This creates:

    • app/Repositories/UserRepository.php (interface)
    • app/Repositories/Eloquent/UserRepositoryEloquent.php (implementation)
  4. Register the repository in AppServiceProvider:

    public function register()
    {
        $this->app->bind(
            \App\Repositories\UserRepository::class,
            \App\Repositories\Eloquent\UserRepositoryEloquent::class
        );
    }
    
  5. Use the repository in a controller/service:

    use App\Repositories\UserRepository;
    
    public function index(UserRepository $repository)
    {
        $users = $repository->all();
        return view('users.index', compact('users'));
    }
    

First Use Case: CRUD Operations

Replace direct Eloquent calls in a controller with repository methods:

// Before (Controller)
public function store(Request $request)
{
    return User::create($request->all());
}

// After (Controller)
public function store(Request $request, UserRepository $repository)
{
    return $repository->create($request->all());
}

Implementation Patterns

Core Workflows

  1. Repository Generation

    • Use make:repository for new models:
      php artisan make:repository PostRepository --model=Post --with-transactions
      
    • Flags:
      • --with-transactions: Auto-wraps create/update in DB transactions.
      • --with-scopes: Generates scope methods (e.g., scopeActive()).
  2. Dependency Injection

    • Controllers:
      public function __construct(private UserRepository $users) {}
      
    • Services:
      public function __construct(
          private UserRepository $users,
          private RoleRepository $roles
      ) {}
      
  3. Customizing Queries Extend the Eloquent implementation:

    // app/Repositories/Eloquent/UserRepositoryEloquent.php
    public function findActiveUsers()
    {
        return $this->model->where('active', true)->get();
    }
    
  4. Scopes Define reusable query constraints:

    // UserRepository.php (interface)
    public function scopeActive($query);
    
    // UserRepositoryEloquent.php (implementation)
    public function scopeActive($query)
    {
        return $query->where('active', true);
    }
    

    Usage:

    $activeUsers = $repository->active()->get();
    
  5. Transactions Wrap operations in a transaction block:

    $repository->transaction(function (UserRepository $repo) {
        $user = $repo->create([...]);
        $repo->attachRole($user, 'admin');
    });
    

Integration Tips

  1. Unit Testing Mock repositories in tests:

    $this->mock(UserRepository::class, function ($mock) {
        $mock->shouldReceive('find')
             ->once()
             ->andReturn(new User());
    });
    
  2. API Resources Combine repositories with API resources:

    public function show(UserRepository $repository, $id)
    {
        return new UserResource($repository->find($id));
    }
    
  3. Event Dispatching Trigger events from repository methods:

    public function create(array $attributes)
    {
        $model = $this->model->create($attributes);
        event(new UserCreated($model));
        return $model;
    }
    
  4. Caching Cache repository results:

    public function all()
    {
        return Cache::remember('users.all', now()->addHours(1), function () {
            return $this->model->all();
        });
    }
    
  5. Validation Move validation logic to repositories:

    public function create(array $attributes)
    {
        $validated = $this->validate($attributes);
        return $this->model->create($validated);
    }
    
    protected function validate(array $data)
    {
        return Validator::make($data, [
            'email' => 'required|email|unique:users',
        ])->validate();
    }
    

Gotchas and Tips

Common Pitfalls

  1. Forgetting to Bind the Repository

    • Issue: BindingResolutionException when injecting the repository.
    • Fix: Register the binding in AppServiceProvider or use Laravel’s auto-binding:
      $this->app->bind(
          'App\Repositories\UserRepository',
          'App\Repositories\Eloquent\UserRepositoryEloquent'
      );
      
  2. Overusing Repositories for Simple Queries

    • Tip: Reserve repositories for complex logic. Use Eloquent directly for simple find() or all() calls.
  3. Not Extending the Base Repository

    • Issue: Missing methods like findOrFail() or firstOrFail().
    • Fix: Extend Arafat69\Repository\Eloquent\BaseRepository:
      class UserRepositoryEloquent extends BaseRepository
      {
          // Custom methods here
      }
      
  4. Transaction Conflicts

    • Issue: Deadlocks or timeouts in long-running transactions.
    • Tip: Keep transactions short or use retryWhen:
      $repository->transaction(function () {
          // ...
      }, 3, 100); // Retry 3 times with 100ms delay
      
  5. Stub Customization

    • Issue: Generated stubs don’t match your team’s conventions.
    • Fix: Publish and modify stubs:
      php artisan vendor:publish --tag="repository-stubs"
      
      Edit files in resources/stubs/repository/.

Debugging Tips

  1. Log Repository Calls Add logging to the base repository:

    // app/Repositories/Eloquent/BaseRepository.php
    protected function logQuery($method, $args)
    {
        \Log::debug("Repository [$method] called with: " . json_encode($args));
    }
    
  2. Check for Missing Scopes

    • Error: Call to undefined method when using scopes.
    • Fix: Ensure the scope method exists in the Eloquent implementation (not just the interface).
  3. Verify Model Binding

    • Error: Model not found or BindingResolutionException.
    • Fix: Confirm the model is bound correctly in the repository:
      protected $model = \App\Models\User::class;
      

Extension Points

  1. Custom Repository Types Extend the package to support non-Eloquent repositories (e.g., API clients):

    namespace App\Repositories\Api;
    
    class UserRepositoryApi implements UserRepository
    {
        public function all()
        {
            return Http::get('api/users')->json();
        }
    }
    
  2. Dynamic Model Binding Bind models dynamically in the repository:

    public function __construct(protected BaseRepository $repository)
    {
        $this->repository->setModel($this->model);
    }
    
  3. Repository Events Dispatch events for repository actions:

    // app/Repositories/Eloquent/BaseRepository.php
    protected function afterCreate($model)
    {
        event(new ModelCreated($model));
    }
    
  4. Repository Middleware Add middleware to repository methods:

    public function find($id)
    {
        return $this->model->findOrFail($id);
    }
    
    // In a service provider:
    $this->app->when(UserRepository::class)
        ->needs('$model')
        ->give(function ($repo) {
            return tap($repo->model, function ($model) {
                // Add global scopes/middleware
            });
        });
    
  5. Repository Caching Layer Implement a caching decorator:

    class CachedUserRepository implements UserRepository
    {
        public function __construct(private UserRepository $repository) {}
    
        public function all()
        {
            return Cache::remember('users.all', now()->addHours(1), function () {
                return $this->repository->all();
            });
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon
itsemon245/lamet
baks-dev/dashboard
amoifr/pickle-panther-bundle
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle