xuwenxiong / phalcon4to5-rector
Rector upgrade rules for Phalcon Framework 4 to 5
Package info
github.com/xuwenxiong/phalcon4to5-rector
Type:rector-extension
pkg:composer/xuwenxiong/phalcon4to5-rector
Deleted by maintainer on 2026-11-13 02:00:15 UTC
Requires
- php: ^8.1
- ext-xml: *
Requires (Dev)
- phalcon/ide-stubs: ^5.0
- phpunit/phpunit: ^11.5
- rector/rector: ^2.1
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
基于 Rector 的 Phalcon Framework 4 → 5 自动升级规则集。
作者:xuwenxiong
Rector 官方目前没有 Phalcon 规则包,本项目按照 rectorphp/rector-symfony 的扩展包结构,实现 Phalcon 5 官方升级指南 中的破坏性变更,让应用代码升级尽可能自动化。
⚠️ 开发测试阶段:本项目目前处于开发测试阶段,规则覆盖度和行为仍在迭代验证中,暂不能用于生产。使用前请务必先
--dry-run预览全部变更并人工审查,再应用到代码。
功能
- 一键重命名迁移到新命名空间的类(
Phalcon\Loader→Phalcon\Autoload\Loader等) - 方法重命名(
Loader::registerDirs()→setDirectories()、Asset::getLocal()→isLocal()等) - 构造函数注入修复(
Cache\AdapterFactory自动注入Storage\SerializerFactory)
安装
composer require --dev xuwenxiong/phalcon4to5-rector
使用
方式一:自动加载(推荐)
本包已通过 extra.rector.includes 注册规则集。在项目中安装 rector/extension-installer 插件后,composer install 时会自动发现并加载 phalcon50 规则集,无需任何手动配置:
composer require --dev rector/extension-installer
原理:插件按
type: rector-extension发现本包,将extra.rector.includes聚合写入生成的GeneratedConfig;Rector 运行时通过Bootstrap\ExtensionConfigResolver读取并加载这些配置文件。
方式二:手动加载
不想用插件的话,在项目根目录 rector.php 中手动引用规则集路径:
<?php declare(strict_types=1); use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__ . '/src', ]); $rectorConfig->sets([ __DIR__ . '/vendor/xuwenxiong/phalcon4to5-rector/config/sets/phalcon50.php', ]); };
运行
先预览变更,确认后再应用:
vendor/bin/rector process src --dry-run # 预览 diff vendor/bin/rector process src # 应用变更
支持的规则
类与命名空间重命名(RenameClassRector)
| Phalcon 4 | Phalcon 5 |
|---|---|
Phalcon\Loader |
Phalcon\Autoload\Loader |
Phalcon\Cache |
Phalcon\Cache\Cache |
Phalcon\Collection |
Phalcon\Support\Collection |
Phalcon\Config |
Phalcon\Config\Config |
Phalcon\Container |
Phalcon\Container\Container |
Phalcon\Crypt |
Phalcon\Encryption\Crypt |
Phalcon\Debug |
Phalcon\Support\Debug |
Phalcon\Di |
Phalcon\Di\Di |
Phalcon\Escaper |
Phalcon\Html\Escaper |
Phalcon\Filter |
Phalcon\Filter\Filter |
Phalcon\Logger |
Phalcon\Logger\Logger |
Phalcon\Registry |
Phalcon\Support\Registry |
Phalcon\Security |
Phalcon\Encryption\Security |
Phalcon\Url |
Phalcon\Mvc\Url |
Phalcon\Validation |
Phalcon\Filter\Validation |
Phalcon\Version |
Phalcon\Support\Version |
Phalcon\Acl\ComponentAware |
Phalcon\Acl\ComponentAwareInterface |
Phalcon\Acl\RoleAware |
Phalcon\Acl\RoleAwareInterface |
Phalcon\Exception |
\Exception(v5 已移除根级异常,cphalcon#15800) |
方法重命名(RenameMethodRector)
| 类 | 旧方法 | 新方法 |
|---|---|---|
Phalcon\Autoload\Loader |
registerDirs() |
setDirectories() |
Phalcon\Autoload\Loader |
registerNamespaces() |
setNamespaces() |
Phalcon\Autoload\Loader |
registerFiles() |
setFiles() |
Phalcon\Autoload\Loader |
registerClasses() |
setClasses() |
Phalcon\Autoload\Loader |
registerExtensions() |
setExtensions() |
Phalcon\Autoload\Loader |
getDirs() |
getDirectories() |
Phalcon\Assets\Asset |
getLocal() |
isLocal() |
Phalcon\Assets\Asset |
setLocal() |
setIsLocal() |
Phalcon\Assets\Collection |
getLocal() |
isLocal() |
Phalcon\Assets\Collection |
setLocal() |
setIsLocal() |
Phalcon\Assets\Collection |
getTargetLocal() |
getTargetIsLocal() |
Phalcon\Assets\Collection |
setTargetLocal() |
setTargetIsLocal() |
自定义规则
CacheAdapterFactoryConstructorInjectionRector— 补齐Phalcon\Cache\AdapterFactory构造函数中 v5 必传的Phalcon\Storage\SerializerFactory参数(v4 中可选,默认null):
// v4(两种写法在 v5 都会报 TypeError) $factory = new AdapterFactory(); $factory = new AdapterFactory(null); // 迁移后 $factory = new AdapterFactory(new SerializerFactory());
AssetsManagerTagFactoryInjectionRector— 为Phalcon\Assets\Manager构造函数注入 v5 必传的Phalcon\Html\TagFactory(含其必需的Escaper依赖链),v4 的options数组自动后移:
// v4 $assets = new Manager(); $assets = new Manager(['sourceBasePath' => '/src']); // 迁移后 $assets = new Manager(new TagFactory(new Escaper())); $assets = new Manager(new TagFactory(new Escaper()), ['sourceBasePath' => '/src']);
TextAndHelperToSupportHelperRector— 将已移除的Phalcon\Text/Phalcon\Helper\*静态调用迁移为 v5 官方推荐的Phalcon\Support\HelperFactory方法调用(工厂__call按方法名代理各 helper,方法名 = helper 类名的 lcfirst),共映射 51 个方法 + 6 个RANDOM_*常量:
// v4 $camel = Text::camelize('foo_bar'); $endsWith = Helper\Str::endsWith('hello world', 'world'); $first = Helper\Arr::first($items); $type = Text::RANDOM_ALPHA; // 迁移后(use 导入自动补齐) use Phalcon\Support\HelperFactory; $camel = $helperFactory->camelize('foo_bar'); $endsWith = $helperFactory->endsWith('hello world', 'world'); $first = $helperFactory->first($items); $type = \Phalcon\Support\Helper\Str\Random::RANDOM_ALPHA;
注:v4
Helper\Number::between()→ v5 工厂方法isBetween()(方法名大小写不敏感匹配);Phalcon\Helper\File在 v4 中不存在,不做迁移。未映射的调用(如动态方法名$class::$method())原样跳过。RANDOM_*常量无工厂代理,仍指向Helper\Str\Random类常量。
DeduplicateHelperFactoryRector— 同一方法体内出现 ≥ 2 次内联new HelperFactory()时,自动提取为局部变量复用(单次调用保持内联);方法内已存在同名变量或调用位于嵌套普通function内时整体跳过:
// 提取前 $camel = (new HelperFactory())->camelize($a); $upper = (new HelperFactory())->upper($b); // 提取后 $helperFactory = new HelperFactory(); $camel = $helperFactory->camelize($a); $upper = $helperFactory->upper($b);
💡 生产环境建议改用 DI 注册服务:
HelperFactory是无状态的,在 Phalcon 5 的 DI 容器中注册为单例服务并注入到需要的类,可全应用复用一个实例,避免逐方法提取变量:$di->setShared('helperFactory', HelperFactory::class); // 类中通过构造器注入 / $di->get('helperFactory') 使用规则输出是机械改写的安全下限,DI 化属于应用架构决策,由你自行决定。
TagToTagFactoryRector— 将已移除的Phalcon\Tag的确定性子集迁移为$tagFactory->...调用($tagFactory为作用域内的Phalcon\Html\TagFactory变量,是本包的显式约定):
// v4 $name = Tag::textField(['name', 'value' => 'x', 'class' => 'c']); $slug = Tag::friendlyText('Some Title', '-'); $doctype = Tag::HTML5; // 迁移后 $name = $tagFactory->inputText('name', 'x', ['class' => 'c']); $slug = $tagFactory->friendlyTitle('Some Title', '-'); $doctype = \Phalcon\Html\Helper\Doctype::HTML5;
覆盖:22 个输入字段方法(textField/emailField/checkField/submitButton 等,字符串形态与字面量数组形态自动拆解为 (name, value, attributes))、friendlyText() → friendlyTitle()(签名一致)、11 个 HTML*/XHTML* doctype 常量 → Doctype:: 常量。
RemovedClassUsageHintRector— 对仍引用 v5 中已移除且无自动迁移方案类(Phalcon\Kernel等)的语句 /use导入添加 TODO 提示注释,让手工迁移点在 rector diff 中可见:
// v4 use Phalcon\Kernel; \Phalcon\Kernel::preFlightChecks($container, $eventsManager); // 迁移后(加提示,不自动改写) // TODO Phalcon v5: "Phalcon\Kernel" was removed in Phalcon v5 without a replacement - inline the bootstrap/pre-flight checks it performed manually use Phalcon\Kernel; // TODO Phalcon v5: "Phalcon\Kernel" was removed in Phalcon v5 without a replacement - inline the bootstrap/pre-flight checks it performed manually \Phalcon\Kernel::preFlightChecks($container, $eventsManager);
注:提示清单刻意保持精简——有迁移方案的类都由对应规则处理(重命名、TagFactory、Support\Helper 等),避免与其他规则产生冲突注释。
Phalcon\Exception属于"有迁移方案"(替换为\Exception),由RenameClassRector处理,不在此列。
RenameUseImportsRector— 改写类重命名后残留的use导入语句(Rector 2.x 的RenameClassRector只重命名内联引用,旧导入会留在文件顶部)。与RenameClassRector共享同一份映射表(PhalconClassRenames::MAP),纯配置驱动、不依赖类反射,别名导入的别名原样保留:
// 迁移前 use Phalcon\Loader; use Phalcon\Crypt as PhalconCrypt; // 迁移后 use Phalcon\Autoload\Loader; use Phalcon\Encryption\Crypt as PhalconCrypt;
明确不迁移(参数语义非确定或依赖 DI/全局状态,机械替换会产出错代码,需手动改写):
linkTo()、image()、stylesheetLink()、javascriptInclude()、select()/selectStatic()、form()/endForm()、tagHtml()/tagHtmlClose()、renderAttributes()- 状态方法:
setTitle()/getTitle()系列、setDefault()/getValue()系列、setDocType()/getDocType() - DI 访问器:
setDI()/getDI()/getEscaper()/getUrlService()
已知限制
Phalcon\Tag仅迁移确定性子集:输入字段方法、friendlyText和 doctype 常量已自动迁移;linkTo、image、select、form等参数语义非确定的方法需手动改写(见上方TagToTagFactoryRector的说明)。Phalcon\Text/Phalcon\Helper静态调用已全量迁移,Phalcon\Exception已自动重命名,Phalcon\Kernel已自动添加 TODO 提示。- 反射依赖:方法重命名规则依赖
phalcon/ide-stubs提供的类定义来解析类型,无法解析的类型会被跳过。use导入重命名(RenameUseImportsRector)为纯配置驱动,不受此限制。 - 规则集开启了
importNames():迁移引入的 FQCN 会自动补use导入并缩写为短名(如new \Phalcon\Autoload\Loader()→use Phalcon\Autoload\Loader;+new Loader())。这也会影响用户代码中原本的 FQCN 写法(统一补导入),如不需要可在自己的rector.php中覆盖。
开发
环境要求
- PHP ^8.1
- Composer
目录结构
├── config/sets/
│ └── phalcon50.php # 规则集入口(RenameClass / RenameMethod 配置 + 自定义规则)
├── rules/
│ └── Phalcon5/Rector/New_/
│ └── CacheAdapterFactoryConstructorInjectionRector.php
├── rules-tests/
│ ├── Phalcon5/Phalcon50Set/ # 规则集整体测试
│ └── Phalcon5/Rector/New_/.../ # 单条规则测试
测试约定(Rector 社区惯例)
- 每条规则先写失败的 fixture 测试,再实现规则
- fixture 是
*.php.inc文件,-----分隔符上方为输入代码(升级前),下方为期望输出(升级后) - 只有上半段、没有
-----的 fixture 表示"规则必须原样跳过"(命名惯例skip_xxx.php.inc)
运行测试:
vendor/bin/phpunit --colors=never
本地开发环境(Windows)
本项目用 PHP 8.4 开发与测试(PHP 8.4 已验证 20 个测试全绿;包要求 PHP 8.1+,见 composer.json)。
Set-Location "d:\opt\htdocs\Phalcon4To5Rector" # 运行测试 & "D:\software\php\php8.4.27\php.exe" "vendor\phpunit\phpunit\phpunit" --colors=never # 运行 rector CLI 处理你自己的项目 & "D:\software\php\php8.4.27\php.exe" "vendor\rector\rector\bin\rector" process src --config "config\sets\phalcon50.php" --no-progress-bar
Roadmap
-
Phalcon\Tag确定性子集 →Phalcon\Html\TagFactory迁移规则 ✅(linkTo/image/select等复杂方法仍需手动改写) -
Phalcon\Assets\Manager构造器注入Phalcon\Html\TagFactory✅ -
Phalcon\Text/Phalcon\Helper→Phalcon\Support\Helper\*静态调用迁移 ✅ - 对 v5 中已移除且无自动迁移方案的类(
Phalcon\Kernel等)输出提示 ✅ - 接入
rector/extension-installer实现规则集自动注册 ✅ - 发布到 Packagist,并尝试收录进
rectorphp官方组织
许可
MIT