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

L5 Repository Laravel Package

prettus/l5-repository

Repository pattern implementation for Laravel that abstracts the data layer with base repositories, criteria/query filters, presenters/transformers, caching, validators, and Artisan generators. Helps keep controllers thin and makes apps easier to maintain and test.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require prettus/l5-repository
    php artisan vendor:publish --provider="Prettus\Repository\Providers\RepositoryServiceProvider"
    

    For Laravel 5.5+, the service provider auto-registers.

  2. Generate a Repository:

    php artisan make:repository Post
    

    This creates:

    • PostRepository (base class)
    • PostRepositoryEloquent (implementation)
    • Interface (PostRepositoryInterface)
  3. First Use Case: Inject the repository into a controller and fetch data:

    use App\Repositories\PostRepository;
    
    class PostController extends Controller {
        protected $repository;
    
        public function __construct(PostRepository $repository) {
            $this->repository = $repository;
        }
    
        public function index() {
            $posts = $this->repository->all(); // Fetch all posts
            return view('posts.index', compact('posts'));
        }
    }
    

Implementation Patterns

Core Workflows

  1. CRUD Operations:

    // Create
    $post = $this->repository->create(['title' => 'Hello', 'body' => 'World']);
    
    // Read
    $post = $this->repository->find(1);
    $posts = $this->repository->paginate(10);
    
    // Update
    $this->repository->update(['title' => 'Updated'], 1);
    
    // Delete
    $this->repository->delete(1);
    
  2. Query Scoping:

    // Custom scope
    $posts = $this->repository->scopeQuery(function ($query) {
        return $query->where('published', true);
    })->paginate();
    
    // Relationships
    $posts = $this->repository->with(['author', 'comments'])->get();
    
  3. Criteria for Dynamic Filtering:

    // Define a criteria
    class ActiveCriteria implements CriteriaInterface {
        public function apply($model, RepositoryInterface $repository) {
            return $model->where('is_active', true);
        }
    }
    
    // Apply in controller
    $this->repository->pushCriteria(new ActiveCriteria());
    $activePosts = $this->repository->all();
    
  4. Presenters for API Responses:

    // Define presenter
    class PostPresenter implements PresenterInterface {
        public function present($data) {
            return [
                'id'    => $data->id,
                'title' => $data->title,
                'url'   => route('posts.show', $data->id),
            ];
        }
    }
    
    // Enable in repository
    $this->repository->setPresenter(new PostPresenter());
    $presentedPost = $this->repository->present($this->repository->find(1));
    
  5. Validation:

    // Define validator
    class PostValidator extends Validator {
        public function rules() {
            return [
                'title' => 'required|max:255',
                'body'  => 'required',
            ];
        }
    }
    
    // Enable in repository
    $this->repository->setValidator(new PostValidator());
    $validated = $this->repository->validator()->validate(Input::all());
    
  6. Generators for Boilerplate:

    # Generate full entity (model, repo, validator, presenter, controller)
    php artisan make:entity Post --fillable="title:string,body:text" --rules="title:required|max:255,body:required"
    

Gotchas and Tips

Pitfalls

  1. Namespace Conflicts:

    • Ensure generator.basePath and generator.rootNamespace in config/repository.php match your project structure.
    • Example: If using src/App, set:
      'basePath' => base_path('src'),
      'rootNamespace' => 'App\\',
      
  2. Criteria Order Matters:

    • Criteria are applied in LIFO (Last-In-First-Out) order. Push criteria in reverse order of execution:
      $this->repository->pushCriteria(new ActiveCriteria());
      $this->repository->pushCriteria(new PublishedCriteria()); // Runs first
      
  3. Presenter Overhead:

    • Presenters add a layer of abstraction. For simple APIs, skip them to avoid unnecessary processing:
      $this->repository->skipPresenter(true);
      
  4. Cache Invalidation:

    • Cache keys are generated per method + arguments. Clear cache manually if data changes unexpectedly:
      Cache::forget($this->repository->getCacheKey('find', [1]));
      
  5. Mass Assignment Risks:

    • Always define $fillable in your model. The repository does not override this:
      class Post extends Model {
          protected $fillable = ['title', 'body']; // Only these can be mass-assigned
      }
      
  6. Eloquent vs. Query Builder:

    • The repository uses Eloquent by default. For raw queries, extend BaseRepository and override model() to return a QueryBuilder instance.

Debugging Tips

  1. Log Queries: Enable Eloquent logging in AppServiceProvider:

    DB::enableQueryLog();
    $posts = $this->repository->all();
    dd(DB::getQueryLog());
    
  2. Criteria Debugging: Temporarily log criteria application:

    class DebugCriteria implements CriteriaInterface {
        public function apply($model, RepositoryInterface $repository) {
            \Log::info('Criteria applied:', ['query' => $model->toSql(), 'bindings' => $model->getBindings()]);
            return $model;
        }
    }
    
  3. Validator Errors: Access raw validation errors:

    $validator = $this->repository->validator();
    $validator->validate(Input::all());
    if ($validator->fails()) {
        dd($validator->errors()->all());
    }
    
  4. Presenter Debugging: Dump presenter output:

    $data = $this->repository->find(1);
    $presenter = $this->repository->presenter();
    dd($presenter->present($data));
    

Extension Points

  1. Custom Repository Methods: Extend BaseRepository to add domain-specific methods:

    class PostRepository extends BaseRepository {
        public function publishedAndRecent($limit = 5) {
            return $this->scopeQuery(function ($query) {
                return $query->where('published', true)
                            ->orderBy('created_at', 'desc')
                            ->limit($limit);
            })->get();
        }
    }
    
  2. Dynamic Criteria: Create dynamic criteria based on request input:

    class SearchCriteria implements CriteriaInterface {
        protected $search;
    
        public function __construct($search) {
            $this->search = $search;
        }
    
        public function apply($model, RepositoryInterface $repository) {
            return $model->where('title', 'like', "%{$this->search}%");
        }
    }
    
    // Usage:
    $this->repository->pushCriteria(new SearchCriteria(request('q')));
    
  3. Event Hooks: Listen to repository events (e.g., retrieving, retrieved) via Laravel events:

    Event::listen('retrieving: App\Post', function ($repository, $method, $args) {
        \Log::info("Retrieving posts with method: {$method}");
    });
    
  4. Repository Interfaces: Define strict interfaces for better dependency injection:

    interface PostRepositoryInterface extends RepositoryInterface {
        public function publishedAndRecent($limit);
    }
    
  5. Testing: Mock repositories in tests:

    $mock = Mockery::mock(PostRepositoryInterface::class);
    $mock->shouldReceive('find')->andReturn(new Post());
    $this->app->instance(PostRepositoryInterface::class, $mock);
    
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata