feat: EC-CUBE 4.4への対応 - #67
Conversation
Symfony 7.4 / Doctrine ORM 3.0 / PHP 8.2+ へ対応し、コードを Recommend44 に改名。 - composer.json: name/code/version を Recommend44・4.4.0 へ - 全 namespace と @Recommend42 エイリアスを Recommend44 へ改名 - Entity: アノテーション → PHP 属性、型付きプロパティ化、型宣言追加 - Controller: @Route/@template → 属性、戻り値型明示、Sensio 依存除去 - Form: Length 制約を名前付き引数化、戻り値型追加 - PluginManager: 全メソッドに : void、暗黙 nullable 廃止 - Doctrine ORM 3.0: flush($entity) → flush() - phpunit.xml.dist: PHPUnit 11 形式(source/extensions)へ - CI: EC-CUBE 4.4 / PHP 8.2-8.4 マトリクス、deprecated action 更新 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sample-payment-plugin に倣い、EC-CUBE 4.4 + 本プラグインを Docker Compose で 立ち上げて PHPUnit を実行できるようにする。 - docker-compose.yml: ベース(ghcr.io/ec-cube/ec-cube-php:8.2-apache-4.4 + mailcatcher、SQLite、APP_ENV=test) - docker-compose.dev.yml: プラグインを tar 化し eccube:plugin:install で導入・有効化 (PharData は先頭 "./" エントリで失敗するため ./* を対象に tar 化) - docker-compose.mysql.yml / docker-compose.pgsql.yml: DB 切り替え用オーバーレイ - dockerbuild/grant_to_dbuser.sql: MySQL 用権限付与 - README: 起動・テスト実行手順を追記 あわせて 4.4 移行に伴うテスト期待値を修正: - Length バリデーションメッセージを Symfony 7.4 の文言へ更新 - getVisible() の boolean 型化に合わせ testRecommendDelete の期待値を false に 動作確認: EC-CUBE 4.4 + PHP 8.2 + SQLite で全 24 テスト パス(PHPUnit 11.5) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
APP_ENV=test ではセッションがモックストレージ(mock_file)になり、実ブラウザで ログイン状態を保持できなかった。またEC-CUBE 4.4(Symfony 7)の既定 cookie_samesite: none により HTTP では Cookie が拒否される。 - docker-compose.yml: APP_ENV を test → dev に変更(実セッションが必要なため) - dockerbuild/dev-framework.yaml: dev 環境の Cookie を cookie_secure:false / cookie_samesite:lax に上書き - docker-compose.dev.yml: 上記上書きファイルをマウント - README: PHPUnit は test 環境のキャッシュをクリアしてから実行するよう手順を更新 動作確認: ログイン POST → 302 → ダッシュボード 200(admin/password、HTTP localhost:8080) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sample-payment-plugin (#53) / eccube-api4 (#186) のモデルケースに倣い、 4.4 対応の保守性向上のため開発ツール設定を追加する。 - phpstan.neon.dist: PHPStan level 6(ルート、neon のため配置可) - Resource/rector.php: Symfony 7.4 / Doctrine ORM 3 への rector 設定 - Resource/.php-cs-fixer.dist.php: php-cs-fixer 設定 ※ rector.php / .php-cs-fixer.dist.php は .php のためルート直下に置くと 本体の Plugin\: サービス検出で 500 になる。Resource/ 配下が必須。 - .gitignore: /vendor/・composer.lock・.php-cs-fixer.cache を追加 - CLAUDE.md: 開発・テスト手順、アーキテクチャ、移行/配置の注意を記載 検証: 設定ファイル配置後も EC-CUBE 起動 OK(admin 302・ルート7件、500 なし) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
追加した静的解析ツールを実際に適用・対応した。 - rector process 適用: constructor promotion / readonly プロパティ / Elvis 演算子 / PHPDoc クラス名 import(TernaryToElvis / ClassPropertyAssignToConstructorPromotion / ReadOnlyProperty) - php-cs-fixer fix 適用: 戻り値型補完・ライセンスヘッダ https 化など 11 ファイル整形 - テストクラスのプロパティを nullable 化(EccubeTestCase が tearDown で全プロパティに null 代入するため、非 null 型だと TypeError になる) - phpstan-baseline.neon を追加し level 6 を green に(既存の型注釈不足/doctrine 偽陽性を grandfather、新規コードは level 6 で検査) 検証: PHPUnit 全 24 件パス / php-cs-fixer 差分ゼロ / phpstan [OK] No errors Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EC-CUBE 4.4 (Symfony 7.4) の symfony/cache が ext-redis <6.1 と衝突を宣言する一方、 CI ランナー(nanasess/setup-php) には古い php-redis 5.3.7 が apt で入るため本体の composer install が失敗していた。本プラグイン・本体テストは redis を使用しないため --ignore-platform-req=ext-redis で回避する。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
有効化したプラグインのルーティングはコンテナのコンパイル時に dtb_plugin から確定する。 phpunit プロセスでの遅延コンパイルに委ねると DB/タイミングにより有効プラグイン一覧を 取りこぼし、RouteNotFoundException で断続的に失敗していた(特に pgsql)。 - Run PHPUnit: cache:clear 後に cache:warmup を実行し、クリーンなプロセスで プラグイン込みのコンテナを確定的にビルドしてから phpunit を実行 - Setup Plugin: enable 後に cache:clear する順序へ(api4 #186 に合わせる) 検証: ローカル(EC-CUBE 4.4/test)で warmup 後にルート7件登録・phpunit 24件パス Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
baseline で grandfather していた 74 件の指摘を実際に解消し、phpstan-baseline.neon を撤廃。 - Repository に @extends AbstractRepository<RecommendProduct> を付与し、find()/findOneBy()/ QueryBuilder の戻り値型を確定(method.notFound 7・doctrine.dql 5・argument.type を解消) - 配列型に値型を明示(array<string, mixed> / RecommendProduct[] / int[] 等) - Service の $data を RecommendProduct 型に、PluginManager の @param を整理(null/不明引数除去) - Entity の visible を NOT NULL カラムに合わせ bool 型へ(doctrine.columnType 解消) - テストメソッドに : void、ヘルパ引数に型、プロパティに @var を付与 (EccubeTestCase の tearDown 対策で native 型化はせず @var + 無型に統一) - php-cs-fixer: phpdoc_to_property_type を無効化(テストプロパティの非null native 型化を防ぐ) - phpstan.neon.dist: includes(baseline) を削除 検証: phpstan No errors / php-cs-fixer 差分ゼロ / phpunit 24件パス(EC-CUBE 4.4・PHP 8.2) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
release.yml の packaging で、本番配布物に不要な開発用ファイルを削除してから tar 化する。 - docker-compose*.yml / dockerbuild/(Docker テスト環境) - CLAUDE.md / phpstan.neon.dist / Resource/rector.php / Resource/.php-cs-fixer.dist.php(開発ツール) 検証: 上記除外後も PharData 展開 OK・composer code=Recommend44 を確認(インストール可能) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
DB 種別に依存しない静的解析を、テストマトリクスとは別の static-analysis ジョブで SQLite・PHP 8.3 の1構成・3ツール直列で実行する(重複実行を避けつつ Checks を分離)。 - php-cs-fixer --dry-run --diff / rector process --dry-run(差分で失敗) - phpstan analyse(level 6)。phpstan は objectManagerLoader がカーネルを起動し EccubeExtension が dtb_plugin を読むため、本体インストール+DB+プラグイン有効化を前提とする Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- static-analysis: Setup EC-CUBE に eccube:fixtures:load を追加。プラグイン有効化時に PluginManager::createDataBlock() が DeviceType マスタを参照するため、未投入だと newBlock(null) で enable が TypeError になり失敗していた - static-analysis / テストマトリクスの対象 PHP に 8.5 を追加(サポート範囲 8.2-8.5 の上端) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
コンストラクタでのみ代入される typed プロパティのため readonly が適切。 rector の ReadOnlyPropertyRector が検出する差分(過去の rector→php-cs-fixer の 適用順で型付与後に readonly 化されず残っていた)を解消し、CI の rector --dry-run を green にする。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
eccube:plugin:enable 直後の 1 回の cache:clear では、プラグインのルーティング (おすすめ管理ページ plugin_recommend_list)と Nav メニューが確定せず、 docker compose up 直後の初回ロードで /admin/plugin/recommend が 404 になっていた。 enable とは別パスで cache:clear をもう一度実行すると確定するため、 docker-compose.dev.yml の entrypoint で cache:clear を 2 回流すようにした。 curl で docker compose up 直後(手動キャッシュ操作なし)から /admin/plugin/recommend が 200・おすすめ管理ページ表示・Navメニュー表示に なることを確認済み。CLAUDE.md にも挙動と対処を記載。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
dotani1111
left a comment
There was a problem hiding this comment.
4.4/Symfony7 対応をレビュー・実機検証しました。Recommend42→44 の移行(PluginManager シグネチャのコア親一致・flush() 引数除去・#[Route]/#[ORM]/#[Template] 属性化・namespace 全面統一)は正しく、CI 全マトリクス green。実機(install/enable・schema:validate 同期・管理画面描画)に加え、商品検索モーダルからおすすめ商品を登録→一覧表示まで確認しました。Blocker なし。LGTM 👍
任意の軽微点: Resource/rector.php のライセンスヘッダが http のまま/FormType の未使用 getName()。
nanasess
left a comment
There was a problem hiding this comment.
4.4 環境(PHP 8.5.4 / Symfony 7.4.13 / Doctrine ORM 3.6.2 / DBAL 4.4.3)へ本 PR のブランチをインストールし、実機で動作確認したうえでレビューしました。
一覧・新規登録・編集・削除・フロント表示のすべてが正常に動作しました。移行の品質は高く、fatal 化しうる箇所(AbstractPluginManager の新シグネチャ、EccubeNav::getNav(): array、ORM 3 の flush() 引数削除、Routing\Attribute\Route、@ORM → #[ORM] の options / JoinColumn)はすべて正しく追従できていることを本体 4.4 のソースと突き合わせて確認しています。
blocker はありません。
実機動作検証の結果
| 検証項目 | 結果 |
|---|---|
| おすすめ商品一覧 | ✅ 表示・件数カウント |
| 新規登録(商品検索モーダル → 選択 → 保存) | ✅ 「おすすめ商品を登録しました。」 |
| 編集 | ✅ 「おすすめ商品を修正しました。」 |
| 削除(DELETE + CSRF) | ✅ 「おすすめ商品を削除しました。」 |
| フロント表示(ブロック) | ✅ 下層ページ(レイアウト 2 / MAIN_BOTTOM)に描画 |
| XSS 対策 | ✅ 説明文は |raw|purify|nl2br を通す |
別 PR での対応をご検討ください(差分範囲外)
Resource/template/admin/index.twig の冒頭で読み込んでいる assets/js/vendor/jquery.ui/*.min.js 4 本は、本体 4.2.0 の時点で削除済みで 4.4 のツリーに存在しません。実機で /admin/plugin/recommend を開くと 404 が 4 件出ます。
404 /html/template/admin/assets/js/vendor/jquery.ui/jquery.ui.core.min.js
404 /html/template/admin/assets/js/vendor/jquery.ui/jquery.ui.widget.min.js
404 /html/template/admin/assets/js/vendor/jquery.ui/jquery.ui.mouse.min.js
404 /html/template/admin/assets/js/vendor/jquery.ui/jquery.ui.sortable.min.js
機能退行はありません。 jQuery UI sortable は本体の admin.bundle.js が同梱しており、default_frame.twig の <head> で読み込まれるため、読み込み順の面でも問題ありません。本 PR の差分には含まれない 4.2 からの持ち越しなので、別 PR での削除をご検討ください。
良い点
- 削除が
methods: ['DELETE']+ CSRF トークン検証で保護されている - 説明文の出力が
|raw|purify|nl2brで XSS 対策済み Resource/rector.php/Resource/.php-cs-fixer.dist.phpをResource/配下に置く配置が、4.4 のapp/config/eccube/services.phpの exclude と整合しているRecommendServiceがRecommendProduct $dataに対して$data['id']で配列アクセスしている点は、Eccube\Entity\AbstractEntity implements \ArrayAccessのため問題なし
| * @Route("/%eccube_admin_route%/plugin/recommend/sort_no/move", name="plugin_recommend_rank_move") | ||
| * @throws \Exception | ||
| */ | ||
| #[Route(path: '/%eccube_admin_route%/plugin/recommend/sort_no/move', name: 'plugin_recommend_rank_move')] |
There was a problem hiding this comment.
[minor] methods 指定と CSRF トークン検証がありません
同じコントローラの delete() は methods: ['DELETE'] + $this->isTokenValid() で保護されていますが、並び替えの moveRank() にはどちらもありません。
本体 4.4 の同型エンドポイントは 6 本すべて(CategoryController / ClassCategoryController / ClassNameController / TagController / PaymentController / DeliveryController)が
methods: ['POST']if (!$request->isXmlHttpRequest()) throw new BadRequestHttpException();if ($this->isTokenValid())
の 3 点セットになっており、本実装だけがこの規約から外れています。
実害の度合いは限定的です($request->isXmlHttpRequest() を通しており、X-Requested-With は CORS のセーフリストヘッダではないため、クロスサイトからの単純フォーム POST は成立しません)。ただし修正コストはほぼゼロで、テンプレート側の変更も不要です。
修正案: 本体 CategoryController::moveSortNo() と同じ形に揃える。
#[Route(path: '/%eccube_admin_route%/plugin/recommend/sort_no/move', name: 'plugin_recommend_rank_move', methods: ['POST'])]
public function moveRank(Request $request): Response
{
if (!$request->isXmlHttpRequest()) {
throw new BadRequestHttpException();
}
if ($this->isTokenValid()) {
...
}
}There was a problem hiding this comment.
ご指摘のとおり、本体の 3 点セットに揃えました(78dde65)。
#[Route(..., name: 'plugin_recommend_rank_move', methods: ['POST'])]
public function moveRank(Request $request): Response
{
if (!$request->isXmlHttpRequest()) {
throw new BadRequestHttpException();
}
if ($this->isTokenValid()) { ... return new Response('OK'); }
throw new BadRequestHttpException();
}ご指摘どおりテンプレートの変更は不要でした。本体 default_frame.twig の $.ajaxSetup が ECCUBE-CSRF-TOKEN ヘッダを全 Ajax に付与し、isTokenValid() がそれを読むためです。実機で並び替えを行い、リクエストヘッダに同トークンが乗って 200 が返ること、リロード後も順序が保持されることを確認しました。
ガードの動作も確認済みです: トークンなし → 403 / GET → 405 / X-Requested-With なし → 400 / 正常 → 200。
| - 3306:3306 | ||
| options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 | ||
| mysql8: | ||
| image: mysql:8 |
There was a problem hiding this comment.
[minor] CI の DB イメージが、同じ PR で追加した docker-compose とも本体 4.4 とも食い違っています
| 場所 | MySQL | PostgreSQL |
|---|---|---|
.github/workflows/main.yml |
mysql:8 | postgres:14 |
docker-compose.mysql.yml(本 PR で追加) |
mysql:8.4 | — |
docker-compose.pgsql.yml(本 PR で追加) |
— | postgres:18 |
本体 unit-test.yml |
8.4 | 18 / 13 |
本 PR 自身が追加した docker-compose は本体に揃えているのに、CI の service コンテナだけ 4.2 ブランチから持ち越した設定のままで、ローカル開発と CI でテストする DB バージョンが食い違っています。
なお database_server_version は本体 4.4 も MySQL 8.4 に対して 8 を指定しているので、現状のままで問題ありません。
There was a problem hiding this comment.
mysql:8.4 / postgres:18 に更新し、pgsql の database_server_version も 18 に合わせました(92b0834)。ご指摘のとおり MySQL 側の 8 は本体と同じなので据え置いています。
開発環境が SQLite のためローカルでは検証できておらず、CI の結果で確認します。MySQL 8.4 は mysql_native_password が既定で無効なので、接続まわりで落ちるようなら追って調整します。
| foreach ($arrRank as $recommendId => $rank) { | ||
| /* @var $Recommend RecommendProduct */ | ||
| /** @var RecommendProduct $Recommend */ | ||
| $Recommend = $this->find($recommendId); |
There was a problem hiding this comment.
[nit] find() の戻り値の null チェックがありません
$this->find($recommendId) は RecommendProduct|null を返しますが、直後に $Recommend->getSortno() を呼んでいます。存在しない ID を含む配列を渡すと Error: Call to a member function getSortno() on null になり、catch (\Exception $e) は \Error を捕捉しないため beginTransaction() したまま 500 になります。
ただし 本体 4.4 の CategoryController::moveSortNo() も同一パターンのため、移行 PR での退行でも規約違反でもありません。上記の moveRank() を修正される際に、ついでにガードを入れておくと堅くなる、という程度です。
$Recommend = $this->find($recommendId);
if (!$Recommend) {
continue;
}There was a problem hiding this comment.
①と同じ経路なので、ついでに入れました(78dde65)。
1 点補足で、直前の /** @var RecommendProduct $Recommend */ も削除しています。@extends AbstractRepository<RecommendProduct> で find() は RecommendProduct|null に解決されますが、@var が残っていると非 null に絞り込まれ、追加したガードが booleanNot.alwaysFalse として phpstan に検出されるためです。level 6 エラーゼロは維持しています。
| * @return string | ||
| */ | ||
| public function getName() | ||
| public function getName(): string |
There was a problem hiding this comment.
[nit] getName() は Symfony 3 以降どこからも呼ばれないデッドコードです
FormTypeInterface(Symfony 7.4)に getName() は存在せず、AbstractType にも実装がありません。フォーム名は AbstractType::getBlockPrefix() の既定実装が返す recommend_product で決まります。
実際、テンプレートの #recommend_product_Product は getName() が返す admin_recommend ではなく recommend_product を前提にしており、admin_recommend という文字列はリポジトリ内でこの 1 箇所にしか現れません。
属性化・型付けを一通り行ったこのタイミングで削除してしまうのが良さそうです。
There was a problem hiding this comment.
削除しました(92b0834)。dotani1111 さんからも同じご指摘をいただいていました。
削除後に実機のフォームを確認したところ、フィールド名は recommend_product[_token] / recommend_product[Product] / recommend_product[comment] のままで、getBlockPrefix() 由来の名前で決まっていることが裏取りできました。テンプレートの #recommend_product_Product とも整合しています。
| dirname(__DIR__).'/vendor', | ||
| dirname(__DIR__).'/node_modules', | ||
| ]) | ||
| ->withSets([ |
There was a problem hiding this comment.
[nit] rector の対象に Tests/ が入っておらず、PHPUnit 用のセットも未適用です
withPaths() は Controller / Entity / Form / Repository / Service / PluginManager.php / Nav.php のみで Tests/ が対象外、withSets() にも PHPUnitSetList::PHPUNIT_CODE_QUALITY / PHPUNIT_110 がありません(本体 4.4 の rector.php は両方入れています)。
本 PR のテストコード自体は静的データプロバイダも withConsecutive() も使っていないため現時点で問題はありませんが、Resource/.php-cs-fixer.dist.php と phpstan.neon.dist はいずれも Tests/ を見ているので、rector だけ穴が空いている状態です。
There was a problem hiding this comment.
Tests/ を withPaths() に追加し、PHPUnitSetList::PHPUNIT_CODE_QUALITY / PHPUNIT_110 を有効にしました(92b0834)。
「現時点で問題はない」とのことでしたが、実際に有効化したところ rector が差分を出しました。CI が rector --dry-run をゲートにしているため適用しています:
declare(strict_types=1)の付与- テストクラスの
final化 'POST'→Request::METHOD_POSTassertInstanceOf()の追加
いずれも本体 4.4 の tests/Eccube/Tests/ が既に同じ形になっていることを確認したうえで取り込みました。PHPUnit は 24/24 のままパスしています。
Tests/bootstrap.php のみ withSkip() に追加しました。名前空間を持たないスクリプトのため、import 整理で use ...\Dotenv; がライセンスヘッダより上に移動し、その結果 php-cs-fixer の header_comment がヘッダを二重に付与する事象が実際に発生したためです。phpstan も同ファイルを除外しているので、扱いを揃えた形になります。
| @@ -0,0 +1,61 @@ | |||
| <?php | |||
|
|
|||
| declare(strict_types=1); | |||
There was a problem hiding this comment.
[nit] CLI 実行ガードがありません
本 PR で追加した Resource/.php-cs-fixer.dist.php にはガードがあり、本体 4.4 の rector.php にも同等のガードがありますが、このファイルにだけありません。
app/Plugin/ はドキュメントルート外で、かつ release.yml で配布物からも除去されるため実害はありませんが、多層防御として揃えておくのが無難です。
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit;
}There was a problem hiding this comment.
本体 4.4 と同じガードを追加しました(92b0834)。多層防御として揃えておくべき、というご指摘に同意です。
| @@ -13,6 +13,10 @@ jobs: | |||
| working-directory: ../ | |||
| run: | | |||
| rm -rf $GITHUB_WORKSPACE/.github | |||
There was a problem hiding this comment.
[nit] このファイルだけ runs-on: ubuntu-22.04 のまま残っています(8 行目)
main.yml は 2 ジョブとも ubuntu-24.04 に更新されていますが、release.yml は 22.04 のままです。配布パッケージ生成は tar と rm しか使わないため今すぐ壊れはしませんが、ランナーイメージの世代を揃えておかないと将来 22.04 の提供終了時にリリースだけ落ちます。
(8 行目は差分範囲外のため、本 PR で触っているこの行にコメントしています。別 PR での対応でも構いません。)
There was a problem hiding this comment.
別 PR でも構わないとのことでしたが、main.yml を 24.04 にしたのが本 PR なので、こちらで ubuntu-24.04 に揃えました(92b0834)。
並び替えの moveRank() には methods 指定と CSRF トークン検証がなく、本体 4.4 の 同型エンドポイント (CategoryController::moveSortNo() 等) が揃って備えている 3 点セットから外れていた。本体と同じ形に揃える。 - methods: ['POST'] を指定 - !isXmlHttpRequest() で BadRequestHttpException を送出 - isTokenValid() で CSRF トークンを検証 トークンは本体 default_frame.twig の $.ajaxSetup が ECCUBE-CSRF-TOKEN ヘッダとして 全 Ajax に付与するため、テンプレート側の変更は不要。 併せて moveRecommendRank() の find() に null ガードを追加した。存在しない ID を 渡すと getSortno() が \Error になり、catch (\Exception) では捕捉できず beginTransaction() したまま 500 になっていた。null 非許容として扱っていた @var アノテーションは、ガードが常時 false と解析されるため削除する。 edit() / delete() / moveRank() の戻り値型も明示した。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Form/Type/RecommendProductType.php: getName() を削除。Symfony 3 以降どこからも
呼ばれず、FormTypeInterface にも存在しない。フォーム名は getBlockPrefix() 既定の
recommend_product で決まっており、返り値の admin_recommend は未参照だった。
- Resource/rector.php:
- ライセンスヘッダを https へ(プラグイン内の他ファイルと統一)
- CLI 実行ガードを追加(.php-cs-fixer.dist.php・本体 4.4 と同様の多層防御)
- Tests/ を対象に追加し PHPUnit セットを有効化。php-cs-fixer と phpstan は
Tests/ を見ており rector だけ穴が空いていた。Tests/bootstrap.php のみ、
import 整理でライセンスヘッダが二重化するため除外する。
- 上記に伴い、テストへ declare(strict_types=1) / final / Request 定数化 /
assertInstanceOf が適用された(本体 4.4 のテストと同じ形)
- .github/workflows/main.yml: CI の DB を mysql:8.4 / postgres:18 に更新。
同 PR で追加した docker-compose および本体 4.4 と食い違っていた。
postgres の database_server_version も 18 に合わせる。
- .github/workflows/release.yml: runs-on を ubuntu-24.04 に更新(main.yml と統一)
- Resource/template/admin/index.twig: jquery.ui の個別読み込み 4 本を削除。
本体 4.2.0 で削除済みのファイルを参照しており 404 が 4 件出ていた。
sortable は本体 admin.bundle.js に同梱され head で読まれるため機能退行はない。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@nanasess 詳細な実機検証とレビューをありがとうございます。いただいた指摘 7 件はすべて対応し、各スレッドに個別に返信しました(78dde65 / 92b0834)。 jQuery UI の 404 について別 PR をご提案いただきましたが、4 行の削除で本 PR の CHANGES_REQUESTED をまとめて解消できるため、こちらに含めさせていただきました(92b0834)。差分範囲外への越境になりますので、不適切であれば切り出します。 削除にあたって、ご指摘の裏取りをしています:
なお 4.2 ブランチにも同じ 4 行が残っています( 検証結果phpstan level 6 エラーゼロ(baseline なし)/ php-cs-fixer 差分ゼロ / rector dry-run クリーン / PHPUnit 24 テストパス。実機は EC-CUBE 4.4 + PHP 8.2 + SQLite で、一覧・登録・編集・削除・並び替えを確認しました。 CI の DB イメージ更新(mysql:8.4 / postgres:18)のみローカル未検証です。開発環境が SQLite のため、CI の結果で確認します。 |
|
@dotani1111 レビューと実機検証をありがとうございます。ご指摘の任意 2 点はどちらも対応しました。
|
Static Analysis ジョブの "Setup EC-CUBE" が以下で失敗するようになっていた。
Could not create database var/eccube.db for connection named default
Operation "Doctrine\DBAL\Platforms\SQLitePlatform::getCreateDatabaseSQL"
is not supported by platform.
本体 4.4 が doctrine/dbal 4 系を解決するようになったことによるもので、本 PR の
変更が原因ではない(同じステップは 2026-06-25 の実行では成功していた)。
SQLite では DB ファイルを doctrine:schema:create が生成するため
doctrine:database:create は不要。本体 4.4 の unit-test.yml も sqlite3 の場合は
同コマンドをスキップしており、その扱いに合わせる。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI 追加修正のご報告(5817ef4)レビュー指摘対応(78dde65 / 92b0834)をプッシュしたところ、Static Analysis ジョブが失敗しました。調査の結果、本 PR の変更が原因ではなく、本体 4.4 側の依存解決の変化によるものでしたので、併せて修正しています。 失敗内容
本 PR 起因でない根拠
修正内容SQLite では DB ファイルを レビュー範囲外の修正になりますので、別 PR に切り出すべきであればご指示ください(単一コミットなので分離は容易です)。 補足: 開発用 Docker イメージと CI で DBAL のバージョンが異なります調査の過程で判明した点です。
ORM と Symfony は一致していますが DBAL だけ差があり、ローカルでは 最終確認結果CI 全 19 チェック green
実機確認(EC-CUBE 4.4 + PHP 8.2 + SQLite): 一覧・登録・編集・削除・並び替え、および並び替えエンドポイントのガード(トークンなし 403 / GET 405 / |
概要
おすすめ商品管理プラグインを EC-CUBE 4.4(Symfony 7.4 / Doctrine ORM 3.0 / PHP 8.2+) に対応させ、コードを
Recommend42→Recommend44に改名します。4.3 とは非互換(属性必須・ORM 3・PHP 8.2+)のため、新規4.4ブランチへの取り込みです。参考: 4.3→4.4 マイグレーション手順 (doc #346) / 先行対応 eccube-api4 #186 / sample-payment-plugin #53
変更内容
1. EC-CUBE 4.4 対応(コア移行)
@ORM\*→#[ORM\*]、Controller の@Route/@Template→#[Route]/#[Template](Sensio依存除去)?int/?string/bool等)、ゲッター/セッター・各メソッドの戻り値型flush($entity)→flush()Assert\Lengthを名前付き引数形式へ: void、暗黙 nullable 引数の解消phpunit.xml.distを<source>/<extensions>形式へcode/version: 4.4.0/ テンプレート参照をRecommend44に統一2. Docker Compose によるテスト環境
docker-compose.yml+dev/mysql/pgsqlオーバーレイ、dockerbuild/ghcr.io/ec-cube/ec-cube-php:8.2-apache-4.4)でプラグインを自動導入・有効化し PHPUnit を実行可能APP_ENV=dev起動+dev 用 Cookie 設定(cookie_secure:false/cookie_samesite:lax)を上書き3. 静的解析・整形ツール
phpstan.neon.dist(level 6)/Resource/rector.php/Resource/.php-cs-fixer.dist.phpを追加(.php設定は本体のPlugin\:サービス検出で 500 を避けるためResource/配下に配置)@extends AbstractRepository<RecommendProduct>を付与する等)CLAUDE.mdに開発・テスト手順、アーキテクチャ、移行・配置の注意を記載4. CI(
.github/workflows/main.ymlほか)checkout@v4・$GITHUB_OUTPUT化--ignore-platform-req=ext-redis: Symfony 7.4 のsymfony/cacheが古いphp-redisと衝突して本体 composer install が失敗するのを回避(redis は未使用)cache:warmup: 有効プラグインのルートはコンテナのコンパイル時に確定するため、phpunit プロセスの遅延コンパイルだとRouteNotFoundExceptionが断続的に発生する問題を解消release.yml: 配布パッケージから開発・テスト用ファイル(docker-compose / dockerbuild / CLAUDE.md / phpstan / rector / php-cs-fixer)を除外テスト
8.2-apache-4.4)+ SQLite で PHPUnit 全 24 テスト パス(PHPUnit 11.5 / PHP 8.2)code=Recommend44を確認🤖 Generated with Claude Code