Skip to content

fix: プラグイン/Customize 直下のバンドルでも Entity の redeclare fatal を防ぐ (auto_mapping の二重登録をコンパイル時に除去) - #6982

Merged
nanasess merged 5 commits into
EC-CUBE:4.4from
nanasess:fix/6979-strip-auto-mapped-entity-paths
Jul 31, 2026

Conversation

@nanasess

@nanasess nanasess commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

概要(Overview・Refs Issue)

Entity の if (!class_exists()) ガードを全廃した #6895 以降、Proxy 生成後に全リクエスト・全コンソールコマンドが redeclare fatal で失敗する問題を修正します。

PHP Fatal error: Cannot redeclare class Eccube\Entity\Customer,
because the name is already in use in src/Eccube/Entity/Customer.php on line 49

fixes #6979 / #6963 を置き換えます#6963 の方式では塞げない経路が #6979 で報告されたため、方式を変更して出し直したものです。#6963 はクローズします)

refs #6979, #6963, #6895, #6891, #5844

原因

doctrine.orm.auto_mapping が、EC-CUBE が明示登録しているのと同じ Entity ディレクトリを素の AttributeDriver にも登録することが原因です。

  1. Kernel::addEntityExtensionPass()src/Eccube/Entity / app/Customize/Entity / app/Plugin/<Code>/EntityTraitProxyAttributeDriver で登録する。こちらは refactor: Entity の if(!class_exists()) ガードを全廃 (refs #6891, #5844) #6895 の追随修正(77defa74ca)で「宣言済みの Entity は再 require_once しない」ようになっている。
  2. 一方 doctrine-bundle は、バンドルクラスが置かれたディレクトリ + /Entity を auto_mapping の対象として検出する(DoctrineExtension::detectMetadataDriver() / getMappingDriverBundleConfigDefaults())。
// DoctrineExtension::getMappingDriverBundleConfigDefaults()
$bundleClassDir = dirname($bundle->getFileName());
...
$bundleConfig['dir'] = $bundleClassDir . '/' . $this->getMappingObjectDefaultName();  // 'Entity'
  1. さらに registerMappingDrivers()同じドライバ型のバンドルを 1 つの Definition に集約する。
$mappingDriverDef = new Definition($this->getMetadataDriverClass($driverType), [
    array_values($driverPaths),      // 全バンドルのパスが 1 インスタンスに入る
]);
foreach ($driverPaths as $prefix => $driverPath) {
    $chainDriverDef->addMethodCall('addDriver', [new Reference($mappingService), $prefix]);
}
  1. 素のドライバは ColocatedMappingDriver::getAllClassNames() で Entity ソースを無条件に require_once する。Kernel::loadEntityProxies() が先に app/proxy/entity の Proxy を読み込んでいるため、二重宣言になる。ガード全廃前は各 Entity の if (!class_exists()) がこれを吸収していた。

MappingDriverChain は名前空間ごとに 1 ドライバしか保持しないため、EC-CUBE の明示登録で上書きされたように見えます。しかし getAllClassNames()ドライバインスタンス単位で走査するため、素のドライバが別の名前空間(第三者バンドル)でチェーンに残っていると、そのタイミングで自身の全パスを require_once して同じ fatal になります。

// MappingDriverChain::getAllClassNames()
foreach ($this->drivers as $namespace => $driver) {
    $oid = spl_object_hash($driver);
    if (! isset($driverClasses[$oid])) {
        $driverClasses[$oid] = $driver->getAllClassNames();   // ← ここで全パスを require_once
    }
    ...
}

実際のスタックトレース(PostgreSQL / APP_ENV=prod):

#0 doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php(188): require_once()
#1 MappingDriverChain.php(104): Doctrine\ORM\Mapping\Driver\AttributeDriver->getAllClassNames()
#2 doctrine-bundle/src/Mapping/MappingDriver.php(25): MappingDriverChain->getAllClassNames()
#3 AbstractClassMetadataFactory.php(95): MappingDriver->getAllClassNames()
#4 symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php(60): getAllMetadata()
...
#9 src/Eccube/Kernel.php(137): Symfony\Component\HttpKernel\Kernel->boot()

方針(Policy)

Kernel::addEntityExtensionPass() が明示登録した Entity ディレクトリを、コンパイル時に auto_mapping 側のドライバの paths から取り除きますStripAutoMappedEntityPathsPass)。

  • 対象は doctrine.orm.<em>_attribute_metadata_driver(および .inner)のみ。第三者バンドルのパスはそのまま残るため、プラグインが依存するバンドル(league/oauth2-server-bundle 等)の Entity は従来どおりマッピングされます。
  • 除去対象のパスは addEntityExtensionPass() が登録したものをそのまま pass に渡すため、明示登録とパス一覧が二重管理になりません
  • 全パスが取り除かれた場合は、paths が空のまま getAllClassNames() を呼ばれると MappingException::pathRequiredForDriver になるため、MappingDriverChainaddDriver() 呼び出しからも外します。

バンドル名を列挙する方式を採らなかった理由

当初 #6963 では doctrine.orm.mappings: { EccubeBundle: false } でコア分だけ無効化していましたが、#6979app/Plugin/<Code>/app/Customize/ の直下にバンドルクラスを置いた構成では同じ fatal が残ることが報告されました(@kurozumi さんによる詳細な調査・再現手順に感謝します)。

PHP Fatal error: Cannot declare class Plugin\Foo\Entity\Bar,
because the name is already in use in app/Plugin/Foo/Entity/Bar.php on line 6

サードパーティ製プラグインが持ち込むバンドル名は事前に知ることができないため、列挙方式ではこの経路を塞げません。バンドル名に依存せず、EC-CUBE が明示登録しているディレクトリという確実な情報でパスを取り除く方式に変更しました。

なお #6979 で言及されているとおり、TraitProxyAttributeDriver 側で吸収する案は成立しません。実際に走査して require_once しているのは doctrine-bundle が生成する素の AttributeDriver であり、受け側では届かないためです。

実装に関する補足(Appendix)

テスト(Test)

ローカル(PHP 8.5 / SQLite / APP_ENV=prod および dev)で、#6979 の再現手順どおりの構成を作って確認しました。

再現用の構成:

  • 第三者バンドル相当: app/Plugin/ExtraBundle/Lib/ExtraLibBundle.php + Lib/Entity/ExtraThing.php(prefix が Plugin\ExtraBundle\Lib\Entity になり明示登録の対象外=チェーンに残る)
  • ルート直下バンドル: app/Plugin/Foo/FooBundle.php + Entity/Bar.php
  • Customize 版: app/Customize/CustomizeBundle.php + Entity/MyThing.php
  • Proxy: app/proxy/entity/ 配下に同一 FQCN を配置(eccube:generate:proxies 相当)
# 構成 修正前 本 PR 適用後
1 第三者バンドル + コア Proxy Cannot redeclare class Eccube\Entity\Customer OK
2 上記 + app/Plugin/Foo/FooBundle.php + Proxy Cannot redeclare class Plugin\Foo\Entity\Bar#6963 適用時) OK
3 上記 + app/Customize/CustomizeBundle.php + Proxy Cannot redeclare class Customize\Entity\MyThing#6963 適用時) OK
4 素の構成(第三者バンドルなし) OK OK
  • bin/console cache:warmupprod / dev とも成功bin/console eccube:generate:proxies も正常終了。
  • bin/console doctrine:mapping:info:
    • 素の構成: 72 entities(修正前後で同数。マッピングの増減なし)
    • 上記フィクスチャ併存時: 75 entitiesPlugin\ExtraBundle\Lib\Entity\ExtraThing(auto_mapping 経由)・Plugin\Foo\Entity\BarCustomize\Entity\MyThing がいずれも [OK]
  • 追加テスト
    • tests/Eccube/Tests/DependencyInjection/Compiler/StripAutoMappedEntityPathsPassTest.php(新規・DB 非依存)— doctrine-bundle が生成するコンテナ構造を模し、明示登録済みパスだけが除去されること / 第三者バンドルのパスが残ること / 全除去時にチェーンから外れること / パラメータ表記の解決 / 無関係なドライバ定義を変更しないこと を検証
    • tests/Eccube/Tests/Doctrine/ORM/Mapping/EccubeEntityMetadataDriverTest.php(新規)— コンパイル済みコンテナ上で、明示登録した全ディレクトリ(コア / Customize / 各プラグイン)を担当するドライバが TraitProxyAttributeDriver だけであることを固定する回帰テスト
  • CI ゲート: phpstan analyse src = 本 PR 由来のエラーなし(既存 15 件から増減なし)、php-cs-fixer --dry-run = 0 件、rector --dry-run = 差分なし(指摘は適用済み)、phpunit tests/Eccube/Tests/Doctrine/ORM/Mapping tests/Eccube/Tests/DependencyInjection/Compiler/StripAutoMappedEntityPathsPassTest.php = OK(7 tests)

相談(Discussion)

  • 同種の問題は「コア Entity または自前 Entity を Proxy 生成するプラグイン」+「Entity を持つ第三者バンドル」の組み合わせで発生します。プラグインテストのマトリクスに api プラグイン導入時の起動確認を含めるべきか、ご意見をいただけると助かります。
  • 現状 Bundle クラスの置き場所は規約で縛られていません。今回の修正はどこに置かれても効きますが、eccube:plugin:generate のスケルトンや開発ドキュメントで推奨配置を示す価値はあるかもしれません。

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

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

レビュワー確認項目

  • 動作確認
  • コードレビュー
  • E2E/Unit テスト確認(テストの追加・変更が必要かどうか)
  • 互換性が保持されているか
  • セキュリティ上の問題がないか

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 改善
    • Doctrine の自動マッピングから、EC-CUBE が明示的に登録した Entity ディレクトリに対応するパスを除外し、重複による不整合や致命的エラーの発生を抑制しました。
  • テスト
    • パス除外・ドライバ維持/削除・パラメータ解決の確認に加え、ルートレベルのバンドルと Proxy が共存するケースでもマッピングが正しく解決されることを回帰テストで検証しました。

doctrine.orm.auto_mapping は、バンドルクラスが置かれたディレクトリの Entity/ を
検出して素の AttributeDriver に登録する (DoctrineExtension::detectMetadataDriver)。
このとき同じドライバ型のバンドルは 1 つの AttributeDriver インスタンスに集約されるため
(DoctrineExtension::registerMappingDrivers)、Kernel::addEntityExtensionPass が
TraitProxyAttributeDriver で明示登録しているディレクトリも素のドライバに入り込む。

素のドライバは ColocatedMappingDriver::getAllClassNames() で Entity ソースを
無条件に require_once するため、Kernel::loadEntityProxies() が app/proxy/entity の
Proxy を先にロードした状態では "Cannot redeclare class" で fatal になる
(Entity の if (!class_exists()) ガード全廃前は、そのガードが吸収していた)。

MappingDriverChain は名前空間ごとに 1 ドライバしか保持しないため、EC-CUBE の
明示登録で上書きされたように見えるが、素のドライバが別の名前空間 (第三者バンドル)
でチェーンに残っていると、その getAllClassNames() が自身の全パスを走査して
同じ fatal を引き起こす。

StripAutoMappedEntityPathsPass を追加し、明示登録済みのディレクトリを素の
AttributeDriver の paths から取り除く。全パスが取り除かれた場合は paths 空で
getAllClassNames() が例外になるため、MappingDriverChain からも外す。

バンドル名を列挙する方式 (doctrine.orm.mappings.<Bundle>: false) では、
サードパーティ製プラグインが持ち込むバンドル名を事前に知ることができず、
app/Plugin/<Code> や app/Customize の直下にバンドルクラスを置いた構成を
塞げないため、パスを動的に取り除く方式とした。

refs EC-CUBE#6979, EC-CUBE#6963, EC-CUBE#6895, EC-CUBE#6891, EC-CUBE#5844

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 44d826f0-d91e-4514-bfdf-2a04499683dc

📥 Commits

Reviewing files that changed from the base of the PR and between 2e21149 and 72ef3bc.

📒 Files selected for processing (1)
  • tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php

📝 Walkthrough

Walkthrough

Doctrine の auto-mapping 用 AttributeDriver から明示登録済み Entity パスを除外するコンパイラパスを追加し、Kernel に登録した。パス除外、ドライバ構成、Kernel 起動後のメタデータ解決を検証する回帰テストも追加した。

Changes

Entity パスマッピング制御

Layer / File(s) Summary
Auto-mapping パス除外処理
src/Eccube/DependencyInjection/Compiler/StripAutoMappedEntityPathsPass.php
対象 AttributeDriver のパスを解決し、明示登録済みパスを除外する。残存パスがない場合は MappingDriverChain からドライバを削除する。
Kernel へのコンパイラパス統合
src/Eccube/Kernel.php
EC-CUBE と Customize の明示マッピング対象パスを収集し、コンパイラパスを指定優先度で登録する。
ドライバ構成の回帰検証
tests/Eccube/Tests/DependencyInjection/Compiler/StripAutoMappedEntityPathsPassTest.php, tests/Eccube/Tests/Doctrine/ORM/Mapping/EccubeEntityMetadataDriverTest.php
パス除外、チェーン維持・削除、プレースホルダ解決、無関係なドライバの非変更、実際のメタデータドライバ構成を検証する。
Kernel 起動回帰検証
tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php, tests/Fixtures/CustomizeRootBundle/*
テスト用バンドル、Entity、Proxy を配置し、Kernel 起動後のメタデータ解決を検証する。

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

Possibly related issues

Possibly related PRs

  • EC-CUBE/ec-cube#6895 — Doctrine の Entity マッピングおよび auto-mapping のクラス収集処理に関連する。
  • EC-CUBE/ec-cube#6963 — Doctrine の auto-mapping と明示マッピングによる Entity パス競合を扱う。

Suggested labels: bug

Suggested reviewers: dotani1111, ttokoro20240902

Sequence Diagram(s)

sequenceDiagram
  participant Kernel
  participant ContainerBuilder
  participant StripAutoMappedEntityPathsPass
  participant MappingDriverChain
  Kernel->>ContainerBuilder: 明示 Entity パスとコンパイラパスを登録
  ContainerBuilder->>StripAutoMappedEntityPathsPass: process()
  StripAutoMappedEntityPathsPass->>MappingDriverChain: auto-mapping ドライバのパスを更新
  StripAutoMappedEntityPathsPass->>MappingDriverChain: 空のドライバ参照を除去
Loading

Poem

ぴょんと跳ねれば重複パス、
auto-mapping から消えていく。
明示の道は一本に、
テストも軽やか耳ぴくり。

🚥 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 変更内容の主旨である、Customize/プラグイン配下の Entity の二重登録による redeclare fatal 防止を的確に表しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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.

@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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@src/Eccube/DependencyInjection/Compiler/StripAutoMappedEntityPathsPass.php`:
- Around line 86-89: 型宣言のない無名関数を更新してください。array_filter のコールバックである無名関数の $path
引数に適切な型を付け、戻り値を bool と明示してください。また、同じファイルの 135-145
行付近にある無名関数にも、各引数と戻り値の型宣言を追加してください。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f0295be-e311-48d2-b503-61f1148e1e5c

📥 Commits

Reviewing files that changed from the base of the PR and between 89dec55 and 6d1324d.

📒 Files selected for processing (4)
  • src/Eccube/DependencyInjection/Compiler/StripAutoMappedEntityPathsPass.php
  • src/Eccube/Kernel.php
  • tests/Eccube/Tests/DependencyInjection/Compiler/StripAutoMappedEntityPathsPassTest.php
  • tests/Eccube/Tests/Doctrine/ORM/Mapping/EccubeEntityMetadataDriverTest.php

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.93548% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.25%. Comparing base (89dec55) to head (72ef3bc).

Files with missing lines Patch % Lines
...ection/Compiler/StripAutoMappedEntityPathsPass.php 90.56% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              4.4    #6982      +/-   ##
==========================================
- Coverage   77.25%   77.25%   -0.01%     
==========================================
  Files         547      548       +1     
  Lines       27163    27225      +62     
==========================================
+ Hits        20985    21032      +47     
- Misses       6178     6193      +15     
Flag Coverage Δ
Unit 77.25% <91.93%> (-0.01%) ⬇️

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.

@kurozumi

Copy link
Copy Markdown
Contributor

#6979 の報告者です。迅速な対応ありがとうございます。方式の変更まで含めて対応いただき助かりました。

手元の再現環境(#6979 で使ったもの)に本 PR(6d1324d776)を適用して確認しましたので、結果を共有します。報告した3ケースはいずれも解消していました。

検証結果

PHP 8.2.27 / SQLite / doctrine-bundle 2.18.2 / doctrine/orm 3.6.2

# 構成 結果
1 コア + Plugin\Foo + Customize の Proxy 全部入り(prod OK
2 同上(dev OK
3 第三者バンドルなし + ルート直下バンドルあり OK / 74 entities
4 完全に素の構成 OK / 73 entities
5 素の構成 + コア Proxy OK / 73 entities
6 素の構成 + 第三者バンドル + コア Proxy(#6963 のケース) OK / 74 entities
7 同一プラグイン内に「除去対象」と「残す対象」が同居 OK / 両方マッピング
8 プロジェクトをシンボリックリンク経由で参照してビルド OK

追加された StripAutoMappedEntityPathsPassTest も手元で green でした(5 tests / 7 assertions)。

7 について

一番壊れやすいと思ったので、同一プラグイン内に除去対象と非対象を同居させて試しました。

app/Plugin/Foo/FooBundle.php          + app/Plugin/Foo/Entity/Bar.php          … 明示登録あり(除去対象)
app/Plugin/Foo/Sub/SubBundle.php      + app/Plugin/Foo/Sub/Entity/SubThing.php … 明示登録なし(残すべき)

共有された 1 つの AttributeDriver インスタンスから前者のパスだけを抜く形になりますが、doctrine:mapping:infoPlugin\Foo\Entity\BarPlugin\Foo\Sub\Entity\SubThing の両方が [OK] になることを確認しました。

8 について

明示登録側は %kernel.project_dir%/... のパラメータ表記、doctrine-bundle 側はリフレクション由来の絶対パスで表記が異なるため、シンボリックリンク配下のデプロイで一致しなくなる可能性を気にしていました。resolvePath() が両方を realpath() に通しているため問題ありませんでした。ここが単純な文字列比較だと、symlink 運用の環境で静かに効かなくなるところだと思います。

気になった点

いずれも本 PR で対応が必要とは考えていません。記録として残しておきます。

1. 第三者バンドルが自前の mappings で同じディレクトリを指した場合

本 PR は「EC-CUBE が明示登録したパス」を除去する方式なので、逆にサードパーティ側が doctrine.orm.mappingsapp/Plugin/<Code>/Entity を直接指定してきた場合は対象外になります。

ただ、そのような設定を書く動機が見当たらない(自分のバンドルの Entity ではなく他所のディレクトリをわざわざ指定することになる)ため、修正は不要だと思います。念のため挙げただけです。

2. 根本原因は残る

「同一 FQCN のファイルが 2 つ存在し、どちらが読まれるかで結果が変わる」という Proxy 方式そのものは変わっていないため、require_once する経路を 1 つずつ塞ぐ形が続くことになります(#6895 で 4 箇所 → #6963 で 5 箇所目 → 本 PR でその一般化)。

とはいえ、これは本 PR が背負う話ではないと思います。バンドル名に依存しない形にしていただいたことで、少なくとも auto_mapping 由来の系統はまとめて塞げていると理解しています。

Discussion について

プラグインテストのマトリクスに api プラグイン導入時の起動確認を含めるべきか

今回の件は「Entity を持つ第三者バンドルが入って初めて露出する」性質なので、api プラグイン(league/oauth2-server-bundle)を入れた状態での起動確認が入っていれば、#6895 マージ前に気づけた可能性が高いと思います。個人的には価値があると感じます。

eccube:plugin:generate のスケルトンや開発ドキュメントで推奨配置を示す価値はあるかもしれません

本 PR でどこに置かれても動くようになったので必須ではないと思いますが、eccube-api4Bundle/ApiBundle.php という配置を選んでいる実績もあるので、ドキュメントに一言あると迷わなくて済みそうです。


検証環境はそのまま残してあります。追加で確認したい構成があればお知らせください。

issue EC-CUBE#6979 の再現構成を実際に配置して Kernel を boot し、メタデータ解決まで
到達することを検証する。再現に必要な 3 要素 (対照実験 A/B で確定済み) を fixture で組む:

1. Entity を持つ第三者バンドル (prefix が明示登録の対象外なので素の AttributeDriver が
   MappingDriverChain に残る)
2. app/Customize 直下に置かれた Bundle (auto_mapping が app/Customize/Entity を
   素のドライバの paths に入れる)
3. 同一 FQCN の Proxy (Kernel::loadEntityProxies が先にロードする)

既存の StripAutoMappedEntityPathsPassTest は ContainerBuilder を組み立てるコンパイル時の
単体テスト、EccubeEntityMetadataDriverTest は素の構成でのドライバ種別の検証であり、
いずれも再現構成そのものは組み立てていなかった。

StripAutoMappedEntityPathsPass を一時的に無効化して
"Cannot redeclare class Customize\Entity\StripAutoMappedTarget" の fatal を再現し、
パスが有効な状態では green になることを両方向で確認済み。

Co-Authored-By: Claude Opus 5 (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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php (1)

106-108: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

メタデータ変換コールバックに型宣言を追加してください。

$metadata 引数と戻り値が無型です。Doctrine ORMの実際の要素型を確認したうえで、引数型と string 戻り値を宣言してください。

-            static fn ($metadata) => $metadata->getName(),
+            static fn (ClassMetadata $metadata): string => $metadata->getName(),

As per coding guidelines: PHPの引数と戻り値には型宣言を付けます。

🤖 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 `@tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php`
around lines 106 - 108, メタデータ変換コールバックにDoctrine
ORMの実際のメタデータ要素型を引数型として指定し、戻り値をstringに宣言してください。対象はgetAllMetadata()をmapするstaticクロージャで、既存のgetName()による変換結果と処理フローは維持してください。

Source: Coding guidelines

🤖 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.

Inline comments:
In `@tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php`:
- Around line 67-89:
テスト用ファイルが実プロジェクトを上書き・削除しないよう、setUpのmirror()/copy()とtearDown()を隔離された一時プロジェクトまたはサブプロセス上で実行する構成に変更してください。既存のapp/Customize、app/proxy/entity配下を使う場合は、CustomizeRootBundle.php、StripAutoMappedTarget.php、Lib、bundles.php、proxyFile()の既存内容を事前に退避し、正常終了時だけでなくfatal終了後も親プロセスで復元できるようにしてください。

In `@tests/Fixtures/CustomizeRootBundle/CustomizeRootBundle.php`:
- Around line 1-3: tests/Fixtures/CustomizeRootBundle/CustomizeRootBundle.php
(1-3), tests/Fixtures/CustomizeRootBundle/Entity/StripAutoMappedTarget.php
(1-3), tests/Fixtures/CustomizeRootBundle/Lib/CustomizeLibBundle.php (1-3),
tests/Fixtures/CustomizeRootBundle/Lib/Entity/StripAutoMappedExtra.php (1-3),
and tests/Fixtures/CustomizeRootBundle/Resource/config/bundles.php (1-3) should
each place declare(strict_types=1); immediately after the PHP opening tag and
before the license comment, preserving the existing file contents otherwise.

---

Nitpick comments:
In `@tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php`:
- Around line 106-108: メタデータ変換コールバックにDoctrine
ORMの実際のメタデータ要素型を引数型として指定し、戻り値をstringに宣言してください。対象はgetAllMetadata()をmapするstaticクロージャで、既存のgetName()による変換結果と処理フローは維持してください。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 38fecdad-bdf0-4090-a829-ce5b12fd0983

📥 Commits

Reviewing files that changed from the base of the PR and between 6d1324d and de67cc8.

📒 Files selected for processing (6)
  • tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php
  • tests/Fixtures/CustomizeRootBundle/CustomizeRootBundle.php
  • tests/Fixtures/CustomizeRootBundle/Entity/StripAutoMappedTarget.php
  • tests/Fixtures/CustomizeRootBundle/Lib/CustomizeLibBundle.php
  • tests/Fixtures/CustomizeRootBundle/Lib/Entity/StripAutoMappedExtra.php
  • tests/Fixtures/CustomizeRootBundle/Resource/config/bundles.php

Comment thread tests/Eccube/Tests/Doctrine/ORM/Mapping/AutoMappedEntityPathsBootTest.php Outdated
Comment thread tests/Fixtures/CustomizeRootBundle/CustomizeRootBundle.php
- AutoMappedEntityPathsBootTest: 文字列 FQCN を ::class に変更
  (StringClassNameToClassConstantRector)。fixture は app/Customize へ配置して初めて
  実体を持つが、::class は静的解決のためロードは発生しない
- fixture の Entity 2 本: #[ORM\Column(type: 'integer')] を Types::INTEGER に変更
  (AttributeKeyToClassConstFetchRector)

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

Copy link
Copy Markdown
Contributor Author

@kurozumi de67cc8 にて回帰テストを追加しました。 eccube-api4 プラグインを入れた状態での起動確認は #6872 でカバーされる想定です。

検証のご協力ありがとうございました!

nanasess and others added 2 commits July 28, 2026 15:49
CodeRabbit の指摘 2 件に対応する。

1. テスト用ファイルを実プロジェクトから隔離 (Major)
   - 検証を bin/console doctrine:mapping:info のサブプロセス実行に変更した。
     回帰時の redeclare は PHP の fatal のため、同一プロセスで起動すると tearDown が
     実行されず fixture が残っていた。子プロセスに閉じ込めることで、終了コードによる
     通常のアサーション失敗として報告され、後始末も確実に実行される
   - 実プロジェクトに同名のファイル・ディレクトリがある場合に備え、setUp で退避し
     tearDown で復元する
   - Proxy の配置で作成したディレクトリは、空になった場合のみ取り除く
     (実運用で生成された Proxy を巻き込まないため)

2. fixture 5 ファイルに declare(strict_types=1) を追加 (Minor)

Pass を一時的に無効化した状態で、子プロセスの fatal が
"Failed asserting that 255 is identical to 0." として報告され、
fixture の後始末も走ることを確認済み。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
前コミットで導入したサブプロセス検証が、コンテナを再生成させるために
var/cache/test を削除していた。PHPUnit は 1 プロセスで全テストを実行するため、
既にコンテナを起動済みの他テストが遅延ロードするサービス定義ファイル
(var/cache/test/Container*/get*.php) まで消え、unit-test が 865 errors で失敗していた。

サブプロセスを専用の APP_ENV (test_auto_mapped) で実行し、
var/cache/test_auto_mapped だけを作成・削除するよう変更する。
Kernel::configureContainer は packages/<env> を is_dir で判定するため、
専用環境名でも共通設定だけで起動できる (doctrine:mapping:info で動作確認済み)。

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

@ttokoro20240902 ttokoro20240902 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@nanasess
nanasess merged commit 21e4663 into EC-CUBE:4.4 Jul 31, 2026
115 checks passed
@nanasess
nanasess deleted the fix/6979-strip-auto-mapped-entity-paths branch July 31, 2026 01:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants