Skip to content

fix: マスタEntityをtraitで拡張するとマスタデータ管理から消える問題を修正 (#5400 #6273)#6892

Open
nanasess wants to merge 2 commits into
EC-CUBE:4.4from
nanasess:issue-5400
Open

fix: マスタEntityをtraitで拡張するとマスタデータ管理から消える問題を修正 (#5400 #6273)#6892
nanasess wants to merge 2 commits into
EC-CUBE:4.4from
nanasess:issue-5400

Conversation

@nanasess

@nanasess nanasess commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

概要(Overview・Refs Issue)

Closes #5400
Closes #6273

(関連PR: #5401 / #6274)

Eccube\Entity\Master 配下のマスタ Entity をプラグインの trait で拡張すると、以下の 2 つの不具合が発生していました。

  1. マスタデータのEntityを拡張すると、マスタデータ管理ページでテーブルを選択できなくなる #5400: マスタデータ管理ページ (/admin/setting/system/masterdata) のプルダウンから、拡張したテーブルが消える。
  2. JobテーブルがTraitでカラム追加できない #6273: プラグインインストール時に schema:update が自動実行されず、trait で追加したカラムが作成されない (手動で bin/console doctrine:schema:update --force を実行すれば作成される)。

いずれも根本原因は同一で、Proxy パス解決を担う 2 つのドライバの getAllClassNames() が、Proxy パス生成時に basename($sourceFile) を用いて Entity/Master/ などのサブディレクトリ情報を落としていたためです。この結果 Entity/Master/DeviceType の Proxy が「存在しない」と誤判定され、メタデータ収集からエンティティが漏れていました。

方針(Policy)

実装に関する補足(Appendix)

  • 変更したコアファイルは 2 つのドライバのみです。
    • src/Eccube/Doctrine/ORM/Mapping/Driver/TraitProxyAttributeDriver.php
    • src/Eccube/Doctrine/ORM/Mapping/Driver/ReloadSafeAttributeDriver.php
  • str_replace() が置換しなかった場合 (Proxy ディレクトリ配下に写像されないパス) は Proxy 扱いしないよう $proxyFile !== $sourceFile のガードを追加しています。
  • 回帰テストを Codeception から Playwright へ移植しました。
    • codeception/_data/plugins/MasterEntityExtension-1.0.0/ (trait は annotation → PHP8 属性へ移植)
    • e2e/pages/master-data-manage.page.ts / e2e/models/plugins/master-entity-extension-local.ts
    • e2e/tests/plugin-extend.spec.tstest_master_entity_extension を追加
    • .github/workflows/plugin-test.ymlplugin-extend マトリクスに追加

テスト(Test)

  • vendor/bin/php-cs-fixer fix (PSR-12, 違反なし)

  • vendor/bin/phpstan analyse (level 6, エラーなし)

  • SQLite 環境で A/B 対照実測を実施し、因果を確認 (mtb_device_typeMasterEntityExtension プラグインで拡張):

    ドライバ eccube:plugin:install 後の mtb_device_type 結果
    修正版 id, name, sort_no, discriminator_type, notes notes が自動追加
    修正前 (basename) id, name, sort_no, discriminator_type ❌ カラム未追加 (JobテーブルがTraitでカラム追加できない #6273 再現)

    両ケースとも install 時の一時 Proxy は Master/ サブパスを保持して生成される (gen -> /tmp/proxy_xxx/src/Eccube/Entity/Master/DeviceType.php) ため、差分の唯一の要因はドライバの basename バグであることを確認済みです。

  • E2E (Playwright plugin-extend / test_master_entity_extension) は本 PR の CI で検証されます。

相談(Discussion)

マイナーバージョン互換性保持のための制限事項チェックリスト

  • 既存機能の仕様変更はありません
  • フックポイントの呼び出しタイミングの変更はありません
  • フックポイントのパラメータの削除・データ型の変更はありません
  • twigファイルに渡しているパラメータの削除・データ型の変更はありません
  • Serviceクラスの公開関数の、引数の削除・データ型の変更はありません
  • 入出力ファイル(CSVなど)のフォーマット変更はありません

レビュワー確認項目

  • 動作確認
  • コードレビュー
  • E2E/Unit テスト確認(テストの追加・変更が必要かどうか)
  • 互換性が保持されているか
  • セキュリティ上の問題がないか
    • 権限を超えた操作が可能にならないか
    • 不要なファイルアップロードがないか
    • 外部へ公開されるファイルや機能の追加ではないか
    • テンプレートでのエスケープ漏れがないか

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 新機能
    • マスターデータ管理画面で「mtb_device_type」の選択肢を表示・選択・保存できるようにしました。
    • 拡張機能のローカルプラグイン(テスト用)を追加しました。
  • バグ修正
    • 拡張データのプロキシ解決方法を見直し、サブディレクトリでも参照ずれが起きにくくしました。
  • テスト
    • 拡張機能のE2Eテストを追加し、対象実行範囲を更新しました。

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 84283f30-0df5-4aaf-9085-79c77f76c487

📥 Commits

Reviewing files that changed from the base of the PR and between 30976e7 and 3ddf609.

📒 Files selected for processing (1)
  • e2e/tests/plugin-extend.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • e2e/tests/plugin-extend.spec.ts

📝 Walkthrough

Walkthrough

DeviceType拡張プラグインを追加し、マスタデータ管理画面での選択・保存をE2Eで確認するテストを導入しました。あわせて、Trait Proxyのファイルパス解決をsourceFile基準に変更しています。

Changes

マスタエンティティ拡張プラグイン追加

Layer / File(s) Summary
プラグイン定義とEntity拡張
codeception/_data/plugins/MasterEntityExtension-1.0.0/Entity/DeviceTypeTrait.php, codeception/_data/plugins/MasterEntityExtension-1.0.0/composer.json
DeviceType拡張用のtraitとプラグインメタデータを追加し、notesカラムを定義。
E2E用ローカルモデルとページ操作
e2e/models/plugins/master-entity-extension-local.ts, e2e/pages/master-data-manage.page.ts
ローカルプラグイン起動と、マスタデータ画面での選択・保存操作を実装。
E2EテストとCI対象追加
e2e/tests/plugin-extend.spec.ts, .github/workflows/plugin-test.yml
新しいE2Eテストを追加し、plugin-extendの実行対象に含めた。

Trait Proxyパス解決ロジックの修正

Layer / File(s) Summary
Proxyパス解決の変更
src/Eccube/Doctrine/ORM/Mapping/Driver/ReloadSafeAttributeDriver.php, src/Eccube/Doctrine/ORM/Mapping/Driver/TraitProxyAttributeDriver.php
proxyFileの生成方法をsourceFileのパス構造を保つ方式へ変更し、存在確認の条件も更新。

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant plugin_extend_spec as plugin-extend.spec.ts
  participant MasterEntityExtensionLocal as MasterEntityExtensionLocal
  participant MasterDataManagePage as MasterDataManagePage
  participant PluginTestConfig as PluginTestConfig

  plugin_extend_spec->>MasterEntityExtensionLocal: start(page, db, config)
  MasterEntityExtensionLocal->>PluginTestConfig: traits設定を含むローカルプラグインを生成
  plugin_extend_spec->>MasterDataManagePage: go(page)
  plugin_extend_spec->>MasterDataManagePage: 選択肢が存在("mtb_device_type")
  MasterDataManagePage-->>plugin_extend_spec: boolean
  plugin_extend_spec->>MasterDataManagePage: 選択(label)
  plugin_extend_spec->>MasterDataManagePage: 保存()
  plugin_extend_spec->>MasterEntityExtensionLocal: plugin無効化/削除
Loading

Suggested labels: bug:Low

Suggested reviewers: dotani1111, saori-kakiuchi, ji-eunsoo

Poem

ぴょんと跳ねたよ、DeviceType 🐰
notes が増えて、道がひらく
選んで保存、ぴたりと確認
Proxy もすっきり、影が整う
ちいさな修正、でも嬉しい朝☀️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは主変更であるマスタEntityのtrait拡張時の表示不具合修正を簡潔に示しています。
Linked Issues check ✅ Passed trait拡張時の一覧消失と追加カラムのスキーマ反映に関わるドライバ修正および回帰テストが含まれています。
Out of Scope Changes check ✅ Passed 追加されたE2E基盤とプラグイン定義、テスト対象の拡張はすべて今回の不具合修正に直接関連しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Entity/Master 配下のマスタEntityをプラグインのtraitで拡張すると、
マスタデータ管理ページのプルダウンから該当テーブルが消え、さらに
プラグインインストール時のschema updateがカラムを自動追加しない問題を修正する。

原因は TraitProxyAttributeDriver / ReloadSafeAttributeDriver の
getAllClassNames() で、Proxyパス生成時に basename() を用いて
Entity/Master 等のサブディレクトリ情報を落としていたため。
$sourceFile のパス構造ごと proxies ディレクトリへ変換するよう修正した。

- 親ドライバ TraitProxyAttributeDriver: プルダウン表示 (EC-CUBE#5400)
- 子ドライバ ReloadSafeAttributeDriver: install時の自動schema update (EC-CUBE#6273)
  の両方を修正 (annotation時代の EC-CUBE#5401 + EC-CUBE#6274 を4.4で統合的に解決)

回帰テストを Codeception から Playwright へ移植:
- MasterEntityExtension プラグイン (テストデータ)
- MasterDataManagePage / MasterEntityExtensionLocal
- plugin-extend.spec.ts に test_master_entity_extension を追加
- plugin-test.yml の plugin-extend マトリクスに追加

Closes EC-CUBE#5400
Closes EC-CUBE#6273
Refs EC-CUBE#5401 EC-CUBE#6274

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Eccube/Doctrine/ORM/Mapping/Driver/ReloadSafeAttributeDriver.php (1)

94-108: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

プロキシパス解決ロジックの重複(TraitProxyAttributeDriverと同一)

ReloadSafeAttributeDriverTraitProxyAttributeDriverを継承しているにもかかわらず、$projectDir$this->trait_proxies_directoryの置換ロジック(Lines 94-108)が親クラスのgetAllClassNames()(TraitProxyAttributeDriver.php Lines 74-91)と完全に重複しています。今回のIssue #5400 / #6273修正が両ファイルに同時に手動反映されている点からも、将来同種の修正が片方だけに適用されて再度ズレるリスクがあります。

共通処理を親クラスのprotectedメソッド(例: resolveProxyFile(string $sourceFile, string $path): string)に切り出し、両ドライバから呼び出す形にすると保守性が向上します。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Eccube/Doctrine/ORM/Mapping/Driver/ReloadSafeAttributeDriver.php` around
lines 94 - 108, The proxy path resolution block in ReloadSafeAttributeDriver
duplicates the same logic already present in
TraitProxyAttributeDriver::getAllClassNames(), so extract the shared $projectDir
to $this->trait_proxies_directory replacement into a protected helper on the
parent class (for example, a resolveProxyFile-style method) and have both
drivers call it instead of keeping separate copies. Keep the existing
sourceFile/path handling and file_exists check behavior, but centralize the
transformation so future fixes for Issue `#5400` / `#6273` only need to be made in
one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/Eccube/Doctrine/ORM/Mapping/Driver/ReloadSafeAttributeDriver.php`:
- Around line 94-108: The proxy path resolution block in
ReloadSafeAttributeDriver duplicates the same logic already present in
TraitProxyAttributeDriver::getAllClassNames(), so extract the shared $projectDir
to $this->trait_proxies_directory replacement into a protected helper on the
parent class (for example, a resolveProxyFile-style method) and have both
drivers call it instead of keeping separate copies. Keep the existing
sourceFile/path handling and file_exists check behavior, but centralize the
transformation so future fixes for Issue `#5400` / `#6273` only need to be made in
one place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd05317e-d308-4f58-a7c8-6ccccf82a208

📥 Commits

Reviewing files that changed from the base of the PR and between a387a99 and a2ac39c.

📒 Files selected for processing (8)
  • .github/workflows/plugin-test.yml
  • codeception/_data/plugins/MasterEntityExtension-1.0.0/Entity/DeviceTypeTrait.php
  • codeception/_data/plugins/MasterEntityExtension-1.0.0/composer.json
  • e2e/models/plugins/master-entity-extension-local.ts
  • e2e/pages/master-data-manage.page.ts
  • e2e/tests/plugin-extend.spec.ts
  • src/Eccube/Doctrine/ORM/Mapping/Driver/ReloadSafeAttributeDriver.php
  • src/Eccube/Doctrine/ORM/Mapping/Driver/TraitProxyAttributeDriver.php

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.32%. Comparing base (a387a99) to head (3ddf609).

Additional details and impacted files
@@           Coverage Diff           @@
##              4.4    #6892   +/-   ##
=======================================
  Coverage   75.32%   75.32%           
=======================================
  Files         519      519           
  Lines       25483    25483           
=======================================
  Hits        19196    19196           
  Misses       6287     6287           
Flag Coverage Δ
Unit 75.32% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

test_master_entity_extension がマスタデータ管理画面へ遷移したまま
無効化() を呼び、プラグイン管理画面前提の i.fa-pause が見つからず
タイムアウトしていた (MySQL/PostgreSQL 両方で失敗)。
マスタデータ検証後に /store/plugin へ戻してから無効化・削除するよう修正。

なお選択・保存 (プルダウン検証の本丸) は両DBで成功しており、
失敗は後片付けのナビゲーションのみが原因。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants