| name | basercms-plugin-5x-update |
| description | baserCMS プラグインを 5.2系 から 5.3系(PHP 8.5 / CakePHP 5.2.x ベース、開発中)へ移行する際の baserCMS 固有の破壊的変更・非推奨・テスト基盤対応のレシピ集。「プラグインを5.3に対応」「baserCMS 5.3 マイグレーション」「PluginCollection::create(): $config null given」「Plugin named X is already loaded(統合テスト)」「BcApp.testAppPluginsToLoad」「plugins.php の null → []」「Class BcCcFile\... not found(サブプラグイン未ロード)」「Cannot set a node's parent as itself(TreeBehavior + Content フィクスチャ)」「validateUnique(): Argument #2 not passed(vendor の CakePHP 二重ロード)」「MissingTemplateException error500.php でテストの真因がマスクされる」「BcFile コンストラクタ/delete() パス指定の非推奨」等、プラグイン本体・テスト基盤の移行時に参照する。これは同一メジャー内のマイナーアップデート(5.2→5.3)のスキルであり、baserCMS 4→5 のメジャーアップグレード(CakePHP 2→5 の全面書き換え)は basercms-plugin-4-to-5-upgrade を参照。PHP本体起因は php-migration、CakePHP本体起因は cakephp-migration、テスト実行手順は basercms-unittest スキルを参照。新しい baserCMS バージョン対応時は本書にバージョン別追記する。 |
| license | MIT |
baserCMS プラグイン バージョン移行ガイド(5.2 → 5.3)
baserCMS プラグインを 5.2系 から 5.3系へ移行する際に遭遇した baserCMS 固有の問題と修正レシピ集。バージョン別に整理して育てる。
推奨: 着手前に一度 basercms5-claude-workflow-setup(環境セットアップ)を参照し、進め方の環境(設計=superpowers brainstorming/権限整理=permissions-audit/その上での Auto mode/spec・plan の Markdown プレビュー)を整える。提案ベースで、整っていればスキップ。
収録: 5.2 → 5.3。5.3系は PHP 8.5 / CakePHP 5.2.x ベース(執筆時点で開発中)。
役割分担:
- PHP 本体起因(暗黙nullable・動的プロパティ・非正規キャスト・setAccessible・null オフセット等)→
php-migration スキル
- CakePHP 本体/関連パッケージ起因(AbstractMigration→BaseMigration・イベント戻り値・PluginCollection・TreeBehavior・ResultSet・order()/group() 等)→
cakephp-migration スキル
- ユニットテストの実行・集計・切り分け手順 →
basercms-unittest スキル
- 本書は上記に当てはまらない baserCMS 固有 + プラグインのテスト基盤 に絞る。
大原則
- 「致命的エラー」と「非推奨警告」を区別する。
logs/debug.log の debug: や logs/error.log の error: で …は非推奨です と出るものは警告(動作継続)。Fatal / Exception が本当のエラー。
- テスト大量失敗は根本原因単位で分類する。数百件でも原因は十数種。例外メッセージを集計して systemic な原因(vendor 混在・プラグイン未ロード・フィクスチャ不正)から潰す。
- 依存の更新は
composer require を使い、composer update で依存全体を動かさない(cakephp-migration 大原則と同じ)。
5.2 → 5.3 の変更
0. 依存バージョンの更新(composer.json)
プラグインの require-dev(または require)の baser-core を 5.3 系に上げる。
"require-dev": {
"baserproject/baser-core": "5.3.x"
}
- 上げた後は
composer update baserproject/baser-core --with-dependencies(プラグインの vendor を持つ場合)で 5.3 系 + CakePHP 5.2.x を取り込む。
- PHP 要件は 8.1 互換を維持するなら
"php": ">=8.1" のまま(8.5 の非推奨対応は php-migration の ❌ 印=据え置き方針に従う)。
テスト基盤(standalone プラグイン test harness)
自前 vendor/ と tests/TestApp/ を持つ「単体実行型」のプラグインを 5.3 で動かすと、ここが最も詰まる。コアプラグイン(親ディレクトリのアプリ経由でテスト)の場合はアプリ側 tests/bootstrap.php が同等の処理をしているので、本節はアプリ側を参照する。
T-1. CakePHP の二重ロード(vendor 混在)で validateUnique(): Argument #2 ($options) not passed
composer test が ルートの phpunit(../../vendor/bin/phpunit)を起動する一方、プラグインの tests/bootstrap.php が ROOT/vendor/autoload.php(=プラグイン自前 vendor)を読み込むと、2つの異なる CakePHP バージョンが同時にロードされる。Composer のオートローダは register(prepend=true) で後勝ちになるため、起動時に読まれたクラス(例 Cake\ORM\Table 5.0系)と実行時に初めて読まれるクラス(例 Cake\Validation\Validator 5.2系)が混在し、validateUnique() 等でシグネチャ不一致の ArgumentCountError が出る。
T-2. plugins.php の null → [](CakePHP 5.2 の PluginCollection::create が array 必須)
tests/TestApp/config/plugins.php の値が null だと、BaseApplication::bootstrap() → PluginCollection::addFromConfig() → create($name, null) で TypeError: …create(): Argument #2 ($config) must be of type array, null given になる(5.1 までは許容)。
return ['BaserCore' => null, ...]; → return ['BaserCore' => []];
- 関連:
cakephp-migration 1-4 にも同記述あり。
T-3. プラグインの読み込みは BcApp.testAppPluginsToLoad を使う(plugins.php は BaserCore のみ)
baser-core 5.2+ の BcTestCase::loadTestAppPlugins() は Configure::read('BcApp.testAppPluginsToLoad') を読み、未 bootstrap が無くなるまでスナップショット単位で(ガード付きで)各プラグインを bootstrap する。
- plugins.php には
BaserCore のみを記載し、コンテンツ系プラグイン(BcBlog / BcCustomContent / BcSearchIndex 等)と対象プラグイン自身は testAppPluginsToLoad に列挙する。本体アプリ(config/plugins.php は BaserCore + 基盤のみ、tests/bootstrap.php で Plugin::loaded() から testAppPluginsToLoad を生成)と同方式。
Configure::write('BcApp.testAppPluginsToLoad', [
'BcMcp', // 対象プラグイン自身
'BcSearchIndex', 'BcBlog', 'BcCustomContent', // 依存コンテンツプラグイン
]);
T-4. 統合テストで Plugin named 'X' is already loaded(二重ロード例外)
T-3 と必ずセットで守る。プラグインを plugins.php と testAppPluginsToLoad の両方に書くと、統合テストがリクエスト毎に生成する per-request app が plugins.php を再び addFromConfig し、既に読み込み済みのプラグインを再 add して CakeException: Plugin named 'X' is already loaded(CakePHP 5.2、cakephp-migration 2-7)になる。500 → さらに後述 T-6 でマスクされ「原因不明の 500」に見える。
- 修正:
BaserCore は plugins.php、その他は testAppPluginsToLoad に分離して重複させない。
T-5. 同梱サブプラグインのクラスが not found(例 Class "BcCcFile\Utility\BcCcFileUtil" not found)
BcCcFile は bc-custom-content に同梱されたサブプラグイン(vendor/baserproject/bc-custom-content/plugins/BcCcFile/)で、BcCustomContentPlugin::bootstrap() → loadPlugin() が App.paths.plugins を追加し BcUtil::includePluginClass() で動的に PSR-4 登録する。composer の autoload には現れないため、親プラグインが bootstrap されないとクラス解決できない。
- 修正: 親プラグイン(
BcCustomContent)を T-3 の testAppPluginsToLoad に入れて bootstrap させる。サブプラグインの namespace を composer.json に手書き登録する必要はない。
T-6. テストの真因が MissingTemplateException: Error/error500.php でマスクされる
standalone の test harness には templates/Error/error500.php が無いため、統合テストで発生した 500 が「エラーページのレンダリング失敗」に化けて本当の例外が見えない(debug の有無に関わらず baserCMS はエラーテンプレートを描画しようとする)。
baserCMS 固有の非推奨
B-1. BcFile のコンストラクタ/delete() のパス指定
logs/error.log に下記が出る(6.0.0 で必須化=今は警告)。
BcFile では、コンストラクタでパスの指定をしないのは非推奨です。パスの指定行うようにしてください。この要件はバージョン 6.0.0 で必須となります。
BcFile::delete() では、第一引数にパスを指定するのは非推奨です。パスの指定はコンストラクタで行ってください。この要件はバージョン 6.0.0 で必須となります。
TreeBehavior + Content フィクスチャ
C-1. Cannot set a node's parent as itself.(Content 保存テスト)
CakePHP 5.2 の TreeBehavior は「親に自分自身」を保存時に例外化する(cakephp-migration 2-11 と同系の厳格化)。baserCMS のテストシナリオで顕在化しやすい典型:
日付・時刻依存テスト
D-1. アップロードパス等の年月ハードコード
ファイルアップロード先は実行時の年月(date('Y/m'))でディレクトリが切られるため、'2025/09/...' のように固定値でアサートしていると月替わりで必ず失敗する。
$this->assertEquals('2025/09/00000001_image_field.png', $result['image_field'] ?? '');
$this->assertEquals(date('Y/m') . '/00000001_image_field.png', $result['image_field'] ?? '');
- 時刻比較全般の注意は
cakephp-migration 3-4(実 time() を使わない)も参照。
調査の進め方(チェックリスト)
- テスト実行・全失敗の集計は
basercms-unittest スキル。まず vendor 混在(T-1) を疑い、トレースに 2 つの cakephp パスが無いか確認。
PluginCollection::create(): … null given → T-2、Plugin named 'X' is already loaded → T-3/T-4。
Class "…\…" not found(サブプラグイン)→ T-5。
- 統合テストの原因不明 500 → T-6 で真因を可視化してから分類。
- フレームワーク/PHP 起因は
cakephp-migration / php-migration の該当節へ。baserCMS 固有非推奨は B-1、TreeBehavior は C-1、日付依存は D-1。
- 修正のたびに
php -l → --filter 単体確認 → 仕上げに全テスト再実行で件数改善と新規回帰を確認。
メモ: 新しくスキルファイルを .claude/skills/ に追加・更新した直後は、現在の Claude Code セッションには反映されない(セッション起動時に discover される)。Claude Code を再起動すると /basercms-plugin-5x-update として呼べるようになる。