c01l / phpdecorator
phpdecorator 库可以用来包装对象和类的函数,添加额外功能。这是与 Python 装饰器可以比较的功能。
1.2.0
2021-12-30 01:00 UTC
Requires
- php: ^8.0
- psr/container: ^2
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: 3.*
README
phpdecorator 库可以用来包装对象和类的函数,添加额外功能。这是与 Python 装饰器可以比较的功能。
如何创建自己的装饰器?
- 声明一个可以放置在库提供的 Decorator 基类扩展方法上的属性。
- 实现返回一个函数的 wrap 函数,该函数将代替原始函数被调用。
- 使用
call_user_func_array
和func_get_args
一起调用原始函数。
#[\Attribute(\Attribute::TARGET_METHOD)] class LoggingDecorator extends \C01l\PhpDecorator\Decorator { public function wrap(callable $func): callable { return function () use ($func) { /** @var Logger $logger */ $logger = $this->getContainer()->get(Logger::class); $logger->log("Started"); $ret = call_user_func_array($func, func_get_args()); $logger->log("Ended"); return $ret; }; } }
使用装饰器
只需在类上注释相关函数。
class SomeClass { #[LoggingDecorator] public function foo(int $bar): int { return $bar; } }
如果对象通过库传递,则只有功能会被替换。
$decoratorManager = new DecoratorManager(); $obj = $decoratorManager->instantiate(SomeClass::class); // only possible for classes with a parameter-less constructor! // OR $obj = new SomeClass(); $obj = $decoratorManager->decorate($obj); // creates a proxy object (do not use the original reference of the object!)
高级用法
将依赖项容器传递给装饰器
您可以向 DecoratorManager
提供一个容器,该容器将传递给每个将被实例化的 Decorator
。
$container = /* use some PSR-11 container */ $decoratorManager = new DecoratorManager(container: $container)
在装饰器中,您可以使用 $this->getContainer()
获取容器。
缓存生成的类
如果您在大量类上使用此库,可能适合使用类缓存。这样类只生成一次,可以由运行时进行优化。
只需提供一个文件夹的路径,您的运行时允许在该文件夹中读取和写入文件。
$decoratorManager = new DecoratorManager(classCachePath: "/path/to/cache/");