PHPackages                             koala-labs/pouch - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. koala-labs/pouch

ActiveLibrary[Database &amp; ORM](/categories/database)

koala-labs/pouch
================

A magical implementation of Laravel's Eloquent models as injectable, masked resource repositories.

3.2.1(3y ago)716.6k↓12.5%1MITPHPPHP ^7.4|^8.0

Since May 3Pushed 3y agoCompare

[ Source](https://github.com/koala-labs/pouch)[ Packagist](https://packagist.org/packages/koala-labs/pouch)[ Docs](https://koala.io/)[ RSS](/packages/koala-labs-pouch/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (5)Versions (17)Used By (0)

Koala Pouch
===========

[](#koala-pouch)

Koala Pouch is a fork of [Fuzz Production's Magic Box](https://github.com/fuzz-productions/magic-box)

##### Koala Pouch has two goals:

[](#koala-pouch-has-two-goals)

1. To create a two-way interchange format, so that the JSON representations of models broadcast by APIs can be re-applied back to their originating models for updating existing resources and creating new resources.
2. Provide an interface for API clients to request exactly the data they want in the way they want.

Installation/Setup
------------------

[](#installationsetup)

1. `composer require koala/pouch`
2. Use or extend `Koala\Pouch\Middleware\RepositoryMiddleware` into your project and register your class under the `$routeMiddleware` array in `app/Http/Kernel.php`. `RepositoryMiddleware` contains a variety of configuration options that can be overridden
3. If you're using `fuzz/api-server`, you can use magical routing by updating `app/Providers/RouteServiceProvider.php`, `RouteServiceProvider@map`, to include:

    ```
    /**
     * Define the routes for the application.
     *
     * @param  \Illuminate\Routing\Router $router
     * @return void
     */
    public function map(Router $router)
    {
        // Register a handy macro for registering resource routes
        $router->macro('restful', function ($model_name, $resource_controller = 'ResourceController') use ($router) {
            $alias = Str::lower(Str::snake(Str::plural(class_basename($model_name)), '-'));

            $router->resource($alias, $resource_controller, [
                'only' => [
                    'index',
                    'store',
                    'show',
                    'update',
                    'destroy',
                ],
            ]);
        });

        $router->group(['namespace' => $this->namespace], function ($router) {
            require app_path('Http/routes.php');
        });
    }
    ```
4. Set up your Pouch resource routes under the middleware key you assign to your chosen `RepositoryMiddleware` class
5. Set up a `YourAppNamespace\Http\Controllers\ResourceController`, [here is what a ResourceController might look like](https://gist.github.com/SimantovYousoufov/dea19adb1dfd8f05c1fcad9db976c247) .
6. Set up models according to `Model Setup` section

Testing
-------

[](#testing)

Just run `phpunit` after you `composer install`.

Eloquent Repository
-------------------

[](#eloquent-repository)

`Koala\Pouch\EloquentRepository` implements a CRUD repository that cascades through relationships, whether or not related models have been created yet.

Consider a simple model where a User has many Posts. EloquentRepository's basic usage is as follows:

Create a User with the username Steve who has a single Post with the title Stuff.

```
$repository = (new EloquentRepository)
    ->setModelClass('User')
    ->setInput([
        'username' => 'steve',
        'nonsense' => 'tomfoolery',
        'posts'    => [
            'title' => 'Stuff',
        ],
    ]);

$user = $repository->save();
```

When `$repository->save()` is invoked, a User will be created with the username "Steve", and a Post will be created with the `user_id` belonging to that User. The nonsensical "nonsense" property is simply ignored, because it does not actually exist on the table storing Users.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

[](#when-repository-save-is-invoked-a-user-will-be-created-with-the-username-steve-and-a-post-willbe-created-with-the-user_id-belonging-to-that-user-the-nonsensical-nonsense-property-is-simplyignored-because-it-does-not-actually-exist-on-the-table-storing-users)

***A limitation on Eloquent HasManyThrough relationships:***

Inputs that define a model related through a `HasManyThrough` relationship must refer to an already existing model. In this example, a `User` has many `Reaction`s through a `Post`. The `Reaction` model must exist and be related to a `Post` in order to correctly relate to the `User`.

```
$repository = (new EloquentRepository)
    ->setModelClass('User')
    ->setInput([
        'username' => 'steve',
        'posts'    => [
            'title' => 'Stuff',
        ],
        'reactions' => [
            [
                'id': 1 //The Reaction model must already exist, and relate to a Post
            ]
        ]
    ]);

$user = $repository->save();
```

A workaround for new `Reaction` and `Post` models attached to a `User` involves nesting the `Reaction` model data under the related `Post`

```
$repository = (new EloquentRepository)
    ->setModelClass('User')
    ->setInput([
        'username' => 'steve',
        //The Post is related to the User, and the Reaction is related to the Post. User Reactions are related through the Post.
        'posts'    => [
            'title' => 'Stuff',
            'reactions' => [
                [
                    'name' => 'John Doe',
                    'icon' => 'thumbs-up'
                ]
            ]
        ],

    ]);

$user = $repository->save();
```

Support for new models defined through a `HasThroughMany` relationship will come soon.

---

By itself, EloquentRepository is a blunt weapon with no access controls that should be avoided in any public APIs. It will clobber every relationship it touches without prejudice. For example, the following is a BAD way to add a new Post for the user we just created.

```
$repository
    ->setInput([
        'id' => $user->id,
        'posts'    => [
            ['title' => 'More Stuff'],
        ],
    ])
    ->save();
```

This will delete poor Steve's first post—not the intended effect. The safe(r) way to append a Post would be either of the following:

```
$repository
    ->setInput([
        'id' => $user->id,
        'posts'    => [
            ['id' => $user->posts->first()->id],
            ['title' => 'More Stuff'],
        ],
    ])
    ->save();
```

```
$post = $repository
    ->setModelClass('Post')
    ->setInput([
        'title' => 'More Stuff',
        'user' => [
            'id' => $user->id,
        ],
    ])
    ->save();
```

Generally speaking, the latter is preferred and is less likely to explode in your face.

The public API methods that return models from a repository are:

1. `create`
2. `read`
3. `update`
4. `delete`
5. `save`, which will either call `create` or `update` depending on the state of its input
6. `find`, which will find a model by ID
7. `findOrFail`, which will find a model by ID or throw `\Illuminate\Database\Eloquent\ModelNotFoundException`

The public API methods that return an `\Illuminate\Database\Eloquent\Collection` are:

1. `all`

Filtering
---------

[](#filtering)

`Koala\Pouch\Filter` handles Eloquent Query Builder modifications based on filter values passed through the `filters`parameter.

Tokens and usage:

TokenDescriptionExample`^`Field starts with`https://api.yourdomain.com/1.0/users?filters[name]=^John``$`Field ends with`https://api.yourdomain.com/1.0/users?filters[name]=$Smith``~`Field contains`https://api.yourdomain.com/1.0/users?filters[favorite_cheese]=~cheddar``50``>=`Field is greater than or equals`https://api.yourdomain.com/1.0/users?filters[lifetime_value]=>=50`` 'Bobby',
    'profile' => [
        'hobbies' => [
            ['name' => 'Hockey'],
            ['name' => 'Programming'],
            ['name' => 'Cooking']
        ]
    ]
]
```

We can filter users by their hobbies with `users?filters[profile.hobbies.name]=^Cook`.

This filter can be read as `select users with whose profile.hobbies.name begins with "Cook"`

Relationships can be of arbitrary depth.

### Filter conjunctions

[](#filter-conjunctions)

We can use `AND` and `OR` statements to build filters such as `users?filters[username]==Bobby&filters[or][username]==Johnny&filters[and][profile.favorite_cheese]==Gouda`. The PHP array that's built from this filter is:

```
[
    'username' => '=Bobby',
    'or'       => [
          'username' => '=Johnny',
          'and'      => [
              'profile.favorite_cheese' => '=Gouda',
          ]
    ]
]
```

and this filter can be read as `select (users with username Bobby) OR (users with username Johnny whose profile.favorite_cheese attribute is Gouda)`.

Other Parameters
----------------

[](#other-parameters)

### Pick

[](#pick)

We can limit the amount of data that comes back with your query by adding `pick` to the URL. Usage:

- `https://api.yourdomain.com/1.0/users?pick=id,username,occupation`
- `https://api.yourdomain.com/1.0/users?pick[]=id&pick[]=username&pick[]=occupation`

Model Setup
-----------

[](#model-setup)

Models need to implement `Koala\Pouch\Contracts\PouchResource` before Pouch will allow them to be exposed as a Pouch resource. This is done so exposure is an explicit process and no more is exposed than is needed.

Models also need to define their own `$fillable` array including attributes and relations that can be filled through this model. For example, if a User has many posts and has many comments but an API consumer should only be able to update comments through a user, the `$fillable` array would look like:

```
protected $fillable = ['username', 'password', 'name', 'comments'];

```

Pouch will only modify attributes/relations that are explicitly defined.

Resolving models
----------------

[](#resolving-models)

Pouch is great and all, but we don't want to resolve model classes ourselves before we can instantiate a repository...

If you've configured a RESTful URI structure with pluralized resources (i.e. `https://api.mydowmain.com/1.0/users` maps to the User model), you can use `Koala\Pouch\Utility\Modeler` to resolve a model class name from a route name.

Testing
-------

[](#testing-1)

`phpunit` :)

### TODO

[](#todo)

1. Route service provider should be pre-setup
2. Support more relationships (esp. polymorphic relations) through cascading saves.
3. Support paginating nested relations

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity31

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity76

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~196 days

Recently: every ~50 days

Total

14

Last Release

1119d ago

Major Versions

1.4 → 2.02021-11-09

2.0 → 3.02021-11-23

PHP version history (2 changes)1.3.x-devPHP ^7.0.0

2.0PHP ^7.4|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/1e5dd1b9f0b7abdb377e228374340e79fa4474b5174f93b3662e262e3ee5f027?d=identicon)[koala\_engineering](/maintainers/koala_engineering)

---

Top Contributors

[![stristr](https://avatars.githubusercontent.com/u/1203925?v=4)](https://github.com/stristr "stristr (39 commits)")[![SimantovYousoufov](https://avatars.githubusercontent.com/u/8379657?v=4)](https://github.com/SimantovYousoufov "SimantovYousoufov (15 commits)")[![jclarkkoala](https://avatars.githubusercontent.com/u/85902655?v=4)](https://github.com/jclarkkoala "jclarkkoala (12 commits)")[![maidoesthings](https://avatars.githubusercontent.com/u/7562272?v=4)](https://github.com/maidoesthings "maidoesthings (7 commits)")[![John2496](https://avatars.githubusercontent.com/u/280511?v=4)](https://github.com/John2496 "John2496 (5 commits)")[![kfuchs](https://avatars.githubusercontent.com/u/2237033?v=4)](https://github.com/kfuchs "kfuchs (3 commits)")[![walterbm](https://avatars.githubusercontent.com/u/7892079?v=4)](https://github.com/walterbm "walterbm (2 commits)")[![fuzzjham](https://avatars.githubusercontent.com/u/44976067?v=4)](https://github.com/fuzzjham "fuzzjham (2 commits)")

---

Tags

eloquentlaravelphp

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/koala-labs-pouch/health.svg)

```
[![Health](https://phpackages.com/badges/koala-labs-pouch/health.svg)](https://phpackages.com/packages/koala-labs-pouch)
```

###  Alternatives

[owen-it/laravel-auditing

Audit changes of your Eloquent models in Laravel

3.4k33.0M95](/packages/owen-it-laravel-auditing)[staudenmeir/eloquent-json-relations

Laravel Eloquent relationships with JSON keys

1.1k5.8M24](/packages/staudenmeir-eloquent-json-relations)[bavix/laravel-wallet

It's easy to work with a virtual wallet.

1.3k1.1M11](/packages/bavix-laravel-wallet)[dragon-code/migrate-db

Easy data transfer from one database to another

15717.4k](/packages/dragon-code-migrate-db)[gearbox-solutions/eloquent-filemaker

A package for getting FileMaker records as Eloquent models in Laravel

6454.8k2](/packages/gearbox-solutions-eloquent-filemaker)[cybercog/laravel-ownership

Laravel Ownership simplify management of Eloquent model's owner.

9126.6k3](/packages/cybercog-laravel-ownership)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
