typo3-batch について
typo3-batchは、TYPO3 v14のコードベースで大規模かつ並列化できる変更を進めるスキルです。作業を独立した単位に分け、計画の承認後に各単位を実行して検証します。
主な機能
- 01TYPO3 v14の一括移行ガイド
- 02コード調査と作業の分割
- 03承認を得る番号付き計画
- 04単位ごとの検証と報告
- 05一般的な移行対象の手順
活用シーン
- 01TYPO3フックとTCA設定の移行
- 02makeInstance呼び出しの依存性注入への置換
- 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つの単位を作成します。
各単位で:
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 → イベントの対応関係(Core のイベント一覧で確認してください):
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/レガシー API | 一般的な移行先 |
|---|---|
processDatamap_afterDatabaseOperations/関連する SC_OPTIONS | processDatamapClass hook メソッドを維持します(1対1で対応する 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) | 1対1で対応する PSR-14 の置き換えはありません。レンダリングパイプラインの操作には PSR-15 ミドルウェアを推奨します |
tslib_fe->contentPostProc(cached) | AfterCacheableContentIsGeneratedEvent |
tslib_fe->contentPostProc(output) | PSR-14 イベントはありません。PSR-15 ミドルウェアを使用してください(Deprecation #91012)。AfterCachedPageIsPersistedEvent が置き換えるのは insertPageIncache であり、この hook ではありません |
tslib_fe->contentPostProc(all) | AfterCacheableContentIsGeneratedEvent(Breaking #97862。usePageCache も対象) |
BackendUtility->getPagesTSconfig | ModifyLoadedPageTsConfigEvent |
generatePageTSconfig | ModifyLoadedPageTsConfigEvent |
1対1で置き換えられない項目(バッチで書き換える前に確認してください):
drawHeaderHook/drawFooterHook— Page モジュールのヘッダー/フッター統合ポイントです。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 単位にします。
単位ごとに:
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 単位にします。
単位ごとに:
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 単位にします。
単位ごとに:
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、アイコン、モジュール、プラグイン)ごとに 1 単位にします。
単位ごとに:
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/ ディレクトリの有無を確認し、テスト可能なクラスを探します。
分割:テストの種類ごとに 1 単位にします。
単位ごとに:
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 単位にします。
単位ごとに:
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 単位にします。
単位ごとに:
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 のフラッシュメッセージ、TCA ラベルにハードコードされた文字列をすべて探します。
分割:言語ファイルの範囲(フロントエンド、バックエンド、TCA)ごとに 1 単位にします。
単位ごとに:
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.json を変更した場合)
composer normalizeが成功する - (設定されている場合)PHPStan が成功する
- (利用可能な場合)ユニットテストが成功する
- (利用可能な場合)機能テストが成功する
- フロントエンドのレンダリングに変更がない(手動でスポットチェック)
- バックエンドのフォームが引き続き動作する(手動でスポットチェック)
中止条件
次の場合はバッチを停止して報告します:
- ある単位によって既存のテストが失敗する
- 生成されたコードに PHP の構文エラーがある
- 2 つの単位で予期せず同じファイルが必要になる
- ユーザーから停止の指示がある
v14 専用の一括移行対象
以下の一括移行パターンは v14 固有です。
共通の v14 バッチ操作 [v14 のみ]
| バッチ操作 | 移行対象 |
|---|---|
$GLOBALS['TSFE'] を削除 | TypoScriptFrontendController を参照するすべての PHP ファイル |
| アノテーション → 属性 | Extbase コントローラー内のすべての @validate、@ignorevalidation |
MailMessage->send() を削除(#108097)→ TYPO3\CMS\Core\Mail\MailerInterface を注入し、$this->mailer->send($email) を呼び出す | すべてのメール送信コード(破壊的変更 #108097) |
ctrl.searchFields を削除(v14)→ フィールド config 内でフィールドごとに searchable を指定 | 破壊的変更:#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 で削除済み(重要 #105538) |
クレジットと帰属表示
TYPO3 のコンテキスト向けに、Boris Cherny(Anthropic)の Claude Code にバンドルされている /batch スキルを基にしています。
著作権 (c) Anthropic — バッチ操作のパターン(MIT ライセンス)