コンテンツにスキップ

商品管理機能仕様書

機能概要

商品管理機能は、ECサイトで扱う商品を管理するための管理画面機能です。商品の作成、編集、削除、一覧表示、並び替えなどの操作が可能です。

URL: /admin/products ナビゲーション: 商品管理グループ(ソート順: 1) 技術スタック: Filament v4, Livewire v3

画面構成

一覧画面(List Products)

商品の一覧を表示し、検索、ソート、並び替え、削除などの操作が可能です。

画面レイアウト

  • テーブル: 商品一覧
  • ツールバー: 一括削除、フィルター、ページネーション

テーブルカラム

カラム名 表示内容 検索 ソート 表示/非表示
商品ID id 常時表示
商品名 name 常時表示
カテゴリ categories.name 常時表示(バッジ)
タグ tags_display 常時表示(HTML)
ブランド brand.name 常時表示
ステータス status 常時表示(バッジ)
販売中 is_active - 常時表示(アイコン)
並び順 sort_order - 常時表示
説明文 description_list - デフォルト非表示
作成日 created_at - 常時表示
更新日 updated_at - 常時表示

機能詳細

検索機能 - 商品ID、商品名、カテゴリ名、タグ名、ブランド名、ステータスで検索可能 - リアルタイム検索(入力と同時にフィルタリング)

ソート機能 - デフォルトソート: updated_at 降順 - 全てのカラムでソート可能 - 商品ID、商品名、ステータス、販売中、並び順、説明文、作成日、更新日: 直接カラムでソート - カテゴリ、タグ、ブランド: リレーション先のカラムでソート(JOINを使用)

並び替え機能 - ドラッグ&ドロップで表示順序を変更可能 - sort_order カラムの値を自動更新 - 並び替え後は自動的にテーブルをリフレッシュ

ページネーション - デフォルト表示件数: 50件 - 表示件数オプション: 10, 20, 30, 40, 50, 100, 150, 200件

フィルター - モーダル表示(スライドオーバー) - モーダル幅: 4XL(FourExtraLarge) - フィルター項目: - 削除済み(TrashedFilter) - カテゴリ(複数選択、検索可能、プリロード) - タグ(複数選択、検索可能、プリロード) - ブランド(検索可能、プリロード) - 公開ステータス(複数選択)

一括操作 - 一括削除 - 一括復元(削除済みの場合) - 一括完全削除(削除済みの場合)

レコードアクション - 編集 - 削除(ソフトデリート) - 復元(削除済みの場合) - 完全削除(削除済みの場合)

作成画面(Create Product)

新しい商品を作成するためのフォーム画面です。

フォーム項目

商品情報セクション - 商品名(name): 必須、最大255文字 - スラッグ(slug): 必須、最大255文字、ユニーク - レジ種別(register_type_id): 必須、デフォルト: 1、検索可能、プリロード - 商品説明(description): リッチエディタ、最小高さ300px、最大5000文字 - 商品一覧用説明文(description_list): リッチエディタ、最小高さ200px、最大5000文字 - 検索キーワード(search_word): テキストエリア、3行、カンマ区切り、最大255文字 - フリーエリア(free_area): リッチエディタ、最小高さ200px、最大5000文字

画像セクション - 商品画像(image): 複数画像、最大10枚、並び替え可能、グリッドレイアウト

ステータスセクション - 公開ステータス(status): 必須、デフォルト: 1(公開)、オプション: 1=公開、2=非公開 - 販売中(is_active): 必須、デフォルト: true - 表示順序(sort_order): 必須、数値

作成者セクション - 作成者(creator): プレースホルダー、現在のユーザー名を表示

カテゴリセクション - カテゴリ(categories): ツリー選択、検索可能、親カテゴリ自動選択

タグセクション - タグ(tags): チェックボックスリスト、検索可能、2列表示

ブランドセクション - ブランド(brand_id): 選択、検索可能、プリロード

レイアウト構成

┌─────────────────────────────────────────────────────────┐
│ 商品情報セクション(2列)                                │
│ ┌─────────────────────┬─────────────────────────────┐ │
│ │ 商品名               │ スラッグ                   │ │
│ │ レジ種別             │                            │ │
│ │ 商品説明(全幅)     │                            │ │
│ │ 商品一覧用説明文     │                            │ │
│ │ 検索キーワード       │                            │ │
│ │ フリーエリア         │                            │ │
│ └─────────────────────┴─────────────────────────────┘ │
│ 画像セクション(全幅)                                  │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 商品画像(複数、グリッド)                          │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ ステータスセクション(1列)                              │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 公開ステータス                                       │ │
│ │ 販売中                                               │ │
│ │ 表示順序                                             │ │
│ └─────────────────────────────────────────────────────┘ │
│ 作成者セクション                                         │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 作成者                                               │ │
│ └─────────────────────────────────────────────────────┘ │
│ カテゴリセクション                                       │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ カテゴリ(ツリー選択)                               │ │
│ └─────────────────────────────────────────────────────┘ │
│ タグセクション                                           │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ タグ(チェックボックス、2列)                       │ │
│ └─────────────────────────────────────────────────────┘ │
│ ブランドセクション                                       │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ブランド                                             │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

バリデーション

項目 ルール
商品名 必須、最大255文字
スラッグ 必須、最大255文字、ユニーク(productsテーブル内)
レジ種別 必須
公開ステータス 必須
販売中 必須
表示順序 必須、数値

作成時の処理

  1. creator_idを自動設定(現在のユーザーID)
  2. 商品レコードを作成
  3. 選択されたカテゴリに関連付け(祖先カテゴリも自動追加)
  4. 選択されたタグに関連付け
  5. 空のバリエーション(0軸)を作成
  6. regular_price: 0
  7. price: 0
  8. stock: 0
  9. stock_unlimited: false
  10. is_active: true

作成後の動作

  • 作成成功後、編集画面にリダイレクト
  • 成功通知を表示

編集画面(Edit Product)

既存の商品を編集するためのフォーム画面です。

フォーム項目

作成画面と同じフォーム項目を使用します。

バリデーション

作成画面と同じバリデーションを適用します。ただし、スラッグのユニークチェックでは現在編集中のレコードを除外します。

編集時の処理

  1. 既存の関連カテゴリIDを取得してフォームに設定
  2. 既存の関連タグIDを取得してフォームに設定
  3. 保存時に選択されたカテゴリに関連付け(祖先カテゴリも自動追加)
  4. 保存時に選択されたタグに関連付け
  5. リレーションのsync()後、親モデルのupdated_atを更新

ヘッダーアクション

  • 削除(ソフトデリート)
  • 復元(削除済みの場合)
  • 完全削除(削除済みの場合)

保存後の動作

  • 保存成功後、編集画面にリフレッシュ(リダイレクトなし)
  • 成功通知を表示

バリデーション

フォームバリデーション

フィールド ルール エラーメッセージ
name required, max:255 商品名は必須です / 商品名は255文字以内で入力してください
slug required, max:255, unique:products,slug,{id} スラッグは必須です / スラッグは255文字以内で入力してください / このスラッグは既に使用されています
description max:5000 商品説明は5000文字以内で入力してください
description_list max:5000 商品一覧用説明文は5000文字以内で入力してください
search_word max:255 検索キーワードは255文字以内で入力してください
free_area max:5000 フリーエリアは5000文字以内で入力してください
register_type_id required レジ種別は必須です
status required 公開ステータスは必須です
is_active required 販売中フラグは必須です
sort_order required, numeric 表示順序は必須です / 表示順序は数値で入力してください

エラーハンドリング

一般的なエラー

  • バリデーションエラー: フォーム内にエラーメッセージを表示
  • データベースエラー: エラーログに記録し、ユーザーにエラー通知を表示
  • ファイルアップロードエラー: アップロード失敗時はエラーメッセージを表示

削除時のエラー

  • ソフトデリート: 削除済みレコードは復元可能
  • 完全削除: 削除済みレコードのみ完全削除可能
  • 削除失敗: エラーログに記録し、ユーザーにエラー通知を表示

技術仕様

使用技術

  • Filament v4: 管理画面フレームワーク
  • Livewire v3: リアクティブコンポーネント
  • Alpine.js: クライアント側インタラクション(Livewireに同梱)

ファイル構成

app/Admin/Resources/
├── ProductResource.php              # メインリソースクラス
└── ProductResource/Pages/
    ├── ListProducts.php             # 一覧ページ
    ├── CreateProduct.php            # 作成ページ
    └── EditProduct.php              # 編集ページ

app/Models/
└── Product.php                      # モデルクラス

モデル機能

リレーション - categories(): belongsToMany(Category::class) - この商品に属するカテゴリ - tags(): belongsToMany(Tag::class) - この商品に属するタグ - brand(): belongsTo(Brand::class) - この商品のブランド - productVars(): hasMany(ProductVar::class) - この商品のバリエーション - creator(): belongsTo(Admin::class) - この商品の作成者

スコープ - active(): is_active = true の商品を取得 - published(): status = 1 の商品を取得

ソフトデリート - deleted_at カラムを使用 - 削除済みレコードは復元可能

ファイル保存

画像保存先 - 商品画像: storage/app/public/products/ - リッチエディタ添付ファイル: storage/app/public/products/

ディスク設定 - 使用ディスク: public - シンボリックリンク: php artisan storage:link で作成済み

ページネーション設定

デフォルト表示件数: 50件(config/ecspoke.pagination.default_per_page

表示件数オプション: 10, 20, 30, 40, 50, 100, 150, 200件(config/ecspoke.pagination.per_page_options

UI/UX仕様

画像プレビュー - 高さ: 100px - グリッドレイアウト(商品画像複数時)

リッチエディタ - 商品説明: 最小高さ300px - 商品一覧用説明文: 最小高さ200px - フリーエリア: 最小高さ200px - 全機能付きツールバー

カテゴリ選択 - ツリー表示 - 親カテゴリ自動選択 - 検索可能

タグ選択 - チェックボックスリスト - 2列表示 - 検索可能

関連機能

商品バリエーション管理

  • 商品編集画面から商品バリエーションを管理可能
  • ProductVarsRelationManagerを使用

カテゴリ管理機能との連携

  • 商品作成・編集画面でカテゴリを選択可能
  • 選択されたカテゴリの祖先カテゴリも自動的に関連付け

タグ管理機能との連携

  • 商品作成・編集画面でタグを選択可能
  • 複数タグを選択可能

ブランド管理機能との連携

  • 商品作成・編集画面でブランドを選択可能
  • ブランド削除時、関連商品のbrand_idが自動的にNULLに設定される

参照資料