如何用 Kiro 构建可复用的 PHP 转 Java 迁移引擎
Build a repeatable PHP-to-Java migration engine with Kiro
AWS 博客介绍用 Kiro(AI IDE)把 PHP 应用迁移到 Java 变成可度量、可重复的流程,核心是一个可复用引擎:共享方法论、机械式发现扫描器和八阶段工作流,要求 Java 移植通过 parity harness 校验后才算完成。
当你的团队将成熟的 PHP 应用迁移到 Java 时,你将获得更强的类型安全性、更广泛的库支持以及更可预测的扩展能力。一个用 Laravel、Symfony 或 Doctrine 历经多年构建的 PHP 代码库,会把业务规则藏在一些不显眼的地方——从 Eloquent trait 到 XML 映射文件——因此一个结构相似的 Java 移植版可能编译顺利通过,行为却有所不同。
这篇文章将展示如何借助 Kiro,把 PHP 到 Java 的迁移从一次性的信仰之跃转变为可衡量、可重复的流程。Kiro 是一款 AI 集成开发环境(IDE),它将 AI 智能体与你的代码库配对,以人机协同的方式执行多步骤工程任务。该方法的核心是一个可复用的引擎:一套共享的方法论、一个机械化的发现扫描器,以及一个八阶段工作流。这个引擎将原始的 PHP 应用视为规格说明,并在一致性验证工具确认之前,拒绝宣告 Java 移植版是正确的。
前提条件
开始之前,你需要:
- 熟悉 PHP(Laravel/Eloquent 或 Symfony/Doctrine)。具备 Java 知识(Spring Boot、JPA)有助于你审查生成的输出,但引擎会为你生成符合习惯用法的 Java 代码,因此你无需亲自用 Java 重写应用。
- 一个可以访问 Skills 和 Steering 文件的 Kiro 工作区。
- 在运行发现扫描器的机器上安装 PHP 8.0 或更高版本,并为生成的 Spring Boot 项目准备 Java 21 和 Maven。
- 对迁移规划(发现、转换和验证)的基本理解。
你将在本文中学到什么
你将从一个公开的代码仓库开始,因此你可以亲自运行这个引擎,而不是仅仅阅读介绍。引擎所知晓的一切都保存在一小组技能文件中,有了这些文件,你可以用不止一种方式运行相同的方法论。
运行引擎的两种方式:Kiro 和 AWS Transform
这里的一切都被打包为技能文件:以版本化 Markdown 能力包的形式编码迁移方法论(php-to-java-migration)和发现扫描器工作流(php-model-discovery)。由于这些知识保存在文件中而不是绑定于任何单一工具,你可以通过两种方式运行相同的方法论。
方式一:Kiro,交互式且开发者全程参与
Kiro 将 AI 智能体引入你的编辑器,逐步推进迁移。将代码仓库根目录作为 Kiro 工作区打开,当你让 Kiro 迁移 PHP 应用时,技能会自动激活。Kiro 随后会按照带有明确审批关卡的八阶段工作流进行,因此你可以审查发现清单、批准规则手册,并在每个阶段结束前签署确认后才开始下一阶段。本文中的所有示例均采用这种方式。
方式二:AWS Transform,智能体化且适用于组合级规模
AWS Transform 是 AWS 用于大规模迁移和现代化的智能体 AI 服务,如今已与 Kiro 原生集成。通过这一集成,你可以把管理交互式 Kiro 会话的同一组技能文件交给 AWS Transform,这样“先发现后转换、以一致性验证工具为裁判,以及‘修复循环,而非代码’”这些原则同样适用于自主运行。
各自的适用场景
- 控制与自主性:先用 Kiro 亲自过一遍代码:在一个应用上运行技能,阅读生成的 Java 代码,并运行测试。当你想迁移更多应用时,AWS Transform 可以以智能体方式运行相同的方法论,并在技能定义的检查点进行审查。
- 规模与新意:Kiro 一次处理一个应用程序,适合首次使用的框架。AWS Transform 则将许多应用程序作为并行任务运行。
- 共享的反馈闭环:两条路径读取相同的技能文件,因此在 Kiro 中做出的每一条规则修正都会改进下一次 AWS Transform 运行,反之亦然。
该引擎围绕一个单一原则组织:一个共享的大脑,多个项目。要打开它,请先将仓库克隆到本地,然后在 Kiro 中打开一个文件夹并选择仓库根目录(包含 .kiro/ 的文件夹)。Kiro 会自动加载技能和引导规则,更完整的步骤见“入门”部分。
该工作区将共享的方法论层与使用它的各个项目分离开来,如下图所示。顶层是每个项目都会调用的全局 .kiro/ 层。其下是各个项目的文件夹,每个文件夹都有自己的 PHP 源码、Java 输出和规范子文件夹。
图 1:工作区分为共享的全局方法论层以及各项目独立的代码和规范文件夹
这些相同的共享技能文件可以通过两种不同的方式运行,如下图所示。完全相同的八阶段、对等优先的流水线既可以由 Kiro 驱动(交互式,一次一个应用程序),也可以由 AWS Transform 驱动(智能体式,组合规模),两者都将 PHP 源码转换为经过对等验证的 Spring Boot Java。
图 2:相同的共享技能文件驱动两条执行路径:Kiro(交互式,一次一个应用程序)和 AWS Transform(智能体式,组合规模)。两者都运行完全相同的八阶段对等优先流水线,将 PHP 源码转换为经过对等验证的 Spring Boot Java
.kiro/ 下的共享全局层包含两个 Skills:php-model-discovery(扫描器)和 php-to-java-migration(八个阶段的操作手册),以及 core-workflow.md Steering 文件。每个项目文件夹在 .kiro/specs/ 下拥有自己的 PHP 源码、Java 输出和 spec 子文件夹,因此只需改进一次方法论,每个项目都能继承这一成果。
先发现,后翻译
最重要的一条规则在任何操作之前就会触发:在扫描器运行之前,不要阅读、猜测或手工翻译任何模型或实体文件。
扫描器单次运行、无任何依赖,如下图所示。它对源码 token 应用三种发现策略,输出一个 JSON 清单,任何含糊之处都会被送入审查标记队列,由人工解决。
图 3:扫描器对源码 token 运行三种发现策略,输出一个带有审查标记队列的 JSON 清单
扫描器是 discover-models.php,一个单文件、无依赖的 PHP 命令行工具,不会执行目标代码。它只把源码文本当作 token 来读取,因此无论依赖是否安装,都可以对你选择的应用运行。每次扫描它会运行三种策略:Eloquent 模型发现(沿类继承链追溯到 Illuminate\Database\Eloquent\Model)、Doctrine 属性检测(#[ORM\Entity] 属性)以及 ORM XML 映射(外部 *.orm.xml 文件)。输出是一个单一的 JSON 清单。一个 models[] 数组承载所有字段、类型转换、关系和可见性规则,每个条目上都有一个 flags[] 数组。扫描器会标记含糊之处,而不是猜测。例如,由运行时表达式构建的 $fillable 列表会变成一条通俗易懂的标记,这些标记列表就是人工审查队列。
对等优先的流水线
Phase 0 是准备阶段:它运行扫描器并汇编清单。随后的前三个阶段集中人类的专业判断。Phase 1 在编写 Java 代码之前先构建对等性测试工具,将请求/响应对同时回放到 PHP 原版和 Java 移植版上。该测试工具必须在正常工作的 PHP 上通过,在人为破坏时必须失败,因为无法捕获注入故障的测试工具是不可信的。Phase 2 填充规则手册与差距清单(RULEBOOK.md、GAP_INVENTORY.md),Phase 3 则在将其提交应用到整个应用之前,先针对代表性文件进行压力测试。
图 4:人类判断被前置到准备性的 Phase 0 以及 Phase 1–3 中。Phase 4–8 大多是自动驾驶式的循环,由对等性测试工具裁决
前四个阶段集中人类的专业判断。Phase 0 运行扫描器并汇编清单。Phase 1 在编写 Java 代码之前先构建对等性测试工具,将请求/响应对同时回放到 PHP 原版和 Java 移植版上。该测试工具必须在正常工作的 PHP 上通过,在人为破坏时必须失败,因为无法捕获注入故障的测试工具是不可信的。Phase 2 填充规则手册与差距清单(RULEBOOK.md、GAP_INVENTORY.md),Phase 3 则在将其提交应用到整个应用之前,先针对代表性文件进行压力测试。
| 阶段 | 名称 | 交付物 |
| 0 | 评估与发现 | 模型清单 + 资产清单 + 切换方案 |
| 1 | 构建裁判 | 可针对 PHP 和 Java 运行的对等性测试工具 |
| 2 | 规则手册 + 差距清单 | RULEBOOK.md、GAP_INVENTORY.md |
| 3 | 对规则手册进行压力测试 | 经过针对代表性文件验证并得到强化的规则手册 |
| 4 | 搭建脚手架 | 可编译的 Spring Boot 项目 |
| 5 | 翻译数据模型 | JPA 实体 + 数据库架构基线 |
| 6 | 翻译 I/O 层 | 控制器、安全、模板均可响应 |
| 7 | 转换业务逻辑 | 逻辑转换完成,测试通过 |
| 8 | 证明对等性并切换 | 对等性报告 + 切换检查清单 |
Phase 4–8 大多是自动驾驶式的循环:Phase 4 搭建项目脚手架,Phase 5 依据清单翻译数据模型,Phase 6 翻译 I/O 层(路由变成控制器,中间件变成过滤器,验证变成带注解的数据传输对象),Phase 7 分批转换业务逻辑,Phase 8 对照测试工具证明对等性并完成切换。有两个原则支配着这个循环。第一,PHP 代码就是规范:当裁判认可时移植才算完成,或者每一处不一致都被记录为经过批准的变更。第二,修复的是循环而非代码,即修订规则手册并重新生成,而不是手工修补。
实战演练:从 Eloquent 到 Spring Boot
laravel-eloquent-sample 项目是一个可行且范围有限的示例:一个开源 Laravel 应用的只读切片,其中 Book、Chapter、Page 和 User 模型已迁移到运行于 Java 21、使用 Maven 和内存 H2 数据库的 Spring Boot 3.4.1 上。
从 PHP 到 Spring Boot 的映射是机械化且可追溯的,如下图所示。左侧的每个清单条目都映射到右侧的一个 Java 构件,从而生成该应用切片的分层运行时架构。
图 5:左侧为清单驱动的映射。右侧为生成的应用切片的分层运行时架构
这些映射是机械化的,并且可以追溯到清单文件:PHP 命名空间对应 Java 包,Eloquent 模型对应 JPA @Entity,has Many 和 belongs to 关系对应 @OneToMany 和 @ManyToOne,Eloquent 查询作用域对应 Spring Data 仓库方法。这种规范性体现在序列化中:html、markdown 和 text 带有 @JsonIgnore,因为清单文件将它们记录在 Page 的 $hidden 列表中,而 Book 的 description 则刻意没有。
规范坦诚地指出,37 个模型中只有 4 个被移植,更重要的是,一致性测试工具从未针对这个切片构建,规范称之为“最大的单一缺口”。记录自身不足之处本身就是设计的一部分。
开始使用
完整的迁移引擎可在 PHP 转 Java 迁移示例仓库中获取。
使用方法:
- 克隆仓库,并将其根目录作为你的 Kiro 工作区打开(打开文件夹并选择包含 .kiro/ 的文件夹)。除了用于扫描器的 PHP 8.0+ 以及带 Maven 的 Java 21 之外,无需安装其他东西。
- 将 PHP 源码获取到项目的 source-php/ 文件夹中。README 锁定了用于一致性验证的确切上游提交,因此任何人都可以复现基线。
- 让 Kiro 迁移该应用程序。php-to-java-migration 技能会自动激活,先运行扫描器,在 .kiro/specs/ 下生成新的规范,并引导你完成审批关卡。
- 对于智能体化运行,可将 AWS Transform 指向相同的技能文件,让它的智能体在你的项目组合中执行完全相同的方法论。
该方可自动检测 Laravel、Symfony、CodeIgniter 和普通 PHP,且扩展是增量的:为新框架添加一行检测规则和一份 references/<framework>-to-spring.md 指南即可。由于 Kiro 和 AWS Transform 读取相同的文件,只需精炼一次即可同时升级两个引擎。
清理
如果你在本次演练过程中部署了示例 Spring Boot 应用程序:
- 停止正在运行的 Spring Boot 应用程序(内存中的 H2 数据库是临时性的,无需单独清理)。
- 如果不再需要,请从工作区中删除生成的 Java 项目文件夹。
- 发现扫描器只生成一个 JSON 清单文件。如果你不打算引用它,请从工作目录中删除发现扫描器的 JSON 清单。
- 迁移引擎本身不预置任何 AWS 资源,因此没有需要撤销的云资源。
结论
我们展示了如何使用 Kiro 构建可重复的 PHP 转 Java 迁移引擎,将大规模重写转变为可度量、可复利的过程。关键原则是:
- 先发现,后翻译:机械化扫描器盘点每一个模型、字段和关系,因此你无需猜测结构。
- 在编写代码之前先构建评判器:一致性测试工具在第一行 Java 代码写出来之前就定义了完成的标准。
- 修复循环,而不是代码:当同样的错误在多个文件中出现时,应修改规则手册并重新生成,而不是手工修补。
- 一个共享的大脑:方法论只编写一次,跨项目共享,并随着每次迁移不断改进。
这些内容并不特定于 PHP 或 Java。同样的模式也适用于其他迁移场景——即旧系统是唯一完整规范的情况。你可以克隆这个 PHP 到 Java 迁移示例仓库,将其作为 Kiro 工作区打开,探索支撑它的 Skills 和 Steering 功能,或者将相同的技能文件用于 AWS Transform。欲了解 AWS 上更多语言迁移模式,请参阅 AWS Prescriptive Guidance 文档。
关于作者
来源: AWS Machine Learning Blog · aws.amazon.com




