EC-CUBE / EC-CUBE/ec-cube

composer.json の残課題: 拡張の宣言漏れ・システム要件の三者不一致・メジャーバージョン遅れ

Open
#6,940 2 comments 0 reactions 0 assignees View on GitHub
refactor
Dominant language
PHP
Stars
788
Forks
719
Avg merge
4d 4h
Merged PRs (30d)
39

Description

## 概要

#6939 で `composer.json` の残骸整理と暗黙依存の明示化を行いましたが、影響範囲の判断が必要なため意図的に保留した項目があります。まとめて Issue 化します。

いずれも #6939 の調査で判明したもので、根拠となる実測を併記します。

---

## 1. `guzzlehttp/guzzle` が `require` にあるが本体は未使用

**事実**

- 本体は **一度も Guzzle を直接使ったことがありません**(`git log -S'GuzzleHttp' -- src app` の結果が空)
- リポジトリ全体で `guzzlehttp` の参照は `composer.json` の 1 行のみ
- lock 上の依存元は `codeception/module-phpbrowser`(dev)、`captbaritone/mailcatcher-codeception-module`(dev)、`monolog/monolog`(require-dev/suggest)

**論点**

`require` から外すと dev には codeception 経由で残り、本番 vendor からのみ消えます。ただし **Guzzle を自前で宣言していないプラグインが壊れます**。EC-CUBE のプラグインは Guzzle を使うものが多く、コアの vendor に暗黙に依存している可能性があります。

**選択肢**

- (a) 保留(現状維持)
- (b) `require` から削除。4.4 はメジャー更新のため破壊的変更として実施可能。プラグイン側に自前 require を促す必要あり
- (c) `require-dev` へ移動(実質 (b) と同じだが意図が明確)

事実上「コアが提供する公開依存」として扱われてきた経緯があるかどうかが判断材料になりそうです。

---

## 2. PHP 拡張の宣言漏れ(`ext-pdo` / `ext-session` / `ext-phar` / `ext-fileinfo`)

**事実**

本体が使用しているのに `composer.json` に無く、**推移的にも一切担保されていない**拡張があります。

| 拡張 | 本体での使用 | 現在の要求元 |
|---|---|---|
| `ext-pdo` | `TransactionListener:95,118`、`PluginService:634,800` が `$nativeConnection->inTransaction()` を PDO 前提で呼ぶ | **なし**(doctrine/dbal も要求しない) |
| `ext-phar` | `PluginService:411`、`TemplateController:126,249` の `new \PharData(...)` | 本番では**なし**(dev の `phar-io/manifest` のみ) |
| `ext-session` | `framework.yaml` の `handler_id: session.handler.native_file` | **なし** |
| `ext-fileinfo` | `UploadedFile::getMimeType()` が symfony/mime 経由で finfo を使用 | **なし** |

**なぜ #6939 で追加しなかったか**

`require` に書くと、その拡張がない環境で **composer が解決不能になり導入できなくなります**。実測:

```
$ composer update --dry-run # config.platform で ext-fileinfo を無効化して再現
Your requirements could not be resolved to an installable set of packages.
- Root composer.json requires PHP extension ext-fileinfo * but the ext-fileinfo package is disabled
exit=2
```

`ext-pdo` / `ext-session` は「無ければ EC-CUBE が起動しない」ため実質リスクゼロと考えられますが、`ext-fileinfo` / `ext-phar` は**本体は動くが一部機能が動かない**ため、これまで動いていた環境を弾く可能性があります。

**参考**: `ext-bcmath` は `nanasess/bcmath-polyfill` が `provide: {"ext-bcmath": "8.1.0"}` を宣言しているため、**bcmath 非搭載環境でも `require` に追加して解決が通ります**(`composer update --dry-run` で exit=0 を実測)。制約は `"*"` にする必要があります(`^8.2` 等では polyfill の 8.1.0 が満たせません)。同様に `ext-ctype` は `symfony/polyfill-ctype` が provide します。

---

## 3. システム要件が「要件ドキュメント / InstallController / composer.json」で三者不一致

**事実**

| 拡張 | [要件ドキュメント](https://github.com/EC-CUBE/doc4.ec-cube.net/blob/master/_pages/quickstart/requirement.md) | `InstallController` | `composer.json` | 本体コードでの使用 |
|---|---|---|---|---|
| `sodium` | **必須** | **必須**(`$requiredModules`) | `config.platform` で緩和 (#6827) | **0 件** |
| `GD` | **必須** | 記載なし | 記載なし | **0 件** |
| `bcmath` | 記載なし | 記載なし | 記載なし(polyfill を require) | **金額計算の中核** |

**論点**

- **sodium**: #6827 で「sodium 非搭載の共有レンタルサーバーでも Web API プラグインを導入可能に」する方針が取られ、`config.platform` で緩和されました。しかし `InstallController.php:83` の `$requiredModules` には `'sodium'` が残り、インストーラが `addDanger()` で必須エラー表示を出します(※ `checkModules()` は表示のみでインストールをブロックしないことは確認済み)。方針と表示が矛盾しています。
- **GD**: 要件では必須ですが、`image*()` / `GdImage` / `getimagesize` の使用は **0 件**です。`Dockerfile` では入れています。要件が実態と合っていない可能性があります。
- **bcmath**: 金額計算(`Order.php`、`PurchaseFlow.php` 等)の中核で全面的に使用しているのに、要件にもインストーラにも記載がありません。polyfill があるため動作はしますが、要件として明示すべきではないでしょうか。
- **4.4 の要件自体が未記載**(ドキュメントは 4.3 まで)

**対応候補**

- doc4.ec-cube.net の要件更新(4.4 追記、sodium/GD の見直し、bcmath 追記)※別リポジトリ
- `InstallController` の `$requiredModules` / `$recommendedModules` の整合(sodium を推奨へ移す等)

---

## 4. `doctrine/common` が `ClassUtils` 1 箇所のためだけの依存

**事実**

- `doctrine/common` を lock 上で require しているのは **root のみ**(ORM 3 は要求しません)
- 本体での唯一の使用箇所は `src/Eccube/Service/CsvExportService.php:211` の `ClassUtils::getClass($entity)` のみ(`Doctrine\Common\Collections` は `doctrine/collections` 由来のため別)

**対応候補**

`$em->getClassMetadata(get_class($entity))->getName()` 等への置換で依存を 1 つ減らせます。実装変更を伴うため要検討。

---

## 5. 直接依存のメジャーバージョン遅れ

`composer outdated --direct --major-only` の結果(2026-09-14 時点、`upstream/4.4` = `979b3e1b45`)。Issue 作成後に新たなメジャーが出た 3 件(guzzle 8 / phpseclib 4 / monolog-bundle 4)を追記しています。

| パッケージ | 現在 | 最新 | 状態 | 備考 |
|---|---|---|---|---|
| `doctrine/data-fixtures` | 2.2.1 | 2.2.1 | ✅ 対応済 | #7039 |
| `codeception/module-phpbrowser` | 4.1.0 | 4.1.0 | ✅ 対応済 | #6995(dev) |
| `doctrine/persistence` | 3.4.5 | 4.2.0 | PR あり | #7123(CI 緑・Approve 済、マージ待ち)。#7129(dependabot)は重複でコード修正を伴わないため rector / phpstan が落ちる。#7123 マージで自動クローズ |
| `doctrine/doctrine-fixtures-bundle` | 3.7.3 | 4.3.1 | PR あり | #7130(dependabot)。CI 全滅の原因は同梱の `doctrine/orm` 3.7.0 の SchemaTool 回帰(`dtb_order.order_status_id` を STI の 3 関連で共有 → `IndexAlreadyExists`)で、3.7.1(doctrine/orm#12607)で修正済み。recreate 済(3.7.1 同梱)。残る unit-test の失敗は ORM 3.7 の ORDER BY 大文字化(doctrine/orm#12449)によるテスト期待値のずれで、**#7145 マージ後に rebase** で緑になる見込み |
| `doctrine/orm` | 3.6.8 | 3.7.1 | PR あり | #7128(doctrine group)。上記と同じ理由で全滅。recreate は対象版を変えないため 3.7.0 のまま。#7145 → #7130 の順でマージされれば自動クローズ(メジャーではないが同じ回帰を踏むため併記) |
| `mobiledetect/mobiledetectlib` | 2.8.45 | 4.11.0 | PR あり | #7040(dependabot)。recreate 済で CI 全緑(128 success)。4.x は UA 未設定時に `isMobile()` が例外を投げるが、既定の `autoInitOfHttpHeaders: true` なら `""` がセットされ `false` を返す(実測)。本体 3 箇所は引数なし呼び出しで影響なし |
| `psr/log` | 2.0.0 | 3.0.2 | PR あり | #7144。4.3 のマイナー互換ポリシーで `~2.0` に固定(#6324 → #6367)し dependabot に通知不要と返した経緯があるため 4.4 でも PR が出ない。`Logger::log()` は `$message` 無型のため契約拡大で互換 |
| `symfony/monolog-bundle` | 3.11.2 | 4.1.0 | PR あり | #7144。dependabot は `symfony/*` の major を ignore。4.0 で削除されたオプションは本体設定に該当なし |
| `softcreatr/jsonpath` | 0.8.3 | 2.0.0 | **更新不可** | 版ごとに PHP 対応範囲が分断(0.8.x `>=8.0` / 0.9–0.10 `8.1 - 8.4` / 0.11–1.0 `^8.5` / 2.0 `^8.3`)しており、4.4 が対応する PHP 8.2〜8.5 を満たすのは 0.8.x のみ。0.10.0 に上げると PHP 8.5 でプラグイン導入(`ComposerApiService` の `composer require`)が解決不能になることを #7144 の CI で実測。`^0.8` は 0.8.x 固定のガードとして維持し、本体未使用の Codeception `module-rest` 推移依存なので #7144 で `require-dev` へ移動。根本解消は Codeception 削除(#7082) |
| `guzzlehttp/guzzle` | 7.15.3 | 8.2.0 | 別 Issue | `captbaritone/mailcatcher-codeception-module`(`^6 || ^7`、更新なし)が拘束。Codeception 削除(#7082)で解消するため #7082 に委ねる。項目 1(本体未使用)とも連動 |
| `phpseclib/phpseclib` | 3.0.56 | 4.0.1 | PR あり | #7146。`nanasess/bcmath-polyfill` 1.2.0(`^3.0 \|\| ^4.0`)で拘束が解け、namespace `phpseclib3` → `phpseclib4` を置換。4.0.1 は `EC::createKey()` の鍵が password `''` を持ち `toString('PKCS8')` が空パスワード暗号化 PEM を出す挙動変更があるため、`UcpSigningKeyPurpose::generate()` で `withoutPassword()` を明示 |

4.4 はメジャー更新のため、破壊的変更を伴う更新を実施できる節目です。

---

## 参考: #6939 で対応済みの項目

- `conflict.easycorp/easy-log-handler` / `skorp/detect-incompatible-samesite-useragents` / `allow-plugins.kylekatarnls/update-helper` / `minimum-stability: RC` / `extra` の死んだ 5 キー / `symfony.lock` の孤児レシピ 13 件の削除
- `phpseclib/phpseclib` / `justinrainbow/json-schema` / `ezyang/htmlpurifier` の明示化
- `ext-filter` / `ext-tokenizer` / `ext-xml` / `ext-zlib` の追加

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Contributor guide

Open the contributing guide

Research direction

Start with composer.json and InstallController.php, then review the referenced dependency-update PRs and the 4.4 requirement page in doc4.ec-cube.net. Reproduce the listed composer update --dry-run checks and inspect the cited usages in CsvExportService.php, TransactionListener, PluginService, TemplateController, Order.php, and PurchaseFlow.php. Done requires an agreed scope, passing CI, and consistent dependency and system requirements.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, symfony
Domain
backend, build-system, documentation
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.