macfja/composer-class-rewrite

Composer 插件用于处理类重写

安装次数: 39

依赖者: 0

建议者: 0

安全: 0

星标: 2

关注者: 3

分支: 0

开放问题: 0

类型:composer-plugin

v0.1.0 2016-01-26 20:44 UTC

This package is auto-updated.

Last update: 2024-09-17 00:51:27 UTC


README

Latest Version Software License Total Downloads

什么是 Composer Class-Rewrite

Composer Class-Rewrite 是一个 Composer 插件,允许您重写项目中几乎所有[1][1] 类。

原理[2][2]

思路是扫描项目的每个类以查找声明为重写的类。然后我们对父类(重写的类)和重写类(重写类的副本)进行一些修改,并将其添加到 Composer 的自动加载(在 PSR-0PSR-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-0PSR-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"

探索的想法

  1. 在 Composer 自动加载期间注入我的代码。 问题: Composer 不提供自动加载器事件。
  2. 更改 Composer 自动加载器代码以添加我的逻辑。 问题: 更改核心代码。因此,如果 Composer 更改它,它也必须更改我的代码。难以维护。
  3. 在 Composer 自动加载器之前添加一个自定义自动加载器。 问题: 失去所有 Composer 自动加载的力量。

内部原理

此插件使用

  • composer-plugin-api(明显)
  • nikic/php-parser:用于解析 PHP 类,并重写它们

如何工作

在生成 Composer 自动加载器之前,插件解析每个 PSR-0PSR-4 命名空间。它搜索实现接口 \MacFJA\ClassRewrite\Rewriter 的类,将重写类和重写的类存储在内存中。当插件解析完所有类后,它重新构建每个重写类和重写类,将重写类名重命名为一个难以猜测的类名(实际上是源文件的 sha1),并将重写类名重命名为原始重写类名。最后,它将重写目标目录添加到 Composer 类映射自动加载。
然后它让 Composer 做它的工作。

它之所以有效,是因为 Composer 从类映射自动加载中开始搜索类。

许可

MIT 许可证(MIT)。有关更多信息,请参阅 许可文件