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

Warehouse Laravel Package

artesaos/warehouse

Warehouse V2 is a Laravel repository-pattern demo/package that centralizes queries and business rules while still returning Eloquent models and Collections. Use it as a ready-to-use repository layer without giving up Eloquent’s practicality.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require artesaos/warehouse 2.x-dev
    

    Register the service provider in config/app.php (only if using Fractal):

    'providers' => [
        Artesaos\Warehouse\WarehouseServiceProvider::class,
    ],
    
  2. Create a Repository: Define a repository class extending BaseRepository or AbstractCrudRepository:

    namespace App\Repositories;
    
    use App\Models\User;
    use Artesaos\Warehouse\BaseRepository;
    
    class UserRepository extends BaseRepository
    {
        protected $modelClass = User::class;
    }
    
  3. First Use Case: Inject the repository into a controller/service and use its methods:

    public function index(UserRepository $userRepo)
    {
        $users = $userRepo->getAll(10); // Paginated list
        return view('users.index', compact('users'));
    }
    

Key Starting Points

  • BaseRepository: For basic CRUD operations.
  • AbstractCrudRepository: For full CRUD methods (if available in later versions).
  • newQuery(): Access the Eloquent query builder for custom queries.
  • doQuery(): Execute queries with pagination/take logic.

Implementation Patterns

Core Workflows

  1. Basic CRUD:

    // Get all (paginated)
    $users = $userRepo->getAll(15);
    
    // Find by ID (throws ModelNotFoundException if not found)
    $user = $userRepo->findByID(1);
    
    // List specific columns
    $names = $userRepo->lists('name');
    
  2. Custom Queries: Override newQuery() or use doQuery():

    public function activeUsers()
    {
        return $this->doQuery($this->newQuery()->where('active', true));
    }
    
  3. Dependency Injection: Register repositories in Laravel's IoC container (optional but recommended):

    $this->app->bind(
        UserRepository::class,
        function ($app) {
            return new UserRepository(new User());
        }
    );
    
  4. Integration with Services: Use repositories in services to encapsulate business logic:

    class UserService {
        public function __construct(private UserRepository $userRepo) {}
    
        public function getActiveUsers()
        {
            return $this->userRepo->activeUsers();
        }
    }
    

Advanced Patterns

  1. Repository Interfaces: Define interfaces for repositories to enforce contracts:

    interface UserRepositoryInterface {
        public function getAll($take = 15, $paginate = true);
        public function findByID($id, $fail = true);
    }
    
  2. Query Scopes: Use Eloquent scopes in repositories:

    class UserRepository extends BaseRepository {
        protected function newQuery()
        {
            return parent::newQuery()->with(['posts']);
        }
    }
    
  3. Event Handling: Dispatch events in repositories (e.g., after save):

    public function save(array $data)
    {
        $model = $this->modelClass::create($data);
        event(new UserCreated($model));
        return $model;
    }
    

Gotchas and Tips

Pitfalls

  1. Archived Package:

  2. No Full CRUD in Base:

    • BaseRepository lacks full CRUD methods (e.g., create, update, delete). Extend AbstractCrudRepository if available (check for v3+ updates).
  3. Fractal Dependency:

    • Fractal (for API responses) is optional but requires manual setup. Avoid if not needed.
  4. Eloquent Overhead:

    • Returns Eloquent models/collections, which may not align with strict Repository Pattern principles (e.g., avoiding ORM coupling).
  5. No Query Builder:

    • Lacks built-in query filtering (e.g., no scopeWhere() or scopeFilter()). Implement manually:
      public function scopeActive($query)
      {
          return $query->where('active', true);
      }
      

Debugging Tips

  1. Query Logging: Enable Eloquent logging in config/logging.php:

    'eloquent' => [
        'driver' => 'single',
        'level' => 'debug',
        'channel' => env('LOG_CHANNEL', 'stack'),
    ],
    
  2. ModelNotFoundException: Catch exceptions when $fail = true in findByID():

    try {
        $user = $userRepo->findByID(999);
    } catch (ModelNotFoundException $e) {
        abort(404);
    }
    
  3. Pagination Issues: Ensure $take is an integer for getAll():

    // Correct:
    $users = $userRepo->getAll(10);
    
    // Avoid:
    $users = $userRepo->getAll('10'); // May fail silently
    

Extension Points

  1. Custom Methods: Add domain-specific methods to repositories:

    public function getUsersWithPosts()
    {
        return $this->doQuery($this->newQuery()->with('posts'));
    }
    
  2. Model Events: Hook into Eloquent events in repositories:

    public function save(array $data)
    {
        $model = $this->modelClass::create($data);
        $model->fresh()->fireModelEvent('saved', false);
        return $model;
    }
    
  3. Caching: Cache repository results (e.g., getAll):

    public function getAll($take = 15, $paginate = true)
    {
        return Cache::remember("users_{$take}_{$paginate}", now()->addHours(1), function () use ($take, $paginate) {
            return parent::getAll($take, $paginate);
        });
    }
    
  4. Testing: Mock repositories in tests:

    $mockRepo = Mockery::mock(UserRepository::class);
    $mockRepo->shouldReceive('getAll')->andReturn(collect([$fakeUser]));
    

Configuration Quirks

  • Service Provider: Only register WarehouseServiceProvider if using Fractal. Otherwise, skip it.
  • Model Class: Always define protected $modelClass in your repository class.
  • Pagination: getAll() defaults to pagination ($paginate = true). Pass false to disable:
    $users = $userRepo->getAll(10, false); // Returns Collection, not Paginator
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity