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

czim/laravel-repository

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require czim/laravel-repository
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Czim\Repository\RepositoryServiceProvider"
    
  2. Define a Model:

    // app/Models/User.php
    class User extends Model
    {
        // Model definition
    }
    
  3. Create a Repository Interface:

    // app/Repositories/Interfaces/UserRepositoryInterface.php
    namespace App\Repositories\Interfaces;
    
    use Czim\Repository\Interfaces\RepositoryInterface;
    
    interface UserRepositoryInterface extends RepositoryInterface
    {
        // Custom methods here
    }
    
  4. Generate a Repository Class:

    php artisan make:repository UserRepository --interface=UserRepositoryInterface
    

    This creates:

    // app/Repositories/UserRepository.php
    class UserRepository extends \Czim\Repository\Repository
    {
        public function __construct(User $model)
        {
            $this->model = $new Model($model);
        }
    }
    
  5. Register in Service Provider:

    // app/Providers/AppServiceProvider.php
    public function register()
    {
        $this->app->bind(
            \App\Repositories\Interfaces\UserRepositoryInterface::class,
            \App\Repositories\UserRepository::class
        );
    }
    
  6. First Use Case:

    // In a controller or service
    $user = app(UserRepositoryInterface::class)->find(1);
    

Where to Look First

  • Repository Contracts: vendor/czim/laravel-repository/src/Interfaces/RepositoryInterface.php (Defines core methods like find(), all(), create(), etc.)
  • Criteria System: vendor/czim/laravel-repository/src/Criteria/ (For filtering/scoping queries dynamically)
  • Model Events: vendor/czim/laravel-repository/src/Events/ (For post-retrieval model manipulation)

Implementation Patterns

Core Workflows

1. Basic CRUD Operations

// Find a single record
$user = $repo->find(1);

// Find all with eager loading
$users = $repo->all(['posts']);

// Create/update/delete
$repo->create(['name' => 'John']);
$repo->update(1, ['name' => 'Jane']);
$repo->delete(1);

2. Dynamic Scoping with Criteria

// Apply a global scope (e.g., for "active" users)
$repo->pushCriteria(new ActiveUsersCriteria());

// Temporarily apply a scope
$activeUsers = $repo->scope(function ($query) {
    return $query->where('active', true);
})->all();

// Remove a scope
$repo->popCriteria();

3. Post-Processing Models

// Apply a transformer (e.g., for API responses)
$repo->pushTransformer(new UserTransformer());

// Temporarily transform models
$transformedUsers = $repo->transform(function ($model) {
    $model->api_key = 'secret-' . $model->id;
    return $model;
})->all();

4. Unit Testing

// Mock the repository in tests
$mockRepo = Mockery::mock(UserRepositoryInterface::class);
$mockRepo->shouldReceive('find')->andReturn($user);

// Inject into tested class
$this->app->instance(UserRepositoryInterface::class, $mockRepo);

Integration Tips

1. Dependency Injection

// In a controller/service
public function __construct(UserRepositoryInterface $repo) {
    $this->repo = $repo;
}

2. Eloquent Relationships

// Eager load relationships
$users = $repo->with(['posts', 'roles'])->all();

// Access relationships
foreach ($users as $user) {
    $user->posts->first();
}

3. Transactions

DB::transaction(function () use ($repo) {
    $repo->create(['name' => 'Alice']);
    $repo->create(['name' => 'Bob']);
});

4. Custom Query Methods

// Add to your repository class
public function findByEmail($email)
{
    return $this->findWhere(['email' => $email])->first();
}

5. Repository Events

// Listen for model events
$repo->on('retrieved', function ($models) {
    // Post-process models after retrieval
});

Gotchas and Tips

Pitfalls

  1. Criteria Order Matters:

    • Criteria are applied in LIFO (Last-In-First-Out) order.
    • Example: pushCriteria(A) then pushCriteria(B) applies B first, then A.
    • Use popCriteria() to remove the last applied scope.
  2. Model Binding:

    • The repository does not automatically bind to the model’s primary key.
    • Always use find($id) or findWhere() explicitly.
  3. Transformer Conflicts:

    • Transformers are applied after Criteria but before returning results.
    • Overlapping transformers can lead to unexpected model states.
  4. Memory Leaks:

    • Avoid global Criteria in long-running processes (e.g., queues).
    • Use popCriteria() to clean up after operations.
  5. Mass Assignment:

    • The repository does not guard against mass assignment.
    • Use $model->fill() or $model->update() carefully.

Debugging Tips

  1. Query Logging: Enable Laravel’s query logging to inspect generated queries:

    DB::enableQueryLog();
    $repo->all();
    dd(DB::getQueryLog());
    
  2. Criteria Debugging: Temporarily override a Criteria’s apply() method to log conditions:

    $repo->pushCriteria(new class extends Criteria {
        public function apply($model, Builder $query)
        {
            \Log::debug('Criteria query:', [$query->toSql(), $query->getBindings()]);
            return parent::apply($model, $query);
        }
    });
    
  3. Transformer Debugging: Add a dump() in the transformer’s transform() method to inspect model states:

    $repo->pushTransformer(new class extends Transformer {
        public function transform($model)
        {
            \Log::debug('Model before transform:', $model->toArray());
            // ... transform logic ...
            return $model;
        }
    });
    

Extension Points

  1. Custom Criteria: Extend \Czim\Repository\Criteria\Criteria to create reusable scopes:

    class PublishedCriteria extends Criteria
    {
        public function apply($model, Builder $query)
        {
            return $query->where('published_at', '<=', now());
        }
    }
    
  2. Custom Transformers: Extend \Czim\Repository\Transformers\Transformer for model post-processing:

    class UserTransformer extends Transformer
    {
        public function transform($model)
        {
            $model->full_name = "{$model->first_name} {$model->last_name}";
            return $model;
        }
    }
    
  3. Repository Events: Listen for events like retrieved, created, or deleted:

    $repo->on('created', function ($model) {
        \Log::info("Model created: {$model->id}");
    });
    
  4. Repository Decorators: Decorate repositories to add cross-cutting concerns (e.g., logging, caching):

    class LoggingRepositoryDecorator extends Repository
    {
        public function __construct(RepositoryInterface $repo)
        {
            $this->repo = $repo;
        }
    
        public function find($id)
        {
            \Log::debug("Finding model ID: {$id}");
            return $this->repo->find($id);
        }
    }
    

Config Quirks

  1. Default Model Binding: The config (config/repository.php) allows setting a default model for repositories:

    'default_model' => \App\Models\User::class,
    
    • Useful for reducing boilerplate in repository constructors.
  2. Criteria Auto-Pushing: Disable auto-pushing of global Criteria in the config:

    'auto_push_criteria' => false,
    
    • Helps avoid unintended query modifications.
  3. Transformer Auto-Pushing: Control whether transformers are auto-applied:

    'auto_push_transformer' => true,
    

Performance Tips

  1. Avoid N+1 Queries: Always use with() for eager loading:

    $repo->with(['posts', 'comments'])->all();
    
  2. Batch Processing: Use chunk() for large datasets:

    $repo->chunk(100, function ($models) {
        foreach ($models as $model) {
            // Process batch
        }
    });
    
  3. Criteria Caching: Cache repeated Criteria applications:

    $repo->
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope