人工智能

用 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 或更高版本,以及用于生成的 Spring Boot 项目的 Java 21 和 Maven。
  • 对迁移规划(发现、翻译和验证)有基本理解。

本文你将学到什么

你从一个开放的代码仓库开始,因此可以自己运行引擎,而不是只阅读相关内容。引擎所知道的一切都存在于一小组 skill 文件中,借助这些文件,你可以用不止一种方式运行同一套方法论。

运行引擎的两种方式:Kiro 和 AWS Transform

这里的一切都打包为 skill 文件:带版本控制的 Markdown 能力包,它们编码了迁移方法论(php-to-java-migration)和发现扫描器工作流(php-model-discovery)。由于这些知识存在于文件中,而不是任何单一工具中,你可以用两种方式运行同一套方法论。

方法 1:Kiro,交互式且开发者参与其中

Kiro 将 AI 代理带入你的编辑器,逐步驱动迁移。将仓库根目录作为 Kiro 工作区打开,当你要求 Kiro 迁移一个 PHP 应用时,这些 skill 会自动激活。随后 Kiro 会带着明确的审批关卡走完八阶段工作流,因此你可以审查发现清单、批准规则手册,并在下一阶段开始前签核每个阶段。本文中的每个示例都使用这种模式。

方法 2:AWS Transform,代理式且面向组合规模

AWS Transform 是 AWS 用于大规模迁移和现代化的代理式 AI 服务,它现在与 Kiro 原生集成。通过该集成,你可以将管理交互式 Kiro 会话的同一批 skill 文件交给 AWS Transform,因此“先发现后翻译”、作为裁判的 parity harness,以及“修复循环,而不是修复代码”都适用于自主运行。

每种路径的适用场景

  • 控制与自主性: 先用 Kiro 处理代码:在一个应用上运行 skill,阅读生成的 Java,并运行测试。当你想迁移更多应用时,AWS Transform 会以代理方式运行同一套方法论,并在 skill 定义的检查点进行审查。
  • 规模与新颖性: Kiro 一次处理一个应用,适合首次出现的框架。AWS Transform 以并行任务运行许多应用。
  • 共享反馈循环: 两条路径读取相同的 skill 文件,因此在 Kiro 中做出的每一次规则手册修复都会改进下一次 AWS Transform 运行,反之亦然。

解决方案概览:一个共享大脑,多个项目

该引擎围绕一个原则组织:一个共享大脑,多个项目。要打开它,请在本地克隆仓库,然后在 Kiro 中打开一个文件夹并选择仓库根目录(包含 .kiro/ 的文件夹)。Kiro 会自动加载 skill 和 steering,更完整的步骤见“入门”。

如下图所示,工作区将共享方法论层与使用它的各个项目分开。顶部是每个项目都会使用的全局 .kiro/ 层。其下是各项目文件夹,每个文件夹都有自己的 PHP 源代码、Java 输出和规范子文件夹。

Workspace architecture: one shared brain, many projects. Diagram of the workspace layout. At the top is the Kiro workspace root, PHP-Java-Migration. Below it, a shared, global layer under .kiro/ holds the skills (the methodology) and the steering file (the governing workflow), and applies to every project. Beneath that, three per-project folders each hold their own spec sub-folder, and the diagram notes that improving the shared layer once benefits every project.

图 1:工作区分为共享的全局方法论层,以及各项目的代码和规范文件夹

如下图所示,这些相同的共享 skill 文件可以用两种不同方式运行。相同的八阶段、parity 优先流水线既可以由 Kiro 驱动(交互式,一次一个应用),也可以由 AWS Transform 驱动(代理式,组合规模),两者都会将 PHP 源代码转换为经 parity 验证的 Spring Boot Java。

PHP-to-Java Migration Engine: One Shared Brain, Two Execution Paths. Overview of the migration engine. A shared layer on the left holds the skill files and steering file that every project uses. Two execution paths on the right run the same methodology: Kiro, for interactive work on one application at a time, and AWS Transform, for agentic work across a portfolio. Below them, an eight-phase pipeline runs from the PHP codebase through Phases 0 to 3 (human judgment), then Phases 4 to 8 (self-driving loops), and ends at a parity harness that acts as the referee.

图 2:相同的共享 skill 文件驱动两条执行路径:Kiro(交互式,一次一个应用)和 AWS Transform(代理式,组合规模)。两者都运行相同的八阶段 parity 优先流水线,将 PHP 源代码转换为经 parity 验证的 Spring Boot Java

在 .kiro/ 下有一个共享的全局层,包含两个 Skill:php-model-discovery(扫描器)和 php-to-java-migration(八阶段操作手册),以及 core-workflow.md Steering 文件。每个项目文件夹都在 .kiro/specs/ 下拥有自己的 PHP 源代码、Java 输出和规范子文件夹,因此改进一次方法论,每个项目都能继承这一收益。

先发现后翻译

最重要的单条规则会在其他一切之前生效:在扫描器运行之前,不要读取、猜测或手工翻译模型或实体文件。

如下图所示,扫描器以单次遍历、无依赖的方式工作。它对源 token 应用三种发现策略,并输出一个 JSON 清单,任何有歧义的内容都会进入审查标记队列,由人工解决。

php-model-discovery, three strategies, one manifest. Diagram of the discovery scanner, discover-models.php. On the left, the PHP codebase feeds into the scanner, which runs three strategies in sequence: Eloquent model discovery, Doctrine attribute detection, and ORM XML mapping. An arrow then carries the results to model-manifest.json on the right, which holds a models array of fields, casts, and relationships, plus a flags array that serves as the human review queue.

图 3:扫描器对源 token 运行三种发现策略,并输出一个带有审查标记队列的单一 JSON 清单

扫描器是 discover-models.php,一个单文件、无依赖的 PHP 命令行工具,它不会执行目标代码。它只把源文本作为 token 读取,因此无论依赖是否安装,它都能针对你选择的应用运行。它在每次扫描中运行三种策略:Eloquent 模型发现(沿类继承链向上追溯到 Illuminate\Database\Eloquent\Model)、Doctrine 属性检测(#[ORM\Entity] 属性)以及 ORM XML 映射(外部 *.orm.xml 文件)。输出是一个单一的 JSON 清单。一个 models[] 数组承载每个字段、类型转换、关系和可见性规则,并且每个条目上都会出现一个 flags[] 数组。扫描器会标记歧义,而不是猜测。例如,由运行时表达式构建的 $fillable 列表会变成一条用平实英语表述的标记,而该标记列表就是人工审查队列。

parity 优先流水线

阶段 0 是准备阶段:它运行扫描器并汇总清单。接下来的三个阶段则集中投入人类专业知识。阶段 1 在编写 Java 之前构建 parity harness,针对 PHP 原版和 Java 移植版重放请求/响应配对。该 harness 必须在可正常工作的 PHP 上通过,并在你故意破坏它时失败,因为漏掉注入式破坏的 harness 是不可信的。阶段 2 播种规则手册和差距清单(RULEBOOK.md、GAP_INVENTORY.md),阶段 3 在提交到整个应用之前,用代表性文件对其进行压力测试。

The parity-first migration pipeline (8 phases) Diagram of the parity-first migration pipeline with eight phases. Phases 0 to 3 are the human-led judgment steps, and Phases 4 to 8 are self-driving loops, and both groups feed a parity harness that acts as the referee comparing the PHP original with the Java port.

图 4:人类判断被前置到准备性的阶段 0 和阶段 1–3。阶段 4–8 主要是自我驱动的循环,由 parity harness 担任裁判

前四个阶段集中投入人类专业知识。阶段 0 运行扫描器并汇总清单。阶段 1 在编写 Java 之前构建 parity harness,针对 PHP 原版和 Java 移植版重放请求/响应配对。该 harness 必须在可正常工作的 PHP 上通过,并在你故意破坏它时失败,因为漏掉注入式破坏的 harness 是不可信的。阶段 2 播种规则手册和差距清单(RULEBOOK.md、GAP_INVENTORY.md),阶段 3 在提交到整个应用之前,用代表性文件对其进行压力测试。

阶段 名称 交付物
0 评估与发现 模型清单 + 清单汇总 + 切换选择
1 构建裁判 可在 PHP 和 Java 上运行的 parity harness
2 规则手册 + 差距清单 RULEBOOK.md、GAP_INVENTORY.md
3 对规则手册进行压力测试 经过加固的规则手册,已用代表性文件验证
4 脚手架 可编译的 Spring Boot 项目
5 翻译数据模型 JPA 实体 + schema 基线
6 翻译 I/O 层 控制器、安全、模板可响应
7 转换业务逻辑 逻辑已转换,测试通过
8 证明 parity 并切换 parity 报告 + 切换检查清单

阶段 4–8 主要是自我驱动的循环:阶段 4 搭建项目脚手架,阶段 5 根据清单翻译数据模型,阶段 6 翻译 I/O 层(路由变成控制器,中间件变成过滤器,验证变成带注解的数据传输对象),阶段 7 分批转换业务逻辑,阶段 8 针对 harness 证明 parity 并切换。两条原则支配着这个循环。第一,PHP 代码就是规范:当裁判同意时,移植才算完成,或者每个不匹配都被记录为已批准的变更。第二,你要修复的是循环,而不是代码,即修订规则手册并重新生成,而不是手工打补丁。

演练:从 Eloquent 到 Spring Boot

laravel-eloquent-sample 项目是一个可运行、有边界的示例:一个开源 Laravel 应用的只读切片,其中 Book、Chapter、Page 和 User 模型已迁移到基于 Java 21 的 Spring Boot 3.4.1,使用 Maven 和内存 H2 数据库。

从 PHP 到 Spring Boot 的映射是机械且可追溯的,如下图所示。左侧的每个清单条目都映射到右侧的一个 Java 构造,从而生成应用切片的层化运行时架构。

From Eloquent to Spring Boot: mapping and the generated slice. Diagram in two parts. The left side maps PHP and Laravel Eloquent constructs to their Java and Spring Boot equivalents, with arrows linking each pair, such as models to JPA entities and query scopes to Spring Data repository methods. The right side shows the layered architecture of the generated book-stack slice: an HTTP client calls a controller layer, which calls a repository layer, then an entity layer, and finally an H2 in-memory database.

图 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 个被移植,而且最重要的是,这个切片从未构建 parity harness,它称之为“最大的单一差距”。记录其不足之处本身就是设计的一部分。

入门

完整的迁移引擎可在 示例 PHP 到 Java 迁移仓库.

要使用它:

  1. 克隆仓库并将其根目录作为你的 Kiro 工作区打开(打开一个文件夹并选择包含 .kiro/ 的文件夹)。除了用于扫描器的 PHP 8.0+ 以及带 Maven 的 Java 21 之外,无需安装任何东西。
  2. 将 PHP 源代码获取到项目的 source-php/ 文件夹中。README 固定了用于 parity 的确切上游提交,以便任何人都能重现基线。
  3. 让 Kiro 迁移应用。php-to-java-migration skill 会自动激活,先运行扫描器,在 .kiro/specs/ 下生成新的规范,并引导你完成审批关卡。
  4. 对于代理式运行,将 AWS Transform 指向相同的 skill 文件,这样它的代理就能在你的组合范围内执行相同的方法论。

该方法论会自动检测 Laravel、Symfony、CodeIgniter 和纯 PHP,并且扩展是增量的:为新框架添加一行检测配置和一个 references/<framework>-to-spring.md 指南。由于 Kiro 和 AWS Transform 读取相同的文件,改进它们一次就能同时升级两个引擎。

清理

如果你在本次演练期间部署了示例 Spring Boot 应用:

  1. 停止正在运行的 Spring Boot 应用(内存中的 H2 数据库是临时的,无需单独清理)。
  2. 如果不再需要,请从工作区中删除生成的 Java 项目文件夹。
  3. 发现扫描器只生成一个 JSON 清单文件。如果你不打算引用发现扫描器的 JSON 清单,请从工作目录中删除它。
  4. 迁移引擎本身不会预置任何 AWS 资源,因此没有需要取消预置的云资源。

结论

我们展示了如何用 Kiro 构建一个可重复的 PHP 到 Java 迁移引擎,将大规模重写转变为一个可度量、可累积的过程。关键原则如下:

  • 先发现,后翻译: 机械扫描器会清点每个模型、字段和关系,因此你无需猜测结构。
  • 先构建判定器,再写代码: 一致性校验框架在编写第一行 Java 代码之前就定义了 完成 的标准。
  • 修复循环,而非代码: 当同一个错误在多个文件中出现时,应修改规则手册并重新生成,而不是手工修补。
  • 一个共享大脑: 方法论只编写一次,在各项目间共享,并随着每次迁移不断改进。

这些内容并非 PHP 或 Java 所特有。同样的形态适用于其他迁移场景,即旧系统是唯一完整的规范。克隆 示例 PHP 到 Java 迁移仓库, 将其作为 Kiro 工作区打开,并探索为其提供支持的 Skills 和 Steering 能力,或者将相同的 skill 文件带到 AWS Transform。有关 AWS 上语言迁移模式的更多信息,请参阅 AWS 规范性指导 文档。


关于作者