yceruto/decorator

PHP function decorators

v1.1.0 2024-11-04 04:16 UTC

This package is auto-updated.

Last update: 2024-11-14 19:22:42 UTC


README

GitHub Actions Workflow Status Version PHP GitHub License

Note

Inspired by Python's decorator

This library implements the Decorator Pattern around any PHP callable, allowing you to:

  • Execute logic before or after a callable is executed
  • Skip the execution of a callable by returning earlier
  • Modify the result of a callable

Installation

composer require yceruto/decorator

Usage

use Yceruto\Decorator\Attribute\DecoratorAttribute;
use Yceruto\Decorator\CallableDecorator;
use Yceruto\Decorator\DecoratorInterface;

#[\Attribute(\Attribute::TARGET_METHOD)]
class Debug extends DecoratorAttribute
{
}

class DebugDecorator implements DecoratorInterface
{
    public function decorate(\Closure $func): \Closure
    {
        return function (mixed ...$args) use ($func): mixed
        {
            echo "Do something before\n";

            $result = $func(...$args);

            echo "Do something after\n";

            return $result;
        };
    }
}

class Greeting
{
    #[Debug]
    public function sayHello(string $name): void
    {
        echo "Hello $name!\n";
    }
}

$greeting = new Greeting();
$decorator = new CallableDecorator();
$decorator->call($greeting->sayHello(...), 'John');

Output:

Do something before
Hello John!
Do something after

Frameworks Integration

Decorators

Compound

To create a reusable set of decorators, extend the Compound class:

use Yceruto\Decorator\Attribute\Compound;

#[\Attribute(\Attribute::TARGET_METHOD)]
class Greetings extends Compound
{
    /**
     * @return array<DecoratorAttribute>
     */
    public function getDecorators(array $options): array
    {
        return [
            new Hello(),
            new Welcome(),
            // ...
        ];
    }
}

class Greeting
{
    #[Greetings]
    public function __invoke(): void
    {
        // ...
    }
}

When the Greeting::__invoke() method is decorated, the Hello and Welcome decorator attributes will be applied in the specified order. This is equivalent to directly defining #[Hello] and #[Welcome] on this method.

License

This software is published under the MIT License