PHPackages                             dorayaki4369/laravel-decorator - 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. dorayaki4369/laravel-decorator

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

dorayaki4369/laravel-decorator
==============================

The decorator package for Laravel

v0.2.0(1y ago)11[1 issues](https://github.com/dorayaki4369/laravel-decorator/issues)MITPHPPHP ^8.2CI passing

Since Feb 24Pushed 1y ago1 watchersCompare

[ Source](https://github.com/dorayaki4369/laravel-decorator)[ Packagist](https://packagist.org/packages/dorayaki4369/laravel-decorator)[ RSS](/packages/dorayaki4369-laravel-decorator/feed)WikiDiscussions main Synced 1mo ago

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

Laravel Decorator
=================

[](#laravel-decorator)

This package provides a simple way to implement the decorator pattern in Laravel.

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

[](#installation)

Require this package with composer using the following command:

```
composer require dorayaki4369/laravel-decorator
```

Usage
-----

[](#usage)

### 1. Create a decorator

[](#1-create-a-decorator)

You can create a decorator by implementing the `Dorayaki4369\LaravelDecorator\Contracts\Attributes\Decorator` interface.

The decorator class must implement the `decorate` method. the method is a similar to `handle` method of [Middleware](https://laravel.com/docs/11.x/middleware).

```
namespace App\Attributes;

use Dorayaki4369\LaravelDecorator\Contracts\Attributes\Decorator;

class LogDecorator implements Decorator
{
    public function decorate(callable $next, array $args, object $instance, string $parentClass, string $method): mixed
    {
        // Before the method is called
        \Illuminate\Support\Facades\Log::debug('Before the method is called');

        $result = $next($args, $instance, $parentClass, $method);

        // After the method is called
        \Illuminate\Support\Facades\Log::debug('After the method is called');

        return $result;
    }
}
```

### 2. Apply the decorator

[](#2-apply-the-decorator)

You can apply the decorator to a method. The applicable classes and methods must meet the following conditions:

1. The target class must be instantiable from the service container.
2. The target class or method must not be final.
3. The target method must be public.
4. The target method must not be a static method.
5. When you using php 8.3 or earlier, the target class must not be a readonly class.

```
namespace App\Services;

use App\Attributes\LogDecorator;
use Illuminate\Contracts\Foundation\Application;

class MyService
{
    public function __constructor(
        // You can define the constructor but the constructor's arguments must be able to resolve from the service container.
        public readonly Application $app,
    )
    {
    }

    #[LogDecorator]
    public function handle(int $value1, int $value2): int
    {
        return $value1 + $value2;
    }
}
```

You can apply multiple decorators to a method. The applied decorators are executed in the order of the attributes.

```
namespace App\Services;

use App\Attributes\LogDecorator;
use App\Attributes\CacheDecorator;

class MyService
{
    public function __constructor(
        // You can define the constructor but the constructor's arguments must be able to resolve from the service container.
        public readonly Application $app,
    )
    {
    }

    #[LogDecorator]
    #[CacheDecorator] // the CacheDecorator will be executed after the LogDecorator
    public function handle(int $value1, int $value2): int
    {
        return $value1 + $value2;
    }
}
```

### 3. Call the method

[](#3-call-the-method)

You can call the method as usual.

```
namespace App\Http\Controllers;

use App\Services\MyService;

class HomeController
{
    public function index(MyService $service): int
    {
        return $service->handle(1, 2); // When this line is executed, the LogDecorator and CacheDecorator decorators are executed in order before and after the function.
    }
}
```

Default decorators
------------------

[](#default-decorators)

This package already implements some commonly used decorators.

### `DBTransactionDecorator`

[](#dbtransactiondecorator)

This decorator wraps the method in a database transaction. If an exception is thrown, the transaction is rolled back.

```
namespace App\Services;

use Dorayaki4369\LaravelDecorator\Attributes\DBTransactionDecorator;
use App\Models\User;

class UserHandler
{
    #[DBTransactionDecorator]
    public function handle(array $attributes): User
    {
        User::create($attributes);
    }
}
```

### `SimpleCacheDecorator`

[](#simplecachedecorator)

This decorator caches the result of the method.

At execution time, a cache key is created from the class name, method name, and arguments, and the execution results are cached. If the same condition is executed from the second time onwards, the cached results will be returned.

```
namespace App\Services;

use Dorayaki4369\LaravelDecorator\Attributes\SimpleCacheDecorator;
use App\Models\User;

class UserHandler
{
    #[SimpleCacheDecorator]
    public function handle(string $name): User
    {
        return User::where('name', $name)->first();
    }
}
```

### `ValidationDecorator`

[](#validationdecorator)

This decorator validates the arguments of the method by [Validation](https://laravel.com/docs/11.x/validation);

```
namespace App\Services;

use Dorayaki4369\LaravelDecorator\Attributes\ValidationDecorator;
use App\Models\User;

class UserHandler
{
    #[ValidationDecorator([
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'email', 'max:255'],
    ])]
    public function handle(array $attributes): User
    {
        return User::create($attributes);
    }
}
```

How it works in the background
------------------------------

[](#how-it-works-in-the-background)

To provide the easiest and simplest decorator functionality, this package generates an anonymous class that overrides the decorated method when the target class is instantiated from the service container. The reason there are some conditions on the class that can be decorated is because this anonymous class inherits from the target class. Read-only anonymous classes are a PHP 8.3 and later feature, so they will not work in earlier versions of PHP.

For example, the `MyService` class resolving from the service container, the package generates the following anonymous class.

```
$method = (new \ReflectionClass(\Dorayaki4369\LaravelDecorator\Tests\Stubs\Targets\InjectionRequiredClass::class))->getConstructor();
if ($method === null) {
    $args = [];
} else {
    $args = array_map(function ($p) {
        $class = $p->getType()?->getName();

        return $class ? app($class) : null;
    }, $method->getParameters());
}

return new class(...$args) extends \App\Services\MyService {
    public function handle(int $value1, int $value2): int
    {
        return \Dorayaki4369\LaravelDecorator\Facades\Decorator::handle($this, __FUNCTION__, [$value1, $value2]);
    }
}
```

If you want to more specification of decorated class, You can find out in [the Package's test codes](https://github.com/dorayaki4369/decoravel/tree/main/tests).

License
-------

[](#license)

The Laravel Decorator is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

###  Health Score

21

—

LowBetter than 19% of packages

Maintenance25

Infrequent updates — may be unmaintained

Popularity3

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

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

Total

2

Last Release

436d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/69ac3966c5d2a694c4d790098846200a6ee29d9855ad63ea1919951c462cec9b?d=identicon)[dorayaki4369](/maintainers/dorayaki4369)

---

Top Contributors

[![dorayaki4369](https://avatars.githubusercontent.com/u/19973638?v=4)](https://github.com/dorayaki4369 "dorayaki4369 (26 commits)")

---

Tags

decoratorlaravelphp82laraveldecorator

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/dorayaki4369-laravel-decorator/health.svg)

```
[![Health](https://phpackages.com/badges/dorayaki4369-laravel-decorator/health.svg)](https://phpackages.com/packages/dorayaki4369-laravel-decorator)
```

###  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)[wnx/laravel-stats

Get insights about your Laravel Project

1.8k1.8M7](/packages/wnx-laravel-stats)[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[coenjacobs/mozart

Composes all dependencies as a package inside a WordPress plugin

4723.6M20](/packages/coenjacobs-mozart)[laragear/preload

Effortlessly make a Preload script for your Laravel application.

119363.5k](/packages/laragear-preload)[dcblogdev/laravel-module-generator

Generate Laravel Modules from a template.

7710.1k1](/packages/dcblogdev-laravel-module-generator)

PHPackages © 2026

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