asmblah / php-code-shift
v0.1.16
2024-09-11 06:42 UTC
Requires
- php: >=8.1
- nikic/php-parser: ^4.18 || ^5.0
- nytris/nytris: ^0.1
- psr/log: ^1|^2|^3
- symfony/filesystem: ^5.4
Requires (Dev)
- mockery/mockery: 1.6.11
- phpstan/phpstan: ^1.10
- phpstan/phpstan-mockery: ^1.1
- phpunit/phpunit: ^10.2
README
允许在预编译时或在运行时动态修改PHP代码。
为什么?
例如,为了在测试期间模拟内置函数。
使用方法
使用Composer安装此包
$ composer require asmblah/php-code-shift
挂钩内置函数
runner.php
<?php use Asmblah\PhpCodeShift\CodeShift; use Asmblah\PhpCodeShift\Shifter\Filter\FileFilter; use Asmblah\PhpCodeShift\Shifter\Shift\Shift\FunctionHook\FunctionHookShiftSpec; require_once __DIR__ . '/vendor/autoload.php'; $codeShift = new CodeShift(); $codeShift->shift( new FunctionHookShiftSpec( 'substr', function (callable $originalSubstr) { return function (string $string, int $offset, ?int $length = null) use ($originalSubstr) { return '[substr<' . $originalSubstr($string, $offset, $length) . '>]'; }; } ), new FileFilter(__DIR__ . '/substr_test.php') ); include __DIR__ . '/substr_test.php';
substr_test.php
<?php // NB: substr(...) will be hooked by the shift defined inside runner.php. $myResult = substr('my string', 1, 4) . ' and ' . substr('your string', 1, 2); print $myResult;
输出将是
[substr<y st>] and [substr<ou>]
挂钩类
类的引用可以被替换成对其他类的引用。这仅适用于静态引用的类,即使用裸词进行引用的地方,例如 new MyClass
。
不支持动态/变量引用,例如 new $myClassName
,因为它们只能在运行时解析。
任何匹配的类型都不会被替换 - 替换的类必须扩展原始类或接口,以便通过类型检查。
runner.php
<?php use Asmblah\PhpCodeShift\CodeShift; use Asmblah\PhpCodeShift\Shifter\Filter\FileFilter; use Asmblah\PhpCodeShift\Shifter\Shift\Shift\ClassHook\ClassHookShiftSpec; require_once __DIR__ . '/vendor/autoload.php'; $codeShift = new CodeShift(); $codeShift->shift( new ClassHookShiftSpec( 'MyClass', 'MyReplacementClass' ), new FileFilter(__DIR__ . '/class_test.php') ); include __DIR__ . '/class_test.php';
class_test.php
<?php class MyClass { public function getIt(): string { return 'my original string'; } } class MyReplacementClass { public function getIt(): string { return 'my replacement string'; } } // NB: References to MyClass will be hooked by the shift defined inside runner.php. $myObject = new MyClass; print $myObject->getIt();
输出将是
my replacement string
静态方法调用(MyClass::myStaticMethod()
)和类常量获取(MyClass:MY_CONST
)也受支持。
限制
目前功能极其有限,您可能最好使用下面列出的替代方案之一。
- 尚不支持
eval(...)
。 FunctionHookShiftType
尚不支持变量函数调用。FunctionHookShiftType
尚不支持call_user_func(...)
和类似函数,也不支持接受可能引用函数的可调用参数的任何其他函数。
另请参阅
- dg/bypass-finals,该库与这个库使用相同的技巧。
- PHP预处理器
- Patchwork