okapi/code-transformer
Composer 安装命令:
composer require okapi/code-transformer
包简介
PHP Code Transformer is a PHP library that allows you to modify and transform the source code of a loaded PHP class.
关键字:
README 文档
README
PHP Code Transformer
PHP Code Transformer is a PHP library that allows you to modify and transform the source code of a loaded PHP class.
Installation
composer require okapi/code-transformer
Usage
📖 List of contents
- Create a Kernel
- Create a Transformer
- Target Class
- Initialize the Kernel
- Target Class (transformed)
- Result
- Limitations
- How it works
- Testing
Create a Kernel
<?php use Okapi\CodeTransformer\CodeTransformerKernel; // Extend from the "CodeTransformerKernel" class class Kernel extends CodeTransformerKernel { // Define a list of transformer classes protected array $transformers = [ StringTransformer::class, UnPrivateTransformer::class, ]; // Define the settings of the kernel from the "protected" properties // The directory where the transformed source code will be stored protected ?string $cacheDir = __DIR__ . '/var/cache'; // The cache file mode protected ?int $cacheFileMode = 0777; }
Create a Transformer
// String Transformer <?php use Okapi\CodeTransformer\Transformer; use Okapi\CodeTransformer\Transformer\Code; // Extend from the "Transformer" class class StringTransformer extends Transformer { // Define the target class(es) public function getTargetClass(): string|array { // You can specify a single class or an array of classes // You can also use wildcards, see https://github.com/okapi-web/php-wildcards return MyTargetClass::class; } // The "transform" method will be called when the target class is loaded // Here you can modify the source code of the target class(es) public function transform(Code $code): void { // I recommend using the Microsoft\PhpParser library to parse the source // code. It's already included in the dependencies of this package and // the "$code->getSourceFileNode()" property contains the parsed source code. // But you can also use any other library or manually parse the source // code with basic PHP string functions and "$code->getOriginalSource()" $sourceFileNode = $code->getSourceFileNode(); // Iterate over all nodes foreach ($sourceFileNode->getDescendantNodes() as $node) { // Find 'Hello World!' string if ($node instanceof StringLiteral && $node->getStringContentsText() === 'Hello World!' ) { // Replace it with 'Hello from Code Transformer!' // Edit method accepts a Token or Node class $code->edit( $node->children, "'Hello from Code Transformer!'", ); // You can also manually edit the source code $code->editAt( $node->getStartPosition() + 1, $node->getWidth() - 2, "Hello from Code Transformer!", ); // Append a new line of code $code->append('$iAmAppended = true;'); } } } }
// UnPrivate Transformer <?php namespace Okapi\CodeTransformer\Tests\Stubs\Transformer; use Microsoft\PhpParser\TokenKind; use Okapi\CodeTransformer\Transformer; use Okapi\CodeTransformer\Transformer\Code; // Replace all "private" keywords with "public" class UnPrivateTransformer extends Transformer { public function getTargetClass(): string|array { return MyTargetClass::class; } public function transform(Code $code): void { $sourceFileNode = $code->getSourceFileNode(); // Iterate over all tokens foreach ($sourceFileNode->getDescendantTokens() as $token) { // Find "private" keyword if ($token->kind === TokenKind::PrivateKeyword) { // Replace it with "public" $code->edit($token, 'public'); } } } }
Target Class
<?php class MyTargetClass { private string $myPrivateProperty = "You can't get me!"; private function myPrivateMethod(): void { echo 'Hello World!'; } }
Initialize the Kernel
// Initialize the kernel early in the application lifecycle // Preferably after the autoloader is registered <?php use MyKernel; require_once __DIR__ . '/vendor/autoload.php'; // Initialize the Code Transformer Kernel $kernel = MyKernel::init();
Target Class (transformed)
<?php class MyTargetClass { public string $myPrivateProperty = "You can't get me!"; public function myPrivateMethod(): void { echo 'Hello from Code Transformer!'; } } $iAmAppended = true;
Result
<?php // Just use your classes as usual $myTargetClass = new MyTargetClass(); $myTargetClass->myPrivateProperty; // You can't get me! $myTargetClass->myPrivateMethod(); // Hello from Code Transformer!
Limitations
- Normally xdebug will point to the original source code, not the transformed one. The problem with this is if you add or remove a line of code, xdebug will point to the wrong line, so try to keep the number of lines the same as the original source code.
How it works
-
The
CodeTransformerKernelregisters multiple services-
The
TransformerManagerservice stores the list of transformers and their configuration -
The
CacheStateManagerservice manages the cache state -
The
StreamFilterservice registers a PHP Stream Filter which allows to modify the source code before it is loaded by PHP -
The
AutoloadInterceptorservice overloads the Composer autoloader, which handles the loading of classes
-
General workflow when a class is loaded
-
The
AutoloadInterceptorservice intercepts the loading of a class -
The
TransformerMatchermatches the class name with the list of transformer target classes -
If the class is matched, query the cache state to see if the transformed source code is already cached
-
Check if the cache is valid:
- Modification time of the caching process is less than the modification time of the source file or the transformers
- Check if the cache file, the source file and the transformers exist
- Check if the number of transformers is the same as the number of transformers in the cache
-
If the cache is valid, load the transformed source code from the cache
-
If not, return a stream filter path to the
AutoloadInterceptorservice
-
-
The
StreamFiltermodifies the source code by applying the matching transformers- If the modified source code is different from the original source code, cache the transformed source code
- If not, cache it anyway, but without a cached source file path, so that the transformation process is not repeated
Testing
- Run
composer run-script test
or - Run
composer run-script test-coverage
Show your support
Give a ⭐ if this project helped you!
🙏 Thanks
- Big thanks to lisachenko for their pioneering work on the Go! Aspect-Oriented Framework for PHP. This project drew inspiration from their innovative approach and served as a foundation for this project.
📝 License
Copyright © 2023 Valentin Wotschel.
This project is MIT licensed.
okapi/code-transformer 适用场景与选型建议
okapi/code-transformer 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 14.25k 次下载、GitHub Stars 达 8, 最近一次更新时间为 2023 年 02 月 23 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「code」 「transformer」 「php-code」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 okapi/code-transformer 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 okapi/code-transformer 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 okapi/code-transformer 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Memio's PrettyPrinter, used to generate PHP code from given Model
Serializer transformers outputting valid API responses in JSON, JSON API and HAL+JSON API formats.
Symfony 2 & 3 JSON API Transformer Package
A simple library that allows transform any kind of data to native php data or whatever
HAL+JSON & HAL+XML API transformer outputting valid API responses.
Optimus Bard takes the content from a Statamic Bard field and transforms it into a string when updating your search index
统计信息
- 总下载量: 14.25k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 9
- 点击次数: 24
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2023-02-23