在PHP中输入安全的通用装饰器

Jer*_*auw 5 php reflection types decorator

我想创建一个类型安全的通用日志装饰器

我有许多存储库(接口),每个存储库都需要一个装饰器,以捕获它们可能抛出的异常,将其传递给LoggerInterface的实例,然后重新抛出它们。可以创建一个专用的装饰器并为每个装饰器进行测试,尽管这非常麻烦(尤其是很好地进行了测试),但我还是避免了。

使用__call创造一个更通用的装饰是,想到的第一种方法。但是,这将导致对象实例无法实现其装饰的存储库接口。在我的项目中,这是不可行的。有没有办法告诉PHP它确实实现了此接口,例如通过使用一些魔术反射

我已经在stackoverflow上阅读了“ 如何在PHP中实现装饰器? ”和“ 在PHP 中实现用于方法结果缓存的装饰器模式的最佳方法 ”,它们都概述了专用方法和通用方法,尽管均未提供对方法的指示。以类型安全的方式执行通用方法。这些问题发布以来已经过去了一段时间,所以也许情况已经改变了。我正在使用PHP 7,并且可以根据需要使用PHP 7.1。

PHPUnit_MockObject允许通过与getMockPHPUnit中熟悉的方法调用的代码相同的代码构造实现接口的对象。这可以作为通用装饰器的基础。但是,这将需要在生产代码中使用模拟库。此外,该库在内部使用eval完成其工作。这使它不符合我的项目的资格。

Sam*_*tch 0

获得所需内容的唯一真正方法是声明一个基本的 Decorator 类,该类完全实现必要的接口,然后基于该接口进行扩展。例如:

interface FooInterface {
    function doFoo();
    function doMoreFoo();
}

class Foo implements FooInterface {
    public function __construct() {}
    public function doFoo() {}
    public function moreFoo() {}
}

class FooDecoratorBase implements FooInterface {
    protected $foo;
    public function __construct(FooInterface $foo) { $this->foo = $foo; }
    public function doFoo() { $this->foo->doFoo(); }
    public function moreFoo() { $this->foo->moreFoo(); }
}

class ExtraFooDecorator extends FooDecoratorBase {
    public function extraFoo() {}
}
Run Code Online (Sandbox Code Playgroud)

虽然我自己无法引用具体细节,但我尊敬的其他 PHP 开发人员告诉我,在生产代码中使用反射是一个坏主意,因为它们的设计考虑的是测试/调试,而不是性能。