coapsyfactor / decorator
PHP 装饰器,在执行前动态添加方法和属性,并正确设置作用域和 $this。
dev-master
2019-01-24 01:13 UTC
Requires
- php: >=7.2
This package is auto-updated.
Last update: 2024-09-24 14:04:03 UTC
README
PHP 装饰器
在执行时,动态向对象添加方法,并使用提供的正确上下文和作用域。
使用方法
可以被装饰的类 必须 使用 Decoratable
特性。
Decoratable
特性依赖于魔法方法 __call
和 __get
,因此直接使用它们会破坏 Decorator
的功能。
要设置自定义的 __call
和 __get
,请使用 __onCall
和 __onGet
。
基本装饰
向某个对象添加方法。
<?php class User { use Decoratable; private $firstName; private $lastName; public function __construct(string $firstName, string $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; } } $user = Decorator::decorate(new User('Brown', 'Fox'), 'getFullName', function (): string { return "{$this->firstName} {$this->lastName}"; }); echo $user->getFullName(); // Brown Fox
严格对象类型装饰
严格对象类型装饰将确保被更改的对象是提供名称的实例或子类。
<?php class User { use Decoratable; private $firstName; private $lastName; public function __construct(string $firstName, string $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; } private function getFirstName(): string { return $this->firstName; } public function getLastName(): string { return $this->lastName; } } $user = Decorator::decorate(new User('Brown', 'Fox'), 'getFullName', function (): string { return "{$this->getFirstName()} {$this->getLastName()}"; }, User::class); echo $user->getFullName(); // Brown Fox
定义方法装饰
在附加装饰器方法时,脚本将检查原始方法是否存在。原始方法 必须 与装饰器方法同名,且不带前缀。
原始方法将被作为装饰器方法的第一参数传递,它将包含附加的上下文和作用域。执行很简单,只需调用例如 $original()
,其中 $original
是装饰器方法的第一参数。
默认前缀:decorated
<?php class User { use Decoratable; private $firstName; private $lastName; public function __construct(string $firstName, string $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; } public function getFullName(): string { return "{$this->firstName} {$this->lastName}"; } } $user = Decorator::decorate( new User('Brown', 'Fox'), 'decoratedGetFullName', function (callable $original, string $title): string { return "{$title}. {$original()}"; } ); echo $user->decoratedGetFullName('Mr'); // Mr. Brown Fox
使用类装饰
对象也可以用某个类进行装饰,提供的装饰器类中找到的所有静态方法都将应用于目标对象。
使用正确的方法访问数据,脚本提供在类定义外部访问私有属性的方式。
<?php class EntityHydrator { public function hydrate(callable $context, array $data): void { // $context callable provide us with instance of target as parameter // in this case called $postEntity, and script has access to its private properties // $this is instance of target object that is being decorated $context(function () use ($data) { // id, firstName, lastName are private properties $this->id = $data['id'] ?? null; $this->firstName = $data['firstName'] ?? null; $this->lastName = $data['lastName'] ?? null; }, User::class); } } $user = Decorator::decorateWithClass(new User(), EntityHydrator::class); $user->hydrate(['firstName' => 'Criss', 'lastName' => 'Popo']); echo $user->getFirstName(); // Criss
装饰属性
向对象添加动态属性
<?php class User { use Decoratable; private $firstName; private $lastName; public function __construct(string $firstName, string $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; } public function getFullName(): string { return "{$this->firstName} {$this->lastName}"; } } $user = Decorator::decorate(new User('Brown', 'Fox'), 'title', 'Dr'); echo $user->title; // Dr