关于 typo3-batch
typo3-batch 是面向 TYPO3 v14 代码库中大型并行变更的技能。它将工作拆分为独立单元,先提交计划供确认,再逐单元执行和验证。
主要功能
- 01TYPO3 v14 批量迁移指导
- 02代码调研与任务拆分
- 03需确认的编号计划
- 04逐单元验证并汇报
- 05常见迁移目标的操作指导
适用场景
- 01迁移 TYPO3 钩子和 TCA 配置
- 02将 makeInstance 调用改为依赖注入
- 03批量重构模板与本地化内容
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dirnbauer/ webconsulting-skills --skill typo3-batch安装后在 Claude Code 中输入/typo3-batch确认已加载。
详细介绍
TYPO3 批量操作
根据 Boris Cherny(Anthropic)的 Claude Code
/batch技能改编,适用于 TYPO3 场景。 **目标:**仅适用于 TYPO3 v14.x。
在 TYPO3 代码库中编排大规模、可并行的变更。将工作拆分为 5–30 个独立单元,提交计划,然后逐个执行并验证。
流程
- 研究:扫描代码库,查找所有受影响的文件
- 拆分:将工作拆分为互不冲突的独立单元
- 规划:向用户提交编号计划以供审批
- 执行:应用每个单元,并在每次完成后运行验证
- 报告:总结变更,列出所有失败项
执行规则
- 每个单元都必须能够独立验证
- 不得在两个不同单元中修改同一个文件
- PHP 变更后运行
composer normalize/php -l/ PHPStan - 如果有测试,则运行测试(
vendor/bin/phpunit) - 每个单元分别提交,并使用描述性提交消息
- 如果某个单元导致测试失败,则停止并报告
常见 TYPO3 批量操作
1. Hook → PSR-14 事件迁移
研究:查找 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'] 和
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'] 中的所有条目。
拆分:每个 hook 类作为一个单元。
每个单元:
1. Identify the hook interface/method
2. Find the corresponding PSR-14 event (see mapping below)
3. Create new event listener class with #[AsEventListener]
4. Move logic from hook method to __invoke()
5. Remove hook registration from ext_localconf.php
6. If **not** using `#[AsEventListener]`: register the listener in `Services.yaml`. With the attribute and `autoconfigure: true` (default), no extra `tags:` entry is required.
7. Run php -l on new file
Hook → 事件映射(请在核心事件列表中核实):
**DataHandler(
t3lib/class.t3lib_tcemain.php):**TYPO3 Core 不会在TYPO3\CMS\Core\DataHandling\Event下提供名为BeforeRecordOperationEvent/AfterRecordOperationEvent这类通用 PSR-14 事件。对于 datamap/cmdmap 响应,请使用SC_OPTIONShook 类(参见 typo3-datahandler §9)。不要将这些 hook“迁移”到不存在的事件。
| Hook / legacy API | 典型迁移方向 |
|---|---|
processDatamap_afterDatabaseOperations / 相关 SC_OPTIONS | 保留 processDatamapClass hook 方法(没有一对一的 Core 事件) |
processDatamap_preProcessFieldArray | 保留 hook;如果有文档说明,也可使用适用于相应表/字段的范围更窄的 Core 事件 |
processCmdmap_postProcess | 保留 processCmdmapClass hook 方法 |
drawHeaderHook | ModifyPageLayoutContentEvent(Breaking #96526) |
drawFooterHook | ModifyPageLayoutContentEvent(Breaking #96526) |
checkFlexFormValue | 通常仍使用 hook;AfterFlexFormDataStructureParsedEvent 用于 DS 解析,不能直接替代验证逻辑——请针对具体场景在 Core 中确认 |
PageRenderer 渲染 hook(render-preProcess、render-postProcess) | 没有一对一的 PSR-14 替代方案;优先使用 PSR-15 中间件来操作渲染管线 |
tslib_fe->contentPostProc(缓存) | AfterCacheableContentIsGeneratedEvent |
tslib_fe->contentPostProc(输出) | 没有 PSR-14 事件——请使用 PSR-15 中间件(弃用 #91012);AfterCachedPageIsPersistedEvent 替代的是 insertPageIncache,而不是此 hook |
tslib_fe->contentPostProc(全部) | AfterCacheableContentIsGeneratedEvent(Breaking #97862;也涵盖 usePageCache) |
BackendUtility->getPagesTSconfig | ModifyLoadedPageTsConfigEvent |
generatePageTSconfig | ModifyLoadedPageTsConfigEvent |
并非一对一替代项(批量重写前请核实):
drawHeaderHook/drawFooterHook——页面模块的页眉/页脚集成点。现由ModifyPageLayoutContentEvent替代(Breaking #96526),监听器可通过它添加或更改页眉和页脚内容;ModifyButtonBarEvent仅用于按钮栏,不是迁移目标。tslib_fe->contentPostProc——各子 hook(all、cached、output)在 FE 管线的不同阶段运行。将cached和all(以及usePageCache)映射到AfterCacheableContentIsGeneratedEvent,将insertPageIncache映射到AfterCachedPageIsPersistedEvent(Breaking #97862);output没有 PSR-14 事件——请改用 PSR-15 中间件。
2. TCA 现代化(逐步推进,目标为 v14)
调研:扫描所有 Configuration/TCA/ 和 Configuration/TCA/Overrides/ 文件。
拆分:每个 TCA 文件作为一个单元。
每个单元:
1. Replace 'eval' => 'required' → 'required' => true
2. Replace 'eval' => 'trim' → keep where trimming is desired (trim is NOT applied by default)
3. Replace 'eval' => 'null' → 'nullable' => true
4. Replace 'eval' => 'int' → 'type' => 'number'
5. Replace 'renderType' => 'inputDateTime' → 'type' => 'datetime'
6. Replace 'renderType' => 'inputLink' → 'type' => 'link'
7. Replace 'renderType' => 'colorPicker' → 'type' => 'color'
8. Replace 'type' => 'input', 'eval' => 'email' → 'type' => 'email'
9. Convert items arrays: [0] => label, [1] => value → ['label' => ..., 'value' => ...]
10. Remove boilerplate columns auto-created from `ctrl` on TYPO3 v14: hidden, starttime, endtime, fe_group, language fields
11. Use palettes for enablecolumns: visibility → hidden, access → starttime, endtime
12. Remove convention fields from ext_tables.sql (auto-added to database)
13. Run php -l to verify syntax
3. GeneralUtility::makeInstance → DI
调研:查找 Classes/ 中所有 GeneralUtility::makeInstance() 调用。
拆分:每个类文件作为一个单元。
每个单元:
1. Identify all makeInstance calls in the class
2. For each: add constructor parameter with type
3. Replace makeInstance calls with $this->propertyName
4. Add/update Services.yaml if needed
5. Use readonly promoted properties
6. Verify with php -l
4. Fluid 模板重构
调研:扫描 Resources/Private/Templates/、Partials/、Layouts/。
拆分:每个模板目录或逻辑分组作为一个单元。
每个单元:
1. Replace hardcoded strings with <f:translate> keys
2. Add missing XLIFF entries to locallang.xlf
3. Replace <a href="..."> with <f:link.page> or <f:link.typolink>
4. Replace <img> with <f:image>
5. Extract repeated blocks to Partials
6. Add accessibility attributes (alt, aria-label, role)
5. 命名空间重命名 / 扩展键变更
调研:查找所有包含旧命名空间/扩展键的文件。
拆分:按文件类型分组(PHP、Fluid、YAML、TypoScript、SQL)。
每个单元:
PHP files:
1. Replace namespace declarations
2. Replace use statements
3. Replace class references in strings (DI, TCA)
Fluid files:
1. Replace {namespace} declarations
2. Replace ViewHelper references
Configuration files:
1. Update composer.json autoload
2. Update ext_emconf.php
3. Update Services.yaml service names
4. Update TCA table prefixes
5. Update TypoScript paths (EXT:old → EXT:new)
Database:
1. Generate SQL rename migration
2. Update ext_tables.sql
6. ext_localconf / ext_tables 清理
调研:扫描 ext_localconf.php 和 ext_tables.php,查找可移出的代码。
拆分:每项关注点作为一个单元(TSconfig、TypoScript、图标、模块、插件)。
每个单元:
Page TSconfig:
1. Extract addPageTSConfig() calls
2. Create Configuration/page.tsconfig
3. Remove from ext_localconf.php
User TSconfig:
1. Extract addUserTSConfig() calls
2. Create Configuration/user.tsconfig
3. Remove from ext_localconf.php
Icons:
1. Extract icon registry calls
2. Move to Configuration/Icons.php (v14)
3. Remove from ext_localconf.php
Backend modules:
1. Extract registerModule() calls
2. Move to Configuration/Backend/Modules.php
3. Remove from ext_tables.php
7. 测试基础设施设置
调研:检查是否存在 Tests/ 目录,并查找可测试的类。
拆分:每种测试类型作为一个单元。
每个单元:
Unit tests:
1. Create Tests/Unit/ structure
2. Generate test class per service/utility class
3. Add phpunit.xml.dist configuration
Functional tests:
1. Create Tests/Functional/ structure
2. Add fixture files
3. Generate test for repository/DataHandler usage
CI pipeline:
1. Create .github/workflows/ci.yml
2. Configure PHP matrix (8.2, 8.3, 8.4, 8.5)
3. Configure CI matrix (TYPO3 v14, PHP 8.2+)
8. PHP 8.4 迁移
调研:扫描 Classes/,查找 PHP 8.4 迁移候选项。
拆分:每个类文件作为一个单元。
每个单元:
1. Add property hooks where getter/setter pattern exists
2. Use asymmetric visibility (public private(set)) on DTOs
3. Replace array_search + if with array_find() **only after checking semantics** — `array_search()` returns a **key** for a given value; `array_find()` takes a **callback** and returns the first matching **value** (or null). Not drop-in replacements.
4. Replace array_filter + reset with array_find() where a callback-based “first match” is what you need
5. Replace `foreach` + conditional checks with `array_any()` / `array_all()` for value-based logic. These do **not** replace `array_key_exists()` (key-based checks).
6. Add #[\Deprecated] attribute to legacy methods
7. Run php -l to verify syntax
9. Content Blocks 迁移
调研:扫描 TCA、ext_tables.sql 和 Fluid 模板,查找传统内容元素。
拆分:每个内容元素/记录类型作为一个单元。
每个单元:
1. Create ContentBlocks/ContentElements/<name>/config.yaml
2. Map TCA columns to YAML fields
3. Move Fluid template to `ContentBlocks/ContentElements/<name>/templates/` (not `Source/`)
4. Align field definitions in `config.yaml` with TCA columns (no separate `EditorInterface.yaml` in Content Blocks)
5. Remove old TCA override file
6. Remove SQL from ext_tables.sql (columns become automatic)
7. Test rendering in frontend
10. 本地化 / XLIFF 批量处理
调研:查找 Fluid、PHP flash 消息和 TCA 标签中的所有硬编码字符串。
拆分:每个语言文件范围作为一个单元(前端、后端、TCA)。
每个单元:
1. Extract strings from templates/PHP
2. Generate XLIFF keys following convention
3. Add entries to Resources/Private/Language/locallang.xlf
4. Replace hardcoded strings with LLL: references
5. Create de.locallang.xlf with German translations (if applicable)
计划模板
执行前呈交给用户:
## Batch Plan: [Description]
Target: EXT:my_extension (TYPO3 v14)
Files affected: 23
Units: 8
| # | Unit | Files | Risk |
|---|------|-------|------|
| 1 | TCA/Overrides/tt_content.php | 1 | Low |
| 2 | TCA/Overrides/pages.php | 1 | Low |
| 3 | Classes/Controller/ListController.php | 1 | Medium |
| 4 | Classes/Service/ImportService.php | 1 | Medium |
| 5 | Resources/Private/Templates/ (6 files) | 6 | Low |
| 6 | ext_localconf.php → Configuration/ | 4 | Medium |
| 7 | Tests/Unit/ (new) | 5 | Low |
| 8 | locallang.xlf updates | 3 | Low |
Estimated: ~15 minutes
Proceed? [y/n]
验证清单(每个单元)
- 所有修改过的 PHP 文件均通过
php -l -
composer normalize通过(如果修改了 composer.json) - PHPStan 通过(如果已配置)
- 单元测试通过(如果可用)
- 功能测试通过(如果可用)
- 前端渲染未发生变化(手动抽查)
- 后端表单仍可正常工作(手动抽查)
中止条件
出现以下情况时,停止批处理并报告:
- 某个单元导致现有测试失败
- 生成的代码中出现 PHP 语法错误
- 两个单元意外需要修改同一个文件
- 用户要求停止
仅适用于 v14 的批量迁移目标
以下批量迁移模式仅适用于 v14。
常见 v14 批量操作 [仅限 v14]
| 批量操作 | 迁移内容 |
|---|---|
移除 $GLOBALS['TSFE'] | 所有引用 TypoScriptFrontendController 的 PHP 文件 |
| 注解 → 属性 | Extbase 控制器中的所有 @validate、@ignorevalidation |
移除 MailMessage->send() (#108097) → 注入 TYPO3\CMS\Core\Mail\MailerInterface 并调用 $this->mailer->send($email) | 所有发送邮件的代码(Breaking #108097) |
移除 ctrl.searchFields(v14)→ 在字段 config 中为每个字段设置 searchable | 请参阅 Breaking: #106972 |
移除 TCA interface | 所有含有 interface 键的 TCA 文件 |
| 后端模块父级 ID | 所有以 web、file、tools 为父级的 Modules.php |
| Fluid 5.0 类型 | 所有 ViewHelper 参数类型不正确的 Fluid 模板 |
| FlexForm 指针字段 | 所有包含指针配置的 FlexForm XML |
资源 external 属性 | 所有包含 external = 1 的 TypoScript |
移除旧版 switchableControllerActions | 已在 v12 移除——并非仅限 v14 的迁移 |
移除旧版插件子类型 / list_type 配置 | 已在 v14 移除(Important #105538) |
致谢与署名
改编自 Boris Cherny(Anthropic)为 TYPO3 场景提供的 Claude Code 内置 /batch 技能。
Copyright (c) Anthropic — 批量操作模式(MIT License)