php - PHP 中类型安全的通用装饰器

标签 php reflection types decorator

我想创建一个通用日志记录 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/

相关文章:

php - Wordpress 忽略 URL 中的 Unicode 字符

javascript - Knockout Js函数没有出现在页面上

c# - 通过变量引用属性名称

c# - 如何使用反射来获取显式实现接口(interface)的属性?

Scala 无法证明类型相等

objective-c - 获取可为空的 bool 的 Objective-C 方法是什么?

php - 如何使用php比较mysql查询中的两个日期时间

php - GoDaddy 域注册 API 上电话号码字段的有效格式是什么

reflection - 路径相关类型与 "underlying types",检查哪些类型?

arrays - 为什么 Swift 有时会将混合类型数组视为单一类型数组?