macfja / composer-class-rewrite
Composer 插件用于处理类重写
v0.1.0
2016-01-26 20:44 UTC
Requires
- composer-plugin-api: ^1.0
- nikic/php-parser: ^2.0
Requires (Dev)
- composer/composer: ~1.0@dev
- phpunit/phpunit: ^5.1
- squizlabs/php_codesniffer: ^2.5
This package is auto-updated.
Last update: 2024-09-17 00:51:27 UTC
README
什么是 Composer Class-Rewrite
Composer Class-Rewrite 是一个 Composer 插件,允许您重写项目中几乎所有[1][1] 类。
原理[2][2]
思路是扫描项目的每个类以查找声明为重写的类。然后我们对父类(重写的类)和重写类(重写类的副本)进行一些修改,并将其添加到 Composer 的自动加载(在 PSR-0 和 PSR-4 类之前)。因此,当类请求重写的类时,Composer 将返回我们的修改后的重写类。
安装
使用 Composer
$ composer require macfja/composer-class-rewrite
使用方法
# File: example/A.php namespace Example; class A { public function who() { return 'A'; } }
# File: example/B.php namespace Example; class B extends A { public function who() { return parent::who() . '-B'; } }
# File: example/C.php namespace Example; class C extends A implements \MacFJA\ClassRewrite\Rewriter { public function who() { return parent::who() . '-C'; } }
$ composer dump-autoload # Mandatory after any changes in Example\A or in Example\C
$b = new B(); echo $b->who(); // Output: "A-C-B"
限制
- 仅适用于 PSR-0 和 PSR-4 命名空间。
- 仅当 Composer 是第一个自动加载器时才有效。
- 仅对非开发依赖有效。
- 仅对类有效(不是对 trait 或接口)。
- 重写类 必须 与重写的类具有相同的命名空间。
- 您必须为每个重写/重写更改重建自动加载。
- 有一些副作用 (见以下示例)
- 类上下文已更改(魔术常量)。
- 如果实例化重写类,则会多次调用。
副作用
多次调用
# File: example/A.php namespace Example; class A { public function who() { return 'A'; } }
# File: example/B.php namespace Example; class B extends A implements \MacFJA\ClassRewrite\Rewriter { public function who() { return parent::who() . '-B'; } }
# File: example/C.php namespace Example; class C extends B { public function who() { return parent::who() . '-C'; } }
# File: test.php require 'vendor/autoload.php'; $class = new A(); echo $class->who(); //output A-B $class2 = new B(); echo $class2->who(); // output A-B-B // -> the output is (A='A-B', parent of B) + '-B' (from B) $class3 = new C(); echo $class3->who(); // output A-B-B-C // -> the output is (A='A-B', parent of B) + '-B' (from B, parent of C) + '-C' (from C)
魔术常量
# File: example/A.php <?php namespace Example; class A { public function dir() { return __DIR__; // "~/example" } public function thisClass() { return __CLASS__; // "Example\A" } }
# File: example/B.php <?php namespace Example; class B extends A implements \MacFJA\ClassRewrite\Rewriter { public function dir() { return __DIR__; // "~/example" } }
# File: test.php require 'vendor/autoload.php'; $class = new A(); echo $class->dir(); //output "~/vendor/_rewrite" echo $class->thisClass(); //output "Example\Cc09c111b433d2b65b9b01c999ae6480874b076a8" echo get_class($class); //output "Example\A"
探索的想法
- 在 Composer 自动加载期间注入我的代码。 问题: Composer 不提供自动加载器事件。
- 更改 Composer 自动加载器代码以添加我的逻辑。 问题: 更改核心代码。因此,如果 Composer 更改它,它也必须更改我的代码。难以维护。
- 在 Composer 自动加载器之前添加一个自定义自动加载器。 问题: 失去所有 Composer 自动加载的力量。
内部原理
此插件使用
composer-plugin-api
(明显)nikic/php-parser
:用于解析 PHP 类,并重写它们
如何工作
在生成 Composer 自动加载器之前,插件解析每个 PSR-0 和 PSR-4 命名空间。它搜索实现接口 \MacFJA\ClassRewrite\Rewriter
的类,将重写类和重写的类存储在内存中。当插件解析完所有类后,它重新构建每个重写类和重写类,将重写类名重命名为一个难以猜测的类名(实际上是源文件的 sha1),并将重写类名重命名为原始重写类名。最后,它将重写目标目录添加到 Composer 类映射自动加载。
然后它让 Composer 做它的工作。
它之所以有效,是因为 Composer 从类映射自动加载中开始搜索类。
许可
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。