typo3-datahandler について
TYPO3 v14 で DataHandler を使ってレコードを変更する開発スキルです。拡張機能の作成、更新、コマンド実行、バックエンドユーザーのコンテキストを案内します。
主な機能
- 01DataHandler の使用ガイド
- 02DataMap と CmdMap のパターン
- 03レコードの作成、更新、移動、コピー
- 04バックエンドユーザーコンテキストの説明
活用シーン
- 01TYPO3 v14 のレコード書き込み実装
- 02レコードの移動や削除操作の追加
- 03CLI や scheduler タスクでの DataHandler 実行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dirnbauer/ webconsulting-skills --skill typo3-datahandlerインストール後、Claude Code で/typo3-datahandlerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/06-common-pitfalls.md07-retrieving-new-record-uids.md08-workspace-aware-operations.md09-extending-datahandler-hooks-and-real-core-events.md10-version-constraints-for-extensions.mdcredits-and-attribution.mdfull-guide.mdv14-only-changes.md詳細
TYPO3 DataHandler の操作
互換性: TYPO3 v14.x このスキルのすべてのコード例は、TYPO3 v14 で動作するように設計されています。
TYPO3 の API を優先: カスタム実装を作成する前に、必ず TYPO3 の組み込み API、コア機能、確立された規約を使用してください。TYPO3 にすでに用意されているものを再実装しないでください。使用する API やメソッドが TYPO3 v14 に存在し、非推奨になっていないことを、公式 TYPO3 ドキュメントで必ず確認してください。
1. 最優先の原則
pages、tt_content、または TCA で設定されたテーブルに対して、生の SQL(INSERT、UPDATE、DELETE)を絶対に使用しないでください。
次の処理を確実に行うために、必ず DataHandler を使用してください。
- 参照インデックスの更新(
sys_refindex) - キャッシュのクリア
- バージョン履歴(
sys_history) - ワークスペースとの互換性
- コアで定義されている適切なフック/イベントの統合(§9 を参照)
- FlexForm の処理
- MM リレーションの管理
例外(生の SQL を使用可能)
- TCA のないカスタムログテーブル
- 一括分析/レポート用クエリ(読み取り専用)
- 明示的な参照インデックスの再構築を伴う移行スクリプト
2. 配列の構造
DataMap($data)
レコードの作成または更新に使用します。
構文: $data[tableName][uid][fieldName] = value
新規レコードの作成:
UID として、NEW で始まる一意の文字列を使用します。
<?php
declare(strict_types=1);
$data = [
'tt_content' => [
'NEW_1' => [
'pid' => 1,
'CType' => 'text',
'header' => 'My New Content Element',
'bodytext' => '<p>Content goes here</p>',
'sys_language_uid' => 0,
],
],
];
既存レコードの更新:
数値の UID を使用します。
<?php
declare(strict_types=1);
$data = [
'tt_content' => [
123 => [
'header' => 'Updated Header',
'hidden' => 0,
],
],
];
NEW レコードの参照:
<?php
declare(strict_types=1);
$data = [
'pages' => [
'NEW_page' => [
'pid' => 1,
'title' => 'New Page',
],
],
'tt_content' => [
'NEW_content' => [
'pid' => 'NEW_page', // References the new page
'CType' => 'text',
'header' => 'Content on new page',
],
],
];
CmdMap($cmd)
レコードの移動、コピー、削除、または削除の取り消しに使用します。
構文: $cmd[tableName][uid][command] = value
レコードの削除:
<?php
declare(strict_types=1);
$cmd = [
'tt_content' => [
123 => ['delete' => 1],
],
];
レコードの移動:
<?php
declare(strict_types=1);
$cmd = [
'tt_content' => [
123 => ['move' => 456], // Target page UID; use negative UID to place after record
],
];
レコードのコピー:
<?php
declare(strict_types=1);
$cmd = [
'tt_content' => [
123 => ['copy' => 1], // Target page UID
],
];
レコードのローカライズ:
<?php
declare(strict_types=1);
$cmd = [
'tt_content' => [
123 => [
'localize' => 1, // Target language UID
],
],
];
3. 実行パターン
TYPO3 v14 における TYPO3 の公開 DataHandler API は、次のとおりです。
- 使用するたびに
GeneralUtility::makeInstance(DataHandler::class)でDataHandlerを取得します。DataHandler は状態を保持するため、依存性注入のコンストラクター経由で注入してはいけません。また、コアの設定(フック、協調オブジェクト)を一貫させるため、new DataHandler()も避けてください。 process_*を呼び出す前に、start($dataMap, $commandMap[, $backendUser[, $referenceIndexUpdater]])を呼び出します。第 4 引数は存在しますが、@internalです。拡張コードでは通常、最初の 2~3 個の引数のみを使用してください。process_datamap()および/またはprocess_cmdmap()を呼び出します。$dataHandler->errorLogを確認し、新規レコードについては$dataHandler->substNEWwithIDsに期待するキーが存在することを確認します。また、ワークスペースでは、バージョン行が想定される場合に$dataHandler->autoVersionIdMapを確認します。
キャッシュ: 従来の DataHandler キャッシュヘルパーではなく、CacheManager/キャッシュグループ、または PSR-14 キャッシュイベントを優先してください。
公式ドキュメントでは、DataHandler の一般的なトランザクション契約は定義されていません。通常の拡張コードでは、まず標準 API を使用し、特定のユースケースで関係するデータベース接続と副作用を慎重に検証した後にのみ、独自のトランザクション処理を追加してください。
<?php
declare(strict_types=1);
namespace Vendor\Extension\Service;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
final class ContentService
{
public function createOrUpdateContent(array $data, array $cmd = []): array
{
/** @var DataHandler $dataHandler */
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);
$dataHandler->start($data, $cmd);
if ($data !== []) {
$dataHandler->process_datamap();
}
if ($cmd !== []) {
$dataHandler->process_cmdmap();
}
if ($dataHandler->errorLog !== []) {
throw new \RuntimeException(
'DataHandler error: ' . implode(', ', $dataHandler->errorLog),
1700000001
);
}
return $dataHandler->substNEWwithIDs;
}
}
4. バックエンドコンテキスト
DataHandler には、有効なバックエンドユーザーコンテキストが必要です。$GLOBALS['BE_USER']->user を変更して管理者モードを手動で偽装する必要はありません。
- CLI/スケジューラーのコンテキストでは、DataHandler を使用する前にバックエンド認証を初期化してください。
- TYPO3 のコマンドは
_cli_バックエンドユーザーを使用します。 - 別のバックエンドユーザーが必要な場合は、適切な
BackendUserAuthenticationオブジェクトをstart()の第 3 引数として渡してください。 $GLOBALS['BE_USER']->user['admin'] = 1を手動で設定するのではなく、権限チェックと実際のバックエンドユーザーオブジェクトを使用してください。
CLI コマンドのセットアップ(TYPO3 v14)
<?php
declare(strict_types=1);
namespace Vendor\Extension\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Core\Bootstrap;
#[AsCommand(
name: 'myext:import',
description: 'Import data using DataHandler',
)]
final class ImportCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
Bootstrap::initializeBackendAuthentication();
// Your DataHandler logic here...
return Command::SUCCESS;
}
}
別のバックエンドユーザーを使用する
<?php
declare(strict_types=1);
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
final class ImportService
{
public function runAsUser(
array $data,
array $cmd,
BackendUserAuthentication $backendUser
): void {
/** @var DataHandler $dataHandler */
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);
$dataHandler->start($data, $cmd, $backendUser);
$dataHandler->process_datamap();
$dataHandler->process_cmdmap();
if ($dataHandler->errorLog !== []) {
throw new \RuntimeException(
'DataHandler error: ' . implode(', ', $dataHandler->errorLog),
1700000001
);
}
}
}
5. 参照インデックスの管理
通常の DataHandler による書き込みでは、TYPO3 が参照インデックスを自動的に同期します。通常の process_datamap() / process_cmdmap() の使用後に、手動で ReferenceIndex を呼び出す必要は基本的にありません。
参照インデックスを手動で更新するのは、主に次のような場合です。
- デプロイや TYPO3 のアップグレード
- TCA で定義されたリレーションの変更
- DataHandler を介さないマイグレーションやスクリプト
- 修復やメンテナンスの場面
参照インデックス全体を再構築する
vendor/bin/typo3 referenceindex:update
特定のレコードを手動で更新する(非推奨)
v14 では、ReferenceIndex と updateRefIndexTable() はどちらも @internal です。拡張機能から参照インデックスを直接操作すべきではありません。代わりに vendor/bin/typo3 referenceindex:update を使用するか、DataHandler にインデックスを管理させてください。それでも内部 API を呼び出す場合、非推奨の告知なしに変更される可能性があることを念頭に置いてください。
<?php
declare(strict_types=1);
use TYPO3\CMS\Core\Database\ReferenceIndex;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// @internal API — discouraged; prefer referenceindex:update or DataHandler
$referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
$referenceIndex->updateRefIndexTable('tt_content', 123);
詳細リファレンス
詳細な例、長いテンプレート、トラブルシューティング用の一覧表、付録、または上記に含まれていないセクションが必要な場合は、完全ガイドをお読みください。限定的なタスクでは、このファイルを読み込まず、スキルが段階的に情報を開示するようにしてください。