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
composer require yceruto/decorator
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
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.
This software is published under the MIT License