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 Service Pattern Laravel Package

adobrovolsky97/laravel-repository-service-pattern

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require adobrovolsky97/laravel-repository-service-pattern
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Adobrovolsky97\LaravelRepositoryServicePattern\RepositoryServicePatternServiceProvider" --tag="config"
    
  2. Define a Repository Interface: Create a contract for your repository (e.g., app/Repositories/Contracts/UserRepositoryInterface.php):

    namespace App\Repositories\Contracts;
    
    interface UserRepositoryInterface {
        public function find(int $id);
        public function all();
        public function create(array $data);
    }
    
  3. Implement the Repository: Extend BaseRepository (e.g., app/Repositories/Eloquent/UserRepository.php):

    namespace App\Repositories\Eloquent;
    
    use App\Models\User;
    use App\Repositories\Contracts\UserRepositoryInterface;
    use Adobrovolsky97\LaravelRepositoryServicePattern\BaseRepository;
    
    class UserRepository extends BaseRepository implements UserRepositoryInterface {
        public function model() {
            return User::class;
        }
    }
    
  4. Bind the Repository in a Service Provider: Register the binding in AppServiceProvider:

    $this->app->bind(
        UserRepositoryInterface::class,
        UserRepository::class
    );
    
  5. First Use Case: Inject the repository into a controller or service:

    use App\Repositories\Contracts\UserRepositoryInterface;
    
    class UserController extends Controller {
        protected $userRepository;
    
        public function __construct(UserRepositoryInterface $userRepository) {
            $this->userRepository = $userRepository;
        }
    
        public function index() {
            $users = $this->userRepository->all();
            return view('users.index', compact('users'));
        }
    }
    

Implementation Patterns

Core Workflows

  1. CRUD Operations: Leverage the base repository methods (find, findByField, create, update, delete) for standard operations:

    $user = $this->userRepository->find(1);
    $user = $this->userRepository->create(['name' => 'John']);
    $this->userRepository->update(1, ['name' => 'Jane']);
    
  2. Query Scopes: Define custom scopes in your model and use them via the repository:

    // In User model:
    public function scopeActive($query) {
        return $query->where('active', true);
    }
    
    // In controller:
    $activeUsers = $this->userRepository->scopeQuery('active')->all();
    
  3. Service Layer Integration: Use repositories in services to encapsulate business logic:

    class UserService {
        protected $userRepository;
    
        public function __construct(UserRepositoryInterface $userRepository) {
            $this->userRepository = $userRepository;
        }
    
        public function register(array $data) {
            $user = $this->userRepository->create($data);
            // Additional logic (e.g., send welcome email)
            return $user;
        }
    }
    
  4. Transaction Management: Wrap repository operations in transactions:

    DB::transaction(function () {
        $this->userRepository->create($userData);
        $this->orderRepository->create($orderData);
    });
    
  5. Event Dispatching: Trigger events after repository operations:

    $this->userRepository->create($data, true); // `true` dispatches `created` event
    

Advanced Patterns

  1. Repository Factories: Dynamically resolve repositories based on conditions:

    $repository = app()->make(\App\Repositories\Contracts\UserRepositoryInterface::class);
    
  2. Caching: Cache repository results using Laravel's cache:

    $this->userRepository->remember(60)->find(1); // Cache for 60 seconds
    
  3. API Integration: Use repositories to abstract API calls (e.g., for third-party services):

    class ThirdPartyUserRepository extends BaseRepository {
        public function model() {
            return ThirdPartyUser::class; // Mock model or API client
        }
    }
    
  4. Soft Deletes: Enable soft deletes in the repository:

    $this->userRepository->delete(1, true); // Soft delete
    
  5. Pagination: Use built-in pagination:

    $users = $this->userRepository->paginate(10);
    

Gotchas and Tips

Common Pitfalls

  1. Over-Abstraction:

    • Issue: Adding unnecessary repositories for simple queries (e.g., User::where(...)->get()).
    • Fix: Reserve repositories for complex or reusable data access logic.
  2. N+1 Query Problem:

    • Issue: Eager loading relationships in loops without proper scoping.
    • Fix: Use with() in repository methods or leverage Laravel's load():
      $this->userRepository->with('posts')->find(1);
      
  3. Repository Bloat:

    • Issue: Stuffing business logic into repositories.
    • Fix: Keep repositories thin; move logic to services.
  4. Forgetting to Bind Interfaces:

    • Issue: Using concrete repositories directly instead of interfaces.
    • Fix: Always bind interfaces in the service provider.
  5. Ignoring Base Repository Features:

    • Issue: Reimplementing basic methods (e.g., find, all) when they exist in BaseRepository.
    • Fix: Extend BaseRepository and override only custom methods.

Debugging Tips

  1. Query Logging: Enable Laravel's query logging to inspect repository-generated queries:

    DB::enableQueryLog();
    $this->userRepository->all();
    dd(DB::getQueryLog());
    
  2. Repository Method Tracing: Use dd() or dump() to trace repository method calls:

    public function customMethod() {
        dump('Custom method called'); // Debug entry point
        // ...
    }
    
  3. Interface Mismatches:

    • Error: Class 'App\Repositories\Eloquent\UserRepository' not found.
    • Fix: Ensure the repository is properly bound in the service provider and the namespace is correct.

Configuration Quirks

  1. Caching Defaults:

    • The package enables caching by default. Disable it in config/repository-service-pattern.php if needed:
      'cache' => [
          'enabled' => false,
      ],
      
  2. Event Dispatching:

    • Events are disabled by default. Enable them per-operation:
      $this->userRepository->create($data, true); // Dispatches events
      
  3. Model Binding:

    • Ensure the model() method in your repository returns the fully qualified class name of your Eloquent model.

Extension Points

  1. Custom Base Repository:

    • Extend BaseRepository to add shared methods:
      class CustomBaseRepository extends BaseRepository {
          public function findByEmail(string $email) {
              return $this->model->where('email', $email)->first();
          }
      }
      
  2. Repository Events:

    • Listen to repository events (e.g., repository.created) in EventServiceProvider:
      protected $listen = [
          'repository.created' => [
              'App\Listeners\LogUserCreation',
          ],
      ];
      
  3. Repository Middleware:

    • Add middleware to repository methods (e.g., for authorization):
      class UserRepository extends BaseRepository {
          public function find(int $id) {
              if (!auth()->can('view-user', $id)) {
                  abort(403);
              }
              return parent::find($id);
          }
      }
      
  4. Dynamic Repository Resolution:

    • Use the resolveRepository() helper to dynamically resolve repositories:
      $repository = resolveRepository(UserRepositoryInterface::class);
      
  5. Testing:

    • Mock repositories in tests:
      $mock = Mockery::mock(UserRepositoryInterface::class);
      $mock->shouldReceive('find')->andReturn($user);
      $this->app->instance(UserRepositoryInterface::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.
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