PHPackages                             adhenrique/laravel-domain-oriented - 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. [Framework](/categories/framework)
4. /
5. adhenrique/laravel-domain-oriented

ActiveLibrary[Framework](/categories/framework)

adhenrique/laravel-domain-oriented
==================================

Build a domain-oriented application on Laravel Framework

v2.1.1(4y ago)111312[1 issues](https://github.com/adhenrique/laravel-domain-oriented/issues)MITPHP

Since Jan 7Pushed 4y ago1 watchersCompare

[ Source](https://github.com/adhenrique/laravel-domain-oriented)[ Packagist](https://packagist.org/packages/adhenrique/laravel-domain-oriented)[ Docs](https://github.com/adhenrique/laravel-domain-oriented)[ RSS](/packages/adhenrique-laravel-domain-oriented/feed)WikiDiscussions master Synced today

READMEChangelog (9)Dependencies (2)Versions (11)Used By (0)

Laravel Domain Oriented
=======================

[](#laravel-domain-oriented)

This package builds a structure to domain-oriented APIs (not DDD, they are different things). With search filters, validations and clean code.

Requirements
------------

[](#requirements)

- PHP 7.2+, 8.0 (new version)
- Laravel 7.x, 8 (prefer-stable)

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

[](#introduction)

My need was simple: build structures in an organized and productive way. A structure that supports filters, validations and data caching (CQRS).

Before proceeding, take a look at the final structure:

```
app
├── ...
├── Domain
│   └── Dummy
│       ├── DummyFilterService.php
│       ├── DummyPersistenceModel.php
│       ├── DummyPersistenceService.php
│       ├── DummyPolicy.php
│       ├── DummyResource.php
│       ├── DummySearchModel.php
│       ├── DummySearchService.php
│       └── DummyValidateService.php
├── Http
│   ├── Controllers
│   │   ├── ...
│   │   └── DummyController.php
├── ...
database
├── factories
│   └── ...
│   └── DummyFactory.php
├── migrations
│   ├── ...
│   └── 2021_01_06_193044_create_dummies_table.php
└── seeders
    ├── DatabaseSeeder.php
    └── DummySeeder.php
```

You must be asking yourself:

1. Why not use Repository Pattern?
    A. It is not possible to obtain a database abstraction more than what Eloquent offers. [1](https://adelf.tech/2019/useless-eloquent-repositories "Please, stop talking about Repository pattern with Eloquent")
2. What is the idea of PersistenceModel, and SearchModel?
    A. In fact, I go further. Model instances of Eloquent should not be returned. So we guarantee a "read-only" instance (which is not used for persistence in the database) [2](https://adelf.tech/2019/read-eloquent-repositories "Useful Eloquent Repositories?") [3](https://medium.com/laraveltips/voc%C3%AA-entende-repository-pattern-voc%C3%AA-est%C3%A1-certo-disso-d739ecaf544e "Você entende Repository Pattern? Você está certo disso?")
3. There are a lot of files, how do I build it all?
    A. It's simple, get a coffee and let's do it...

Setup
-----

[](#setup)

1. Run this Composer command to install the latest version

```
$ composer require adhenrique/laravel-domain-oriented
```

2. If you prefer, you can export the location files:

```
php artisan vendor:publish --provider="LaravelDomainOriented\ServiceProvider" --tag="lang"
```

3. Run this command to build the domain structure:

```
$ php artisan domain:create Dummy
```

4. Stay calm. If the structure already exists, the console asks you if you want to rewrite it, unless you pass the `--force` flag:

```
$ php artisan domain:create Dummy --force
```

5. And of course, if you want to remove the structure, just run this command:

```
$ php artisan domain:remove Dummy
```

That's it enjoy!

Configuration
-------------

[](#configuration)

### Adjust your Models

[](#adjust-your-models)

Our Model's follow the [Eloquent Model Conventions](https://laravel.com/docs/8.x/eloquent#eloquent-model-conventions)

- PersistenceModel: used only for persistence in the database. Define your fields, casts, etc...
- SearchModel: used for searches. It is very likely that your [relationship](https://laravel.com/docs/8.x/eloquent-relationships) will be here.

### Adjust your Migrations

[](#adjust-your-migrations)

Our Migrations follow the [Laravel Migration Structure](https://laravel.com/docs/8.x/migrations#migration-structure)

### Adjust your Seeders and Factories

[](#adjust-your-seeders-and-factories)

Here, too, we follow the Laravel way of doing things:

- [Factories](https://laravel.com/docs/8.x/database-testing)
- [Seeders](https://laravel.com/docs/8.x/seeding)

### Adjust your Policy

[](#adjust-your-policy)

Again, Policies follow the [Laravel Policy Authorization](https://laravel.com/docs/8.x/authorization#writing-policies)

> Note: You don't have to worry about registering your policies, as we do it behind the scenes. However, here we follow a class name convention. When creating a domain, your class must be named SomethingPolicy and belong to the App\\Domain\\Something namespace.

### Config your validations

[](#config-your-validations)

ValidateService is located at `app/Domain/YourDomainName/*`:

```
use LaravelDomainOriented\Services\ValidateService;

class DummyValidateService extends ValidateService
{
    protected array $rules = [
        // You can define general validation rules, which will be inherited
        // for all actions, or you can define validation rules for each action:
        // SHOW, STORE, UPDATE, DESTROY

        // General rules validation.
        // If any action validation rule is not defined, it will inherit from here.
        'name' => 'required|string',

        // Specific action rules validation. If set, ignores general validations.
        self::SHOW => [
            'id' => 'required|integer',
        ],
        self::UPDATE => [
            'id' => 'required|integer',
            'name' => 'required|string',
        ],
        self::DESTROY => [
            'id' => 'required|integer',
        ],
    ];
}
```

### Config routes

[](#config-routes)

We follow [Laravel routes](https://laravel.com/docs/8.x/routing) pattern. But as we are dealing with API, modify the file `routes/api.php`, adding the following routes:

```
Route::get('dummies', 'App\Http\Controllers\DummyController@index');
Route::get('dummies/{id}', 'App\Http\Controllers\DummyController@show');
Route::post('dummies', 'App\Http\Controllers\DummyController@store');
Route::put('dummies/{id}', 'App\Http\Controllers\DummyController@update');
Route::delete('dummies/{id}', 'App\Http\Controllers\DummyController@destroy');
```

Using
-----

[](#using)

### Before Search filters

[](#before-search-filters)

In the SearchService class you have two methods that help you to pre-start queries according to your needs: `beforeAll` and` beforeFindById`. Each method receives 2 parameters: `builder` with the Eloquent instance started and `auth`, with the user session - if are logged in. You just need to override the methods, but ensure that the return is eloquent's `Builder`. Look:

```
class DummySearchService extends SearchService
{
    protected SearchModel $model;
    protected FilterService $filterService;

    public function __construct(DummySearchModel $model, DummyFilterService $filterService)
    {
        $this->model = $model;
        $this->filterService = $filterService;
    }

    public function beforeAll(Builder $builder, Guard $auth): Builder
    {
        return $builder;
    }

    public function beforeFindById(Builder $builder, Guard $auth): Builder
    {
        return $builder;
    }
}
```

In my use case, logged in as admin, I usually filter from the list of users my own user. Look:

```
// ...
public function beforeAll(Builder $builder, Guard $auth): Builder
{
    return $this->removeLoggedFromSearches($builder, $auth);
}

private function removeLoggedFromSearches($builder, $auth)
{
    $id = $auth->id();
    return $builder->where('id', '', $id);
}
```

### Searching with filters

[](#searching-with-filters)

You can filter and paginate the data on the listing routes. To do this, send a payload on the request, using your favorite client:

**Simple Where:**

```
{
    "name": "adhenrique",
    "email": "eu@adhenrique.com.br"
}
```

**Where in:**

```
{
    "id": [1,2,3]
}
```

**Where by operator (like, &gt;, =&gt;, &lt;, &lt;=, &lt;&gt;):**

```
{
    "name": {
        "operator": "like",
        "value": "%adhenrique%"
    }
}
```

**Where between:**

```
{
    "birthdate": {
        "start": "1988-13-12",
        "end": "2021-01-01"
    }
}
```

**Paginate results**

```
{
    "paginate": {
        "per_page": 1,
        "page": 1
    }
}
```

**Note:** You can use the filters and pagination together.

Todo
----

[](#todo)

- CQRS
- Support for old Laravel versions
- Or Where filter
- OOP improvements
- Add beforeAll and beforeFindById tests
- Ask to confirm name
- Add way to test Policies

Testing
-------

[](#testing)

```
$ composer test
```

### Changelog

[](#changelog)

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

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

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Bruno Maranesi](https://github.com/maranesi)
- [Adelf](https://adelf.tech/)
- [Brent](https://stitcher.io/)

License
-------

[](#license)

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

Reading Articles
----------------

[](#reading-articles)

\[1\] [Please, stop talking about Repository pattern with Eloquent](https://adelf.tech/2019/useless-eloquent-repositories)
\[2\] [Useful Eloquent Repositories?](https://adelf.tech/2019/read-eloquent-repositories)
\[3\] [Você entende Repository Pattern? Você está certo disso?](https://medium.com/laraveltips/voc%C3%AA-entende-repository-pattern-voc%C3%AA-est%C3%A1-certo-disso-d739ecaf544e)
[Laravel — Why you’ve been using the Repository Pattern the wrong way](https://medium.com/@sergiumneagu/laravel-why-youve-been-using-the-repository-pattern-the-wrong-way-952aedf1989b)

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

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

Recently: every ~89 days

Total

9

Last Release

1584d ago

Major Versions

v1.1.3 → v2.0.02021-01-14

### Community

Maintainers

![](https://www.gravatar.com/avatar/ed698989d6da39d04f57bdd7afe6c94b1d1e05d0878765d3f90f64919c175260?d=identicon)[adhenrique](/maintainers/adhenrique)

---

Top Contributors

[![adhenrique](https://avatars.githubusercontent.com/u/11527271?v=4)](https://github.com/adhenrique "adhenrique (59 commits)")

---

Tags

ddddomaindomain-builderdomain-driven-designdomain-orientedlaravellaravel-frameworklaravel-librarylaravel-packagelaravellaravel-packageDomain Driven Designdddlaravel-librarydomain orienteddomain builder

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/adhenrique-laravel-domain-oriented/health.svg)

```
[![Health](https://phpackages.com/badges/adhenrique-laravel-domain-oriented/health.svg)](https://phpackages.com/packages/adhenrique-laravel-domain-oriented)
```

###  Alternatives

[lunarstorm/laravel-ddd

A Laravel toolkit for Domain Driven Design patterns

17959.0k](/packages/lunarstorm-laravel-ddd)[nwidart/laravel-broadway

A Laravel adapter for the Broadway ES/CQRS package.

12315.0k](/packages/nwidart-laravel-broadway)

PHPackages © 2026

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