先行/拼凑

PHP 的方法重定义(猴子补丁)功能。


README

Patchwork 实现了 PHP 中函数和方法的重定义(猴子补丁)。这包括用户定义的和内部的调用者,可以是函数、类方法或实例方法。此外,许多类似函数的结构,如 exitinclude,也以类似的方式支持。

内部,Patchwork 使用 file:// 上的 流包装器。对于用户定义的函数和方法,它用于在每个这样的调用者开头注入一个简单的拦截器片段。对于其他类型的调用者,应用各种其他策略。

示例:DIY 性能分析器

use function Patchwork\{redefine, relay, getMethod};

$profiling = fopen('profiling.csv', 'w');

redefine('App\*', function(...$args) use ($profiling) {
    $begin = microtime(true);
    relay(); # calls the original definition
    $end = microtime(true);
    fputcsv($profiling, [getMethod(), $end - $begin]);
});

备注

  • 方法重定义 是 Patchwork 行为的内部首选隐喻。
  • restoreAll()restore($handle) 分别结束所有重定义或其中之一的生命周期,其中 $handle = redefine(...)
  • 闭包 $this 会自动重新绑定到被重定义的方法的封装类。
  • 重定义内部 __CLASS__static::class 等的行为不考虑隐喻。应使用 Patchwork 命名空间中的 getClass()getCalledClass()getMethod()getFunction()

与测试相关的使用

Patchwork 可以用来模拟静态方法,但这是一种有争议的做法。

应谨慎应用,即在使用其在其他编程语言的陷阱和诱惑之前熟悉它。例如,在 JavaScript、Ruby、Python 以及一些其他语言中,原生对猴子补丁的支持使其测试相关用途比 PHP 中更普遍。

使用猴子补丁的测试通常不再是 单元 测试,因为它们对实现的细节变得敏感,而不仅仅是接口:例如,在从 time() 切换到 DateTime 后,这样的测试可能不再通过。

尽管如此,它们在某些情况下仍有其位置,即唯一的可行替代方案是没有测试。

其他用例

Patchwork 不建议用于 AOP 和其他类型的生产使用。它对应用程序性能的影响可能会非常大。此外,尽管没有已知或预期的特定 Patchwork 相关的安全风险,但请注意,Patchwork 从未考虑用于生产环境。