不需要任何 PECL 扩展的纯 PHP 中的 AOP(Go!)- 怎么样?

AOP in plain PHP that doesn't require any PECL-extentions (Go!) - How?

有一个框架叫做Go! Aspect-Oriented Framework for PHP

它是用普通的 PHP 制作的,不需要任何 PECL 扩展和 DI 容器即可工作。

更重要的是可以与任何现有的 PHP 框架和库集成(有或没有额外配置)。

并且没有切入点的运行时检查,没有运行时注释解析,没有 evals 和 __call 方法,没有慢速代理和 call_user_func_array()。快速引导过程(2-20 毫秒)和建议调用。

所以我印象非常深刻,但我想知道的是,它实际上是如何工作的?

我在这里列出的这些要点...

我查看了 github 和官方网站以及其他一些文章,但找不到任何关于它如何工作的具体信息(一般和具体)。

我非常想知道它是如何工作的?它是如何实施的?

这个框架使用了很多隐藏的技巧来完成它的工作,但是如果我们从鸟瞰的角度来看,那么过程可以描述如下:

  1. 当前版本的 AOP 引擎旨在与作曲家紧密合作,因此它使用自己的代理包装作曲家加载器。从那时起,AOP 知道应该加载哪个 class 以及在哪里寻找它的源代码。
  2. 当某些 class Foo 从文件 Foo.php 加载时,AOP 将其包装到特殊的过滤流中,如下所示:include 'php://filter/read=go.source.transforming.loader/resource=Foo.php';。您可以在 'php://stream' manual
  3. 阅读有关此流过滤器的更多信息
  4. 此时,class 还没有加载到 PHP 内存中,但是框架已经知道它的内容并且可以对源代码进行分析甚至修改。
  5. 源代码然后标记化,通过 nikic/PHP-Parser library and then static reflection of this code is generated (still without loading this file into PHP's memory) via goaop/parser-reflection
  6. 解析为 AST
  7. 引擎从方面检查所有注册的切入点并执行原始 class Foo 的转换:它被重命名为 Foo__AopProxied 和新文件 class Foo extends Foo__AopProxied在缓存中生成。
  8. 引擎然后指示自动加载器从那个新文件而不是原始文件加载这个 class,所以你有你原来的 class 名称,但有来自建议的附加逻辑。看起来像是在运行时自动生成装饰器。

当然,这只是少量信息,因为在纯 PHP 中实现 AOP 是一项非常艰巨的任务,在发现可行的解决方案之前我尝试了很多次,因此深入研究源代码会很有趣发现隐藏宝石的代码:) 我的 PhpSerbia talk about cross-cutting concerns in PHP 中也提供了一些信息,您可以观看它以更好地理解(对不起我的英语)。

此外,我们目前正在为框架编写文档,所以如果您想改进它,请向我们发送 PR 至 official documentation

您还应该使用 PhpStorm 插件,它为在 PHP 个项目中使用 AOP 的开发人员提供了许多功能。