PHPackages                             royvoetman/laravel-repository-pattern - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. royvoetman/laravel-repository-pattern

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

royvoetman/laravel-repository-pattern
=====================================

Middleware for Eloquent Models

v2.0.4(2y ago)201393MITPHPPHP ^7.4 || ^8.0CI failing

Since Oct 27Pushed 1y ago2 watchersCompare

[ Source](https://github.com/RoyVoetman/laravel-repository-pattern)[ Packagist](https://packagist.org/packages/royvoetman/laravel-repository-pattern)[ RSS](/packages/royvoetman-laravel-repository-pattern/feed)WikiDiscussions master Synced today

READMEChangelog (8)Dependencies (6)Versions (9)Used By (0)

[![](https://camo.githubusercontent.com/0df55e0a3a59e6dd2986f2091ef5729bd16edd75f00ae995778a6fac7a3fa531/68747470733a2f2f7777772e63732d6c6962726172792e636f6d2f696d616765732f7061636b616765732f7265706f7369746f72792d7061747465726e2e737667)](https://camo.githubusercontent.com/0df55e0a3a59e6dd2986f2091ef5729bd16edd75f00ae995778a6fac7a3fa531/68747470733a2f2f7777772e63732d6c6962726172792e636f6d2f696d616765732f7061636b616765732f7265706f7369746f72792d7061747465726e2e737667)

Middleware for Eloquent Models

[![Latest Version](https://camo.githubusercontent.com/ac3e34744804185d205510ec445c9a675a76b2f11baa088add3f7dc4c7bd6b3f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f79766f65746d616e2f6c61726176656c2d7265706f7369746f72792d7061747465726e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/royvoetman/laravel-repository-pattern)[![MIT Licensed](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Total Downloads](https://camo.githubusercontent.com/71fd56d86d12f11ad47b6e15bba560811c8044a619406b631626c4fbd163a5a2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726f79766f65746d616e2f6c61726176656c2d7265706f7369746f72792d7061747465726e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/royvoetman/laravel-repository-pattern)

Table of Contents
-----------------

[](#table-of-contents)

- [Introduction](#introduction)
- [Installation](#installation)
- [Repositories](#repositories)
    - [Defining repositories](#defining-repositories)
    - [Inserting &amp; Updating Models](#inserting--updating-models)
    - [Deleting Models](#deleting-models)
- [Pipes](#pipes)
    - [Defining Pipes](#defining-pipes)
    - [Before &amp; After Pipes](#before--after-pipes)
    - [Using Pipes](#using-pipes)
    - [Pipe Groups](#pipe-groups)
- [Transactions](#transactions)
- [Pipe Parameters](#pipe-parameters)
- [Changelog](#changelog)

Introduction
------------

[](#introduction)

This package provides a convenient mechanism for grouping data manipulation logic, which is equivalent to Laravel's native HTTP middleware. However, to prevent any confusion with HTTP middleware hereafter this mechanism will be referred to in its more general form called a `pipeline`. In fact, Laravel provides its own Pipeline implementation which is used by middleware under the hood.

A pipeline is a design pattern that composes several different classes (`pipes`) and applies them consecutively. All pipes receive a so-called passable and result in a so-called returnable. In the context of HTTP middleware, the passable is the HTTP request object and the returnable is the HTTP response object. Conversely, in the context of a repository, the `model-data array` is classified as the passable and the resulting Eloquent model object is the returnable. Typically, each pipe will filter or alter the passable that is sent through the pipeline. As a result, creating an easily extensible architecture where each pipe concerns itself with one task. For example, this package provides a pipe that automatically hashes passwords before saving them to the database. Thus, centralizing your password hashing logic and thereby removing responsibility from your other classes.

Additional pipes can be written to perform a variety of tasks besides modifying column values. A translation pipe might save all translations for certain columns to a separate translations table. A transaction pipe might run specific groups of queries in a database transaction. There are a few pipes already included in this package, including pipes for password hashing and database transactions. All of these default pipes will be elaborated upon, along with information on how to define your own pipes.

Installation
------------

[](#installation)

```
composer require royvoetman/laravel-repository-pattern
```

Repositories
------------

[](#repositories)

### Defining repositories

[](#defining-repositories)

First, create a class that extends the `RoyVoetman\Repositories\Repository` class. Second, the repository should be made aware of what model it is associated with by equating the `$model` field to the fully qualified class name of the model. Finally, pipes can be defined by stating them in the `$pipes` field.

```
class BooksRepository extends Repository
{
    protected string $model = Book::class;

    protected array $pipes = [
        'save' => [Translate::class],
        'delete' => [DeleteTranslations::class]
    ];
}
```

#### Generator command

[](#generator-command)

```
php artisan make:repository BooksRepository
```

### Inserting &amp; Updating Models

[](#inserting--updating-models)

`save(array $data, Model $model = null): ?Model`

#### Inserts

[](#inserts)

To create a new database record, instantiate the associated repository, pass the model attributes as an associative array, then call the save method.

```
$book = (new BooksRepository())->save([
  'name' => 'Laravel',
  'author' => 'Taylor Otwell'
]);
```

#### Updates

[](#updates)

The save method may also be used to update models that already exist in the database. To update a model, you should retrieve it, pass any model attributes you which to update in combination with the retrieved model, and then call the save method.

```
$book = Book::find(1);

$updatedBook = (new BooksRepository())->save([
  'name' => 'Laravel!',
  'author' => 'Taylor Otwell'
], $book);
```

### Deleting Models

[](#deleting-models)

`delete(Model $model): bool`

To delete a model, retrieve the model, pass the model to the repository, and then call the delete method.

```
$book = Book::find(1);

(new BooksRepository())->delete($book);
```

Pipes
-----

[](#pipes)

### Defining Pipes

[](#defining-pipes)

To create a new pipe, use the `make:pipe` generator command:

```
php artisan make:pipe HashPassword
```

This command will place a new `HashPassword` class within your `app/Repositories/Pipes` directory. In this pipe, we will check if a password key has been defined. If so, the password will be hashed and replaced with the plain text password.

```
class HashPassword
{
    public function handle($data, Closure $next): Model
    {
        if(Arr::has($data, 'password')) {
            $data['password'] = bcrypt($data['password']);
        }

        return $next($data);
    }
}
```

However pipes that are applied to a **delete** action receive an Eloquent Model as the first parameter instead of a `$data` array with model-data. To create a delete pipe, add the `--delete` option to the generator command.

```
php artisan make:pipe RemoveBookRelations --delete
```

```
class RemoveBookRelations
{
    public function handle(Model $book, Closure $next)
    {
        $book->author()->delete();
        $book->reviews()->delete();

        return $next($book);
    }
}
```

### Before &amp; After Pipes

[](#before--after-pipes)

Whether a pipe runs before or after the insertion/update/deletion of the model depends on the pipe itself. For example, the following pipe would perform some task before any data manipulations are made persistent:

```
class BeforePipe
{
    public function handle($data, Closure $next)
    {
        // Perform actions on the model-data
        // e.g. hashing passwords

        return $next($data);
    }
}
```

However, this pipe would perform its task after the data manipulations are made persisted:

```
class AfterPipe
{
    public function handle($data, Closure $next): Model
    {
        $model = $next($data);

        // Perform actions on Eloquent model
        // e.g. saving relationships

        return $model;
    }
}
```

### Using Pipes

[](#using-pipes)

This package defines the following actions that can be used in the `$pipes` array of your repository. These arrays will automatically be applied when the corresponding actions occur:

ActionApplied when`create`A new model is created`update`An existing model is updated`save`A model is being created or updated`delete`A model is deleted```
class BooksRepository extends Repository
{
    protected array $pipes = [
        'create' => [...],
        'update' => [...],
        'save' => [...],
        'delete' => [...]
    ];

    ...
}
```

Alternatively pipes can be defined at runtime by using the `with` method.

```
(new BooksRepository())->with(Translate::class)->create([
    ...
]);
```

### Pipe Groups

[](#pipe-groups)

Sometimes you may want to group several pipes under a single key to make them easier to apply. You may do this using the `$pipeGroups` field in your repository. For example, you may want to apply special logic when saving a VIP user as opposed to a regular user:

```
class UsersRepository extends Repository
{
    protected string $model = Book::class;

    protected array $pipeGroups = [
        'vip' => [
            AddVipPermissions::class,
            EnrollToVipChannel::class
        ]
    ];
}
```

You may then apply the group by calling the `withGroup` method.

```
$user = (new UsersRepository())->withGroup('vip')->save([
  'name' => 'Roy Voetman',
  'email' => 'info@example.com',
  ...
]);
```

Transactions
------------

[](#transactions)

This package provides a transaction pipe which can be used to run a certain pipeline in a database transaction. For example, the `UsesTransaction` interface could be implemented by the repository to indicate that every pipeline should run in a transaction.

```
class BooksRepository extends Repository implements UsesTransaction
{
    protected string $model = Book::class;
}
```

By implementing `UsesTransaction` the case in which inserting a record or saving the translations raises an exception will not cause data inconsistencies. In fact, when an exception is raised the transaction will be rolled back.

Furthermore, the `transaction()` method could be used to specify that only the current pipeline should be run inside a transaction.

```
$book = $books->transaction()->save([
  'name' => 'Laravel',
  'author' => 'Taylor Otwell'
]);
```

> Caution: the `Transaction` pipe can also be used by adding it to the `$pipes` field. However, since the pipes are run consecutively it should be the first pipe in the array. The techniques discussed above automatically prepend the pipe to the beginning of the pipe stack.

Pipe Parameters
---------------

[](#pipe-parameters)

Pipes can also receive additional parameters. For example, if want to apply the transaction pipe with a specific number of retries, you could pass an integer indicating the retries as an additional argument.

To clarify, the transaction pipe is defined as follows:

```
class Transaction
{
    public function handle($passable, \Closure $next, int $attempts)
    {
        return DB::transaction(fn () => $next($passable), $attempts);
    }
}
```

Pipe parameters may be specified when defining the `$pipes` array by separating the class name and parameters with a :. Multiple parameters should be delimited by commas:

```
class BooksRepository extends Repository
{
    protected array $pipes = [
        'save' => [
            '\RoyVoetman\Repositories\Pipes\Transaction:3'
        ],
    ];

    ...
}
```

However, pipe parameters can also be defined at runtime by using the `with` method on the repository.

```
(new BooksRepository())
    ->with('\RoyVoetman\Repositories\Pipes\Transaction:3')
    ->create([
        ...
    ]
);
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Contributing
------------

[](#contributing)

Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/RoyVoetman/laravel-repository-pattern).

### Pull Requests

[](#pull-requests)

- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
- **Create feature branches** - Don't ask us to pull from your master branch.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance32

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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 ~189 days

Recently: every ~238 days

Total

8

Last Release

1060d ago

Major Versions

v1.0.2 → v2.0.02020-11-05

PHP version history (3 changes)v1.0.0PHP ^7.2

v2.0.0PHP ^7.4

v2.0.3PHP ^7.4 || ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/23026444?v=4)[Roy Voetman](/maintainers/RoyVoetman)[@RoyVoetman](https://github.com/RoyVoetman)

---

Top Contributors

[![RoyVoetman](https://avatars.githubusercontent.com/u/23026444?v=4)](https://github.com/RoyVoetman "RoyVoetman (125 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/royvoetman-laravel-repository-pattern/health.svg)

```
[![Health](https://phpackages.com/badges/royvoetman-laravel-repository-pattern/health.svg)](https://phpackages.com/packages/royvoetman-laravel-repository-pattern)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k43.5M5.2k](/packages/larastan-larastan)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[spatie/laravel-enum

Laravel Enum support

3655.4M31](/packages/spatie-laravel-enum)[orchestra/canvas

Code Generators for Laravel Applications and Packages

21017.2M158](/packages/orchestra-canvas)[laragear/preload

Effortlessly make a Preload script for your Laravel application.

119363.5k](/packages/laragear-preload)

PHPackages © 2026

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