用 Kiro 构建可重复的 PHP 到 Java 迁移引擎
团队把一个成熟的 PHP 应用迁移到 Java,能获得更强的类型安全、更丰富的类库支持,以及更可预测的扩展能力。但用 Laravel、Symfony 或 Doctrine 多年积累下来的 PHP 代码,往往把业务规则藏在一些不显眼的地方——从 Eloquent 的 trait 到 XML 映射文件都是如此。所以,即便照葫芦画瓢写出来的 Java 版本能干净地编译通过,运行时行为也可能和原来不一样。本文介绍如何借助 Kiro,把 PHP 到 Java 的迁移从一次「凭信念纵身一跃」变成可度量、可重复的流程。Kiro 是一款 AI 集成开发环境(IDE),它让 AI 代理与你的代码库协作,在你参与把关的前提下执行多步骤工程任务。这套做法的核心是一个可复用的引擎:一套共享方法论、一个机械化的发现扫描器,以及一个分八个阶段的工作流。这个引擎把原始 PHP 应用当作规格说明,在一致性校验工具(parity harness)验证通过之前,绝不宣布 Java 移植版本是正确的。
前置条件
开始之前,你需要:
- 熟悉 PHP(Laravel/Eloquent 或 Symfony/Doctrine)。
- 懂 Java(Spring Boot、JPA)有助于你审查生成的输出,但引擎会为你生成符合 Java 习惯的代码,所以你不需要自己用 Java 重写应用。
- 一个能访问 Skills 和 Steering 文件的 Kiro 工作区。
- 运行发现扫描器的机器上装有 PHP 8.0 或更新版本,以及 Java 21 和 Maven,用于生成的 Spring Boot 项目。
- 对迁移规划(发现、翻译、验证)有基本了解。
你将在本文中学到什么
你会从一个开放的代码仓库入手,所以能亲手运行这个引擎,而不只是读读介绍。引擎掌握的所有知识都放在一小组 skill 文件里;有了这些文件,你可以用不止一种方式来运行同一套方法论。
运行引擎的两种方式:Kiro 与 AWS Transform
这里的一切都打包成 skill 文件:带版本号的 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:工作区分为共享的全局方法层,以及每个项目各自的代码和 spec 文件夹
同样的共享 skill 文件可以用两种不同方式运行,如下图所示。同一套八阶段、优先验证一致性的流水线,既可以由 Kiro 驱动(交互式,一次处理一个应用),也可以由 AWS Transform 驱动(代理式,按组合规模运行),两者都把 PHP 源文件转换为一致性已验证的 Spring Boot Java。
图 2:同一组共享 skill 文件驱动两条执行路径——Kiro(交互式,一次一个应用)和 AWS Transform(代理式,组合规模)。两者运行同一套八阶段、优先验证一致性的流水线,把 PHP 源码转换为一致性已验证的 Spring Boot Java
.kiro/ 下的共享全局层包含两个 Skill:php-model-discovery(扫描器)和 php-to-java-migration(八阶段操作手册),外加 core-workflow.md 这个 Steering 文件。每个项目文件夹都有自己的 PHP 源码、Java 输出,以及 .kiro/specs/ 下的 spec 子文件夹。因此,方法只要改进一次,所有项目都能受益。
先发现,再翻译
最重要的一条规则要放在最前面:在扫描器跑完之前,不要读取、猜测或手工翻译任何模型或实体文件。
扫描器单遍工作、无依赖,如下图所示。它对源码 token 应用三种发现策略,输出一个 JSON 清单;遇到有歧义的内容,则送入 review-flag 队列,交给人工处理。
图 3:扫描器对源码 token 运行三种发现策略,输出一个 JSON 清单,并附带 review-flag 队列
扫描器就是 discover-models.php,一个单文件、无依赖的 PHP 命令行工具,不会执行目标代码。它只把源文本当作 token 来读取,因此无论依赖是否安装,都能对任意应用运行。每次扫描都会应用三种策略:
- Eloquent 模型发现:沿类继承链找到 Illuminate\Database\Eloquent\Model
- Doctrine 属性检测:识别 #[ORM\Entity] 属性
- ORM XML 映射:读取外部的 *.orm.xml 文件
最终输出一个 JSON 清单。
models[] 数组记录每个字段、类型转换、关系和可见性规则,每个条目的 flags[] 数组也会出现。扫描器遇到歧义就标记出来,不擅自猜测。比如 $fillable 列表由运行时表达式生成,这种情况会变成一条用大白话描述的 flag,而这份 flag 列表就是人工审查队列。
以对齐为先的流水线
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 | 评估与摸底 | 模型清单(manifest)+ 清点表 + 切换方案 |
| 1 | 搭建「裁判」 | 能同时跑 PHP 和 Java 的对比测试台(parity harness) |
| 2 | 规则手册 + 差距清单 | RULEBOOK.md、GAP_INVENTORY.md |
| 3 | 压力测试规则手册 | 加固后的规则手册,并用代表性文件验证过 |
| 4 | 搭建脚手架 | 能编译的 Spring Boot 工程 |
| 5 | 翻译数据模型 | JPA 实体 + 数据库表结构基线 |
| 6 | 翻译输入输出层 | 控制器、安全配置、模板都能正常响应 |
| 7 | 转换业务逻辑 | 逻辑转换完成,测试全部通过 |
| 8 | 验证一致并切换 | 对比报告 + 切换检查清单 |
阶段 4~8 大多是自驱动的循环:阶段 4 搭出工程骨架,阶段 5 按清单翻译数据模型,阶段 6 翻译输入输出层(路由变成控制器,中间件变成过滤器,校验变成加了注解的数据传输对象),阶段 7 分批转换业务逻辑,阶段 8 用测试台验证两边行为一致,然后切换。
这个循环由两条原则支配。第一,PHP 代码就是规格说明:裁判认定一致,移植才算完成;否则每一处不一致都要记录成一次已批准的改动。第二,你修的是循环,不是代码——改规则手册然后重新生成,而不是手工打补丁。
实战演练:从 Eloquent 到 Spring Boot
laravel-eloquent-sample 项目的范围明确、可以直接跑起来:它来自一个开源 Laravel 应用,只做了只读的一个切片,把 Book、Chapter、Page、User 四个模型迁移到 Spring Boot 3.4.1、Java 21,用 Maven 构建,数据库是内存版 H2。
从 PHP 到 Spring Boot 的映射是机械的、可追溯的,如下图所示。左侧每个清单条目对应右侧一个 Java 构造,最终生成出这套应用切片的分层运行时架构。
图 5:左侧是清单驱动的映射关系,右侧是生成的应用切片的分层运行时架构
这些映射都是机械的,能追溯到清单上:PHP 命名空间变成 Java 包,Eloquent 模型变成 JPA 的 @Entity,hasMany 和 belongsTo 关系变成 @OneToMany 和 @ManyToOne,Eloquent 的查询作用域(query scope)变成 Spring Data 的 repository 方法。
这种严谨也体现在序列化上:html、markdown 和 text 字段都带上了 @JsonIgnore,因为清单文件记录它们位于 Page 的 $hidden 列表中,而 Book 的 description 字段则有意不加。规范文档坦承,37 个模型中只迁移了 4 个,更重要的是,这一部分从未构建一致性校验工具(parity harness),文档称之为“最大的单一缺口”。把不足之处记录下来,本身就是设计的一部分。
上手实践
完整的迁移引擎放在 PHP-to-Java 迁移示例仓库中。使用方法:
- 克隆仓库,把它的根目录作为 Kiro 工作区打开(打开文件夹,选择包含 .kiro/ 的那个目录)。除了扫描器需要 PHP 8.0+、运行需要 Java 21 和 Maven 之外,无需安装其他东西。
- 把 PHP 源码拉取到项目的 source-php/ 文件夹。README 中固定了用于一致性比对的上游提交哈希,任何人都能复现基线。
- 让 Kiro 迁移这个应用。php-to-java-migration 技能会自动激活,先运行扫描器,在 .kiro/specs/ 下生成一份新的规范文档,并带你走完各个审批关卡。
- 如果要走智能体(agentic)方式,把 AWS Transform 指向同一批技能文件,它的智能体就会在你的整个项目组合中执行同一套方法论。
这套方法论会自动识别 Laravel、Symfony、CodeIgniter 和原生 PHP,扩展方式是增量式的:支持新框架只需加一行检测规则,再加一份 references/-to-spring.md 指南。由于 Kiro 和 AWS Transform 读取的是同一批文件,改进一次就能同时升级两个引擎。
清理
如果你在本次演练中部署了示例 Spring Boot 应用:
- 停止正在运行的 Spring Boot 应用(内存型 H2 数据库是临时的,无需单独清理)。
- 如果不再需要,从工作区删除生成的 Java 项目文件夹。
发现扫描器只产出一个 JSON 清单文件。如果你不打算参考它,就把工作目录中扫描器的 JSON 清单删掉。
迁移引擎本身不会创建任何 AWS 资源,因此没有云资源需要释放。
本文介绍了如何用 Kiro 搭建一个可重复的 PHP 到 Java 迁移引擎,把大规模重写变成可度量、能持续积累的过程。核心原则有以下几条:
- 先摸清结构,再动手翻译:用机械化的扫描器盘点所有模型、字段和关系,不靠猜来判断结构。
- 先定验收标准,再写代码:在写第一行 Java 代码之前,先用一致性测试框架(parity harness)定义什么叫“完成”。
- 改规则,而不是改代码:同一个错误在多个文件中反复出现时,应该修订规则手册并重新生成,而不是手工逐个修补。
- 共享一套方法:方法论只写一次,跨项目共享,并在每次迁移中持续改进。
这些做法并不局限于 PHP 或 Java。只要旧系统是唯一的完整规格说明,其他迁移场景也适用同样的模式。
你可以克隆示例仓库 PHP-to-Java migration repository,在 Kiro 工作区中打开,探索支撑它的 Skills 和 Steering 能力;也可以把同一套技能文件带到 AWS Transform 中使用。想了解更多 AWS 上的语言迁移模式,请参阅 AWS Prescriptive Guidance 文档。
关于作者
Sarat Guttikonda
Sarat 是 Amazon Web Services(AWS)的首席解决方案架构师,与战略客户合作,设计和交付大规模云解决方案。他热衷于人工智能(AI)和机器学习(ML),帮助客户在保持业务敏捷的同时推动创新和转型。工作之外,Sarat 喜欢和儿子一起在 PS5 上玩合作游戏,也喜欢旅行和打羽毛球。
Phani Parcha
Phani 是 Amazon Web Services 的高级技术客户经理(战略客户),拥有 22 年以上构建和扩展企业平台的经验。他负责推动大型企业工作负载的架构卓越性、系统可靠性和运营性能。Phani 专精于分布式系统、微服务架构和云原生平台,重点关注企业转型和生成式 AI 解决方案。
Pallavi Jha 是 Amazon Web Services 的技术顾问,借助 Kiro 和 AI 驱动的开发生命周期(AIDLC)帮助客户提升开发者效率。她与正在进行工程实践现代化的企业合作,专注于用 AI 辅助、规格驱动的方式更快交付更高质量的软件。工作之余,她喜欢创作音乐和徒步。
有了 Kiro,PHP 到 Java 的迁移不再是靠运气的一次性冒险,而是一个可度量、可重复的过程。本文介绍一套可复用的引擎:一个自动化的发现扫描器,外加一套分八个阶段、对等性优先(parity-first,即先保证 Java 版行为与 PHP 原版一致)的工作流。它把原有的 PHP 应用当作规范,再用对等性校验工具验证 Java 移植版。