我想创建一个通用日志记录 decorator这是类型安全的。
我有很多 repositories (接口(interface)),并且每个都需要一个装饰器来捕获它们可能抛出的异常,将它们传递给 LoggerInterface 的实例。然后重新抛出它们。可以创建一个专用的装饰器并为每个装饰器进行测试,尽管这非常麻烦(尤其是很好地进行测试),而且我宁愿避免这样做。
使用 __call
创建一个更通用的装饰器是第一个想到的方法。然而,这会导致对象实例不实现它所装饰的存储库接口(interface)。这在我的项目中是不行的。有什么方法可以告诉 PHP 它确实实现了这个接口(interface),比如使用一些魔法 reflection ?
我在 stackoverflow 上阅读了“how to implement a decorator in PHP?”和“Best way to implement a decorator pattern for method result caching in PHP”,它们都概述了专用方法和通用方法,但都没有提供以类型安全方式执行通用方法的指示。自从发布这些问题以来已经过去了一段时间,所以也许情况已经改变。我使用的是 PHP 7,如果需要可以使用 PHP 7.1。
PHPUnit_MockObject允许通过 PHPUnit 中熟悉的 getMock
方法调用的相同代码构造一个实现接口(interface)的对象。这可以作为通用装饰器的基础。但是,这需要在生产代码中使用模拟库。此外,这个图书馆 internally uses eval完成它的工作。这使它不符合我的项目的资格。
最佳答案
另一种方法是在运行时动态创建装饰类。遗憾PHP doesn't allow this out of the box .如果runkit扩展名不是一个选项,你可以模拟什么 Doctrine ORM做:有一个执行以下步骤的 DecoratorFactory
:
- 在原始类上使用反射获取所有接口(interface)及其方法,
- 使用 PHP 代码生成一个文件,其中包含一个实现所有接口(interface)的装饰代理类
- 包含生成的代理类
- 用原始类实例化生成的代理类,并返回代理类。
请参阅 http://www.doctrine-project.org/api/orm/2.4/source-class-Doctrine.ORM.Tools.EntityGenerator.html 中的示例
关于php - PHP 中类型安全的通用装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36992540/