Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .claude/skills/eccube-asset/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
name: eccube-asset
description: EC-CUBE 4.4 のフロントエンドアセット(SCSS / JS バンドル)をビルド・改修するときの規約。「スタイルを変えて」「CSSを直して」「scssを編集して」「デザインを調整して」「JSを追加して」「アセットをビルドして」などと言われたとき、または html/template 配下の scss・js/bundle.js・webpack.config.js・gulpfile.js・gulp/ を作成・編集するときに使用する。生成物(css / min.css / map / html/bundle)は git 管理されているため、ソースだけコミットすると実機に反映されない。
---

# アセットビルド規約(EC-CUBE 4.4)

## 対象

- **ソース**: `html/template/{default,admin,install}/assets/scss/**/*.scss`, `html/template/*/assets/js/bundle.js`
- **ビルド定義**: `gulpfile.js`, `gulp/config.js`, `gulp/build/`, `gulp/task/`, `webpack.config.js`, `package.json`
- **生成物(すべて git 管理下)**: `html/template/*/assets/css/*.css` / `*.min.css` / `*.map`, `html/bundle/`

## 基本ルール

- **生成物は git 管理されている。ソースだけコミットしても実機には反映されない。**
`.scss` を変更したら必ずビルドし、生成された `css/` 配下も同じコミットに含める。
- **`css/` 配下を直接編集しない。** 次のビルドで上書きされて消える。変更は必ず `scss/` 側へ。
- **`.map` も追跡対象**(`style.css.map` 等)。生成物一式をコミットする。
- ビルドは `npm run build`(= gulp の既定タスク)。中身は `series(scss, scss-min, webpack)` で、
1 回で `.css` → `.min.css` → JS バンドルまで通る。個別タスクだけを流して片方だけ更新しない。
- **CI は生成物の鮮度を検査しない。** ソースと生成物の不一致は自動検出されないため、
コミット前に自分で `git status` を確認する(下記「実行・確認方法」)。

### 変換パイプライン(`gulp/task/` の実装)

| タスク | 入力 | 出力 | 処理 |
|---|---|---|---|
| `scss` | `html/template/**/scss/**/*.scss` | 同階層の `css/` へ `*.css` + `*.css.map` | sass → postcss(`postcss-import` / `autoprefixer` / `postcss-sort-media-queries`(mobile-first)) |
| `scss-min` | 同上 | 同階層の `css/` へ `*.min.css` + `*.min.css.map` | 上記 + `gulp-clean-css` |
| `webpack` | `html/template/{default,admin,install}/assets/js/bundle.js` | `html/bundle/{front,admin,install}.bundle.js` + `.map` + `.LICENSE.txt` | webpack(`mode: production`, `devtool: source-map`) |

`postcss-sort-media-queries` が `@media` を **mobile-first 順に並べ替え・統合**する点が重要。
手書きで `css` の末尾に `@media` を足した差分は、この並べ替えを通っていないため一目で判別できる。
レビューで「フルビルドか手書き追記か」を見分けるときはここを見る。

## 実装パターン

### スタイルを変える

```bash
# 1. scss を編集(例: 店頭)
# html/template/default/assets/scss/project/_15.1.cart.scss
# 2. ビルド(Docker 環境。ホストに node がある場合は npm ci && npm run build)
docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.nodejs.yml \
run --rm -T nodejs npm ci
docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.nodejs.yml \
run --rm -T nodejs npm run build
# 3. 生成物を含めてコミット
git status # scss と css/*.css *.min.css *.map が両方出ていることを確認
```

新しい部分ファイルを足すときは、エントリ(`style.scss` / `app.scss`)の `@import` へ追加する。
エントリから辿れない `.scss` はビルド対象にならない。

### JS を足す

エントリは 3 つ(`front` / `admin` / `install`)で、それぞれ `assets/js/bundle.js` が入口。
新しいスクリプトはこの `bundle.js` から `import` / `require` する。`webpack.config.js` の
`entry` を増やすのは、新しい画面区分を作るときだけ。

## よくある間違い

- ❌ `.scss` だけ変更してコミットする → ✅ 生成物(`css/*.css` `*.min.css` `*.map`)も同じコミットに含める。含めないと実機のスタイルが変わらない
- ❌ 反映されないので `css/style.css` を直接編集する → ✅ 次のビルドで消える。`scss/` を直して再ビルドする
- ❌ 「E2E が緑だから生成物は最新」と判断する → ✅ E2E のワークフローは自分で `npm run build` するため、コミット済み生成物が古くても緑になる
- ❌ `scss` タスクだけ流して `.min.css` を古いまま残す → ✅ `npm run build` で `scss` / `scss-min` / `webpack` を通す
- ❌ 生成された `css` に手で `@media` を追記する → ✅ `postcss-sort-media-queries` の並べ替えを通らず、次のビルドで消える
- ❌ 生成物のパーミッション差分(`.css` は 100755 / `.map` は 100644)に気づかずモードだけ変えてコミットする → ✅ `git diff` でモード変更が出たら戻す
- ❌ エントリ(`style.scss` / `app.scss`)へ `@import` せずに部分ファイルだけ追加する → ✅ 辿れない `.scss` はビルドされない
- ❌ ホストとコンテナでビルドを混在させ、sass のバージョン差で無関係な行まで差分が出る → ✅ どちらかに統一する(Docker 推奨)

## 実行・確認方法

```bash
# ビルド(Docker 環境。AGENTS.md「アセットビルド」の手順)
docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.nodejs.yml \
run --rm -T nodejs npm ci
docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.nodejs.yml \
run --rm -T nodejs npm run build

# 生成物の取りこぼしが無いか(scss を触ったのに css が出ていなければビルド漏れ)
git status --short html/template html/bundle

# モードだけの差分が混ざっていないか
git diff --summary | grep 'mode change' || echo 'モード変更なし'
```

- 生成物に**想定外の広範囲な差分**が出たときは、ホスト / コンテナのビルド環境差か依存更新を疑う。
意図した変更だけが出ているかを `git diff --stat` で確認してからコミットする。
- 実機での確認は `bin/console cache:clear` 後にブラウザのキャッシュを無効化して表示する。
17 changes: 17 additions & 0 deletions .claude/skills/eccube-controller/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: eccube-controller
description: EC-CUBE 4.4 のコントローラを実装・改修するときの責務分離規約。「コントローラを作って」「アクションを追加して」「このコントローラを直して」「ルーティングを追加して」などと言われたとき、または src/Eccube/Controller・app/Customize/Controller 配下を作成・編集するときに使用する。Fat コントローラを避け業務ロジックを Service へ寄せるための規約。

---

# Controller 規約 — 責務分離と Fat 化防止(EC-CUBE 4.4)
Expand Down Expand Up @@ -137,6 +138,22 @@ vendor/bin/php-cs-fixer fix # PSR-12 整形・ライセン
- ❌ 同一アクションで `executePurchaseFlow()` を複数回呼ぶとき 2 回目以降の `FlowResult` を無視する → ✅ 毎回 `hasError()`/`hasWarning()` の分岐を 1 回目と同じに揃える(共通化可)
- ❌ 配列が来る可能性のあるリクエスト値を `getString()` でスカラーに強制する → ✅ `InputBag` は非スカラーで例外を投げるため強制できない。`all()` で受けて型を検査する

## 実行・確認方法

```bash
# ルーティングが意図どおり登録されたか(#[Route] の属性ミスはここで気づく)
bin/console debug:router | grep <ルート名>
bin/console cache:clear

# 該当コントローラのテストだけを回す
bin/phpunit tests/Eccube/Tests/Web/<対象>ControllerTest.php
```

- 実装後の整形・型・静的解析・テストは **AGENTS.md「開発コマンド」** に従って実行する
(PHP-CS-Fixer / PHPStan level 6 / PHPUnit)。
- 認可の入り口は `security.yaml` だけでは追えない(`access_control` は `EccubeExtension` が動的注入する)。
新規の管理アクションは Skill `eccube-security` の「アクセス制御モデル」を確認する。

---

実装・改修後は、Skill `eccube-review-responsibility` で責務分離を点検すること。
21 changes: 21 additions & 0 deletions .claude/skills/eccube-entity/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: eccube-entity
description: EC-CUBE 4.4 の Doctrine エンティティを実装・改修するときの規約。「エンティティを作って」「テーブルを追加して」「Entityにフィールドを足して」「リレーションを定義して」「マスタを追加して」などと言われたとき、または src/Eccube/Entity・app/Customize/Entity 配下を作成・編集するときに使用する。

---

# Entity 規約(EC-CUBE 4.4)
Expand Down Expand Up @@ -110,3 +111,23 @@ if (!class_exists(Example::class)) {
- ❌ `create_date` / `update_date` を自前の `#[ORM\PrePersist]`(+`#[ORM\HasLifecycleCallbacks]`)でセット → ✅ コアの `SaveEventSubscriber`(グローバル Doctrine prePersist/preUpdate)が `method_exists` で `setCreateDate`/`setUpdateDate`/`setCreator` を自動セットする(`src/Eccube/Doctrine/EventSubscriber/SaveEventSubscriber.php`)。setter さえ生やせばよく、自前 PrePersist は二重実装になるので書かない
- ❌ 他エンティティ(特にコアの `Product`/`Customer` 等、自分で制御できない親)への関連で親削除時の挙動を未決定 → ✅ FK は既定で削除を止める(RESTRICT 相当)。未指定だと**退会・商品削除が FK 違反で失敗**したり孤児化する。`onDelete`(`SET NULL`/`CASCADE`)を指定するか、Service・プラグイン disable 等で後始末する(コアは `onDelete` を限定使用し[95 JoinColumn 中 2 件]、多くは Service 側で関連を整理している)
- ❌ `@deprecated` なゲッタを未使用と判断して削除する → ✅ CSV 出力項目(`dtb_csv`)のアクセサとして現役のことがあり、削除は仕様変更になる。先に CSV 定義と照合する

## 実行・確認方法

```bash
# 属性から導かれるスキーマ差分を SQL で確認(実行前に必ず目視する)
bin/console doctrine:schema:update --dump-sql
bin/console doctrine:schema:update --force

# トレイトで拡張した場合はプロキシを再生成する(忘れると列が生えない)
bin/console eccube:generate:proxies
bin/console cache:clear
```

- 実装後の整形・型・静的解析・テストは **AGENTS.md「開発コマンド」** に従って実行する
(PHP-CS-Fixer / PHPStan level 6 / PHPUnit)。
- カラム追加はマイグレーション不要(`schema:update` が反映する)。要否の判断は Skill `eccube-migration` を参照。

---

実装・改修後は、Skill `eccube-review-responsibility` で責務分離を点検すること。
20 changes: 20 additions & 0 deletions .claude/skills/eccube-formtype/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: eccube-formtype
description: EC-CUBE 4.4 のフォーム(FormType)を実装・改修するときの規約。「フォームを作って」「FormTypeを追加して」「入力項目を足して」「バリデーションを設定して」「検索フォームを作って」「既存フォームに項目を追加して」などと言われたとき、または src/Eccube/Form・app/Customize/Form 配下を作成・編集するときに使用する。

---

# FormType 規約(EC-CUBE 4.4)
Expand Down Expand Up @@ -79,3 +80,22 @@ class ExampleType extends AbstractType
- ❌ 具象クラス依存 → ✅ コンストラクタ DI + 必要なサービスの注入
- ❌ 既存フォームに二重送信防止/楽観ロック用の unmapped hidden を足し、サーバー側で値未送信を即エラー扱い → ✅ 値が空/未送信なら判定をスキップ(プログラム的 POST・既存テスト・外部連携を壊さない後方互換を保つ)
- ❌ 共通 FormType(RepeatedPasswordType 等)を子で使い `options.constraints` を渡す(親が定義した制約が全置換され消える) → ✅ 親の制約一式も再掲して付与する

## 実行・確認方法

```bash
# FormType の構成・オプション・拡張が効いているかを確認する
bin/console debug:form <FormType のクラス名または短縮名>
bin/console cache:clear

# フォームのテストだけを回す
bin/phpunit tests/Eccube/Tests/Form/Type/<対象>TypeTest.php
```

- 実装後の整形・型・静的解析・テストは **AGENTS.md「開発コマンド」** に従って実行する
(PHP-CS-Fixer / PHPStan level 6 / PHPUnit)。
- `FormTypeExtension` で拡張した場合は、`debug:form` の出力に追加項目が現れることで登録を確認できる。

---

実装・改修後は、Skill `eccube-review-responsibility` で責務分離を点検すること。
22 changes: 22 additions & 0 deletions .claude/skills/eccube-migration/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: eccube-migration
description: EC-CUBE 4.4 のデータベースマイグレーションを作成・編集するときの規約。「マイグレーションを作って」「マスタデータ/初期データを投入したい」「カラムの型を変えたい/リネームしたい」「スキーマを変えたい」などと言われたとき、または app/DoctrineMigrations 配下を作成・編集するときに使用する。注意: 単純なカラム追加は Entity 属性+schema:update で反映されるためマイグレーション不要(その判断にも本 Skill を参照)。

---

# マイグレーション規約(EC-CUBE 4.4)
Expand Down Expand Up @@ -132,3 +133,24 @@ final class Version20240101000000 extends AbstractMigration
- ❌ マイグレーションでテーブルを"新規定義"してスキーマの源泉にする → ✅ 源泉は Entity 属性。
- ❌ INSERT・構造変更でガードなし → 再実行や環境差で失敗。✅ 存在チェックで冪等にする。
- ❌ `down()` 未実装 → ロールバック不能。✅ `up()`/`down()` を対で実装。

## 実行・確認方法

```bash
# 属性から導ける差分(カラム追加・変更)は schema:update 側で反映される
bin/console doctrine:schema:update --dump-sql

# マイグレーション(INSERT・型変更等)を適用し、down() も往復で確かめる
bin/console doctrine:migrations:migrate
bin/console doctrine:migrations:migrate prev
bin/console doctrine:migrations:migrate
```

- 実装後の整形・型・静的解析・テストは **AGENTS.md「開発コマンド」** に従って実行する
(PHP-CS-Fixer / PHPStan level 6 / PHPUnit)。
- 冪等性は「同じマイグレーションを 2 回流しても失敗しない」ことで確認する。
- 新規インストール経路(`doctrine:schema:create` + 初期データ)でも通ることを確認する。

---

実装・改修後は、Skill `eccube-review-responsibility` で責務分離を点検すること。
18 changes: 18 additions & 0 deletions .claude/skills/eccube-repository/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: eccube-repository
description: EC-CUBE 4.4 の Doctrine リポジトリを実装・改修するときの規約。「リポジトリを作って」「検索メソッドを追加して」「クエリを書いて」「一覧の絞り込みを実装して」などと言われたとき、または src/Eccube/Repository・app/Customize/Repository 配下を作成・編集するときに使用する。

---

# Repository 規約(EC-CUBE 4.4)
Expand Down Expand Up @@ -74,3 +75,20 @@ class ExampleRepository extends AbstractRepository
- ❌ 画面表示の一覧・関連取得を無制限に全件取得(件数が際限なく増え得る)→ ✅ ページング(Paginator 用に QueryBuilder を返す)か上限を設ける
- ❌ join 先への絞り込みを EXISTS 部分クエリへ移すとき、その別名に掛かっていた既存の制約を引き継がない → ✅ 同じ制約を EXISTS 内に再掲し、集計・出力側の母集団と一致させる
- ❌ 1 対多の範囲絞り込みで下限・上限を独立した EXISTS 2 本に分ける(別々の子行が満たせばヒットしてしまう)→ ✅ 同一の子行に両条件を要求するなら EXISTS 1 本にまとめる

## 実行・確認方法

```bash
# 生成される DQL / SQL を確認する(EXISTS の制約漏れ・JOIN の重複はここで気づく)
# → $qb->getQuery()->getDQL() / ->getSQL() をテストで出力して目視する
bin/phpunit tests/Eccube/Tests/Repository/<対象>RepositoryTest.php
```

- 実装後の整形・型・静的解析・テストは **AGENTS.md「開発コマンド」** に従って実行する
(PHP-CS-Fixer / PHPStan level 6 / PHPUnit)。
- 件数・母集団が絡む変更は、**絞り込み条件を変える前後で件数が一致するか**をテストで固定する。
- 一覧のページングは Paginator 側で適用されるため、Repository は QueryBuilder を返したままにする。

---

実装・改修後は、Skill `eccube-review-responsibility` で責務分離を点検すること。
21 changes: 21 additions & 0 deletions .claude/skills/eccube-review-responsibility/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ description: EC-CUBE 4.4 で実装・改修したコードを実装直後に自

# 実装直後の自己レビュー(全層チェックリスト)

**対象**: 直前の変更差分(`git diff` / `git diff --cached` で見える範囲)。
特定のディレクトリに紐づかず、コントローラ / サービス / フォーム / テンプレート / エンティティ等の
実装・改修が一区切りついた時点で全層を横断して使う。既存の未変更コードは対象外。

実装・改修が一区切りついたら、変更差分を次の観点で横断的に点検する。
**これは助言であり、必ずしも全件修正を要求しない**(既存コードの一括修正は求めない)。

Expand Down Expand Up @@ -65,3 +69,20 @@ description: EC-CUBE 4.4 で実装・改修したコードを実装直後に自
- **新規・改修したコードの指摘**を優先して提示する。
- 既存(未変更)コードの問題は、無理に直さず「将来のリファクタ候補」として軽く触れるに留める。
- 各指摘に「どの処理を、どこ(どの Service/Processor、どのエスケープ)へ」の具体案を添える。

## 実行・確認方法

```bash
# 点検対象の差分を確定させる(レビュー範囲を「変更した箇所」に固定する)
git diff --stat
git diff --cached --stat

# 機械的に判定できるものは先にツールへ委ねる(変更ファイルに絞って実行する)
vendor/bin/php-cs-fixer fix <変更ファイル>
vendor/bin/phpstan analyse <変更ファイル>
bin/phpunit <対象のテストファイル>
```

- ツールが拾えるもの(整形・型・非推奨 API)を人手で数えないこと。本 Skill の観点は
**ツールで検出できない責務分離・認可・エスケープ**に集中する。
- 各レイヤの詳細な検証手順は、該当レイヤの Skill の「実行・確認方法」に従う。
Loading
Loading