Laravelで商品詳細画面(Show)を実装する方法!初心者向けCRUD開発入門
こんにちは!今回は、Laravelを使った商品管理機能の開発に挑戦していきます。
今回のテーマは、商品詳細画面(Show)の実装です。 商品一覧画面から気になる商品を選び、その商品の名前や価格、カテゴリ、説明文などを表示する機能を作っていきます。
Laravelを学び始めると、ルーティングやコントローラ、モデル、Bladeなど、覚えることがたくさんありますよね。 最初はそれぞれの役割がわからず、コードを見ても「結局、どこで何をしているんだろう?」と迷うことがあると思います。
でも、実際に小さな機能を作りながら理解していけば大丈夫です。 今回は商品テーブルとカテゴリテーブルを使い、商品詳細画面が表示されるまでの流れを順番に確認していきましょう!
1. Laravelで商品詳細画面を作る課題の意味
今回の課題では、商品テーブルとカテゴリテーブルを設計し、商品管理機能の一部を実装します。 対象となるのは、一覧表示・詳細表示・登録の3つです。
商品管理機能で実装する3つの処理
- 一覧表示(index):登録されている商品を一覧で表示する
- 詳細表示(show):選択した商品1件の詳しい情報を表示する
- 登録(create/store):新しい商品を登録するための画面を表示し、データを保存する
今回、特に注目するのが詳細表示を担当するshowメソッドです。
例えば、商品一覧に「ノートパソコン」「キーボード」「マウス」が並んでいるとします。 その中から「キーボード」をクリックしたときに、キーボードの価格や説明文などを表示するのが商品詳細画面です。
一覧画面が商品の概要をまとめて確認する場所だとすれば、詳細画面は1つの商品について詳しく知るためのページと考えるとわかりやすいですね。
2. 商品テーブルとカテゴリテーブルの関係
商品詳細画面を作る前に、データベースの構造を確認しておきましょう。 今回は、商品情報を管理するproductsテーブルと、カテゴリ情報を管理するcategoriesテーブルを使用します。
categoriesテーブルの構成
カテゴリテーブルには、商品の分類に関する情報を保存します。
id:カテゴリを識別するIDname:カテゴリ名created_at:作成日時updated_at:更新日時
例えば、「パソコン周辺機器」「文房具」「家電製品」といったカテゴリを登録します。
productsテーブルの構成
商品テーブルには、個々の商品に関する情報を保存します。
id:商品を識別するIDcategory_id:所属するカテゴリのIDname:商品名price:価格description:商品の説明created_at:作成日時updated_at:更新日時
Laravelで理解したい1対多のリレーション
今回のデータベース設計で重要なのが、カテゴリと商品の関係です。
例えば、「パソコン周辺機器」というカテゴリには、キーボードやマウス、モニターなど複数の商品を登録できます。 一方、商品は基本的に1つのカテゴリに所属する設計にします。
このように、1つのカテゴリに複数の商品が関連する関係を1対多(One-to-Many)と呼びます。
- カテゴリ側:複数の商品を持つ
- 商品側:1つのカテゴリに所属する
Laravelでは、この関係をモデルのリレーションとして定義することで、関連するデータを扱いやすくできます。
3. Laravelのモデルとリレーションの設定
データベースの構造を確認したら、次はモデルを設定します。 Laravelのモデルは、データベースのテーブルとやり取りするためのクラスです。
今回はProductモデルとCategoryモデルを使い、それぞれの商品情報とカテゴリ情報を扱います。
Productモデルの設定
まずは、app/Models/Product.phpを確認しましょう。
商品モデルでは、登録可能な項目とカテゴリとの関係を定義します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Product extends Model
{
protected $fillable = [
'category_id',
'name',
'price',
'description',
];
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}
ここで注目したいのが、category()メソッドです。
belongsTo()は、現在のモデルが別のモデルに所属していることを表します。
Productモデルでは、商品がカテゴリに所属する関係を定義しています。
Categoryモデルの設定
続いて、app/Models/Category.phpを確認します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model
{
protected $fillable = [
'name',
];
public function products(): HasMany
{
return $this->hasMany(Product::class);
}
}
Categoryモデルでは、hasMany()を使用しています。
これは、1つのカテゴリに複数の商品が関連していることを表します。
fillableとは何か?
モデルに設定されている$fillableは、一括代入によって値を設定できる項目を指定するための仕組みです。
例えば、商品登録時に複数の項目をまとめて保存するときに関係します。
ただし、$fillableに項目を追加しただけで、商品が自動的に登録されるわけではありません。
実際に保存するときは、コントローラ側でバリデーションなどを行い、適切な値を渡す必要があります。
4. Laravelのルーティングを設定する
モデルの準備ができたら、次はルーティングです。 ルーティングは、ブラウザからアクセスされたURLに対して、どの処理を実行するかを決める仕組みです。
今回は、商品IDを含むURLにアクセスすると商品詳細画面を表示するように設定します。
routes/web.phpにルートを追加する
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::get('/products/{product}', [
ProductController::class,
'show'
])->name('products.show');
このコードでは、/products/{product}というURLにGETリクエストが送られたときに、ProductControllerのshowメソッドを実行します。
URLの{product}は何を意味するのか?
{product}は、URLの一部を動的な値として扱うためのプレースホルダーです。
例えば、次のようなURLが考えられます。
/products/1:IDが1の商品/products/2:IDが2の商品/products/3:IDが3の商品
商品ごとにルートを用意する必要はありません。 同じルートを利用し、URLに含まれるIDに応じて表示する商品を切り替えられます。
Route::resourceを使う方法
Laravelでは、リソースコントローラを使ってCRUD関連のルートをまとめて定義することもできます。
use App\Http\Controllers\ProductController;
Route::resource('products', ProductController::class);
この設定では、index、show、create、store、edit、update、destroyなどのルートが定義されます。 そのため、商品管理機能をまとめて作る場合には便利です。
ただし、実際に利用するには、対応するコントローラのメソッドやビューなども実装する必要があります。 ルートを定義しただけですべての機能が完成するわけではないので注意しましょう。
5. Laravelのコントローラで商品情報を取得する
ルーティングを設定したら、次はコントローラを実装します。 コントローラは、リクエストを受け取り、必要なデータを取得して、表示する画面へ渡す役割を担います。
ProductControllerのshowメソッド
app/Http/Controllers/ProductController.phpに、次のようなshowメソッドを用意します。
public function show(Product $product)
{
$product->load('category');
return view('products.show', compact('product'));
}
このコードでは、商品情報を受け取り、カテゴリ情報を読み込んだうえで、商品詳細画面に渡しています。
Product $productとは?
初心者が特につまずきやすいのが、showメソッドの引数にあるProduct $productです。
これは、Laravelのルートモデルバインディングという機能を利用しています。
例えば、ブラウザで/products/3にアクセスしたとします。
ルートのパラメータ名とコントローラの引数名が対応していれば、LaravelはURLのIDを使って該当する商品モデルを取得し、showメソッドに渡してくれます。
イメージとしては、次のような処理です。
// イメージ:Laravelが商品IDをもとにモデルを取得する
$product = Product::findOrFail(3);
実際のルートモデルバインディングでは、モデルの設定などに応じて取得方法が決まります。 一般的な主キーを使う設定では、該当する商品が存在しなければ404エラーになります。
$product->load('category')の役割
次に、$product->load('category')を見てみましょう。
この処理は、取得済みの商品モデルに関連するカテゴリ情報を読み込むためのものです。 商品名や価格だけでなく、カテゴリ名も詳細画面に表示したい場合に役立ちます。
また、最初からカテゴリ情報も取得するなら、ルートモデルバインディングを利用せず、クエリで取得する設計ではProduct::with('category')などを使う方法もあります。
どちらを使うかは、データの取得方法や実装方針に合わせて選びましょう。
compact('product')とは?
compact('product')は、変数$productをビューへ渡すためのPHPの関数です。
次の2つは、今回の例では同じような意味になります。
return view('products.show', compact('product'));
return view('products.show', [
'product' => $product,
]);
これで、Bladeテンプレート側から$productを使って商品情報を表示できるようになります。
6. Bladeで商品詳細画面を表示する
コントローラから商品情報を渡せるようになったら、最後は画面を作ります。 Laravelでは、Bladeというテンプレートエンジンを使ってHTMLを記述できます。
show.blade.phpを作成する
次の場所にファイルを用意します。
resources/views/products/show.blade.php
商品名・カテゴリ・価格・説明文を表示するコードは、次のとおりです。
<h1>商品詳細</h1>
<dl>
<dt>商品名</dt>
<dd>{{ $product->name }}</dd>
<dt>カテゴリ</dt>
<dd>{{ $product->category?->name ?? '未分類' }}</dd>
<dt>価格</dt>
<dd>{{ number_format($product->price) }}円</dd>
<dt>説明</dt>
<dd>{{ $product->description }}
この例では、商品情報をHTMLの定義リストで表示しています。
<dt>は項目名、<dd>はその項目の説明や値を表します。
{{ $product->name }}で商品名を表示する
Bladeでは、{{ }}の中に変数や式を書くことで、その結果をHTMLに出力できます。
例えば、商品名が「ワイヤレスキーボード」なら、{{ $product->name }}の部分にその商品名が表示されます。
number_format()で価格を見やすくする
価格の表示には、PHPのnumber_format()を使っています。
数値に3桁区切りのカンマを付けることができるため、金額を読み取りやすくなります。
例えば、次のように表示できます。
- 980 → 980円
- 1500 → 1,500円
- 128000 → 128,000円
小さな工夫ですが、商品価格を扱う画面では見やすさにつながります。
カテゴリ名を表示する方法
$product->category?->name ?? '未分類'では、関連するカテゴリが存在する場合はカテゴリ名を表示し、カテゴリが取得できない場合は「未分類」と表示します。
ただし、これはカテゴリが未設定の場合などに備えた表示上の対策です。 データベースの外部キー制約や入力時のバリデーションなど、データの整合性を保つ仕組みも必要に応じて設定しましょう。
7. 商品一覧から詳細画面へ移動する
詳細画面だけを作っても、ユーザーがそこへ移動できなければ使いにくいですよね。 そこで、商品一覧画面に詳細画面へのリンクを追加します。
一覧画面に詳細リンクを追加する
商品一覧のBladeテンプレートで、商品名をリンクにします。
<a href="{{ route('products.show', $product) }}">
{{ $product->name }}
</a>
route('products.show', $product)は、名前付きルートからURLを生成する書き方です。
商品モデルを渡すことで、通常はその商品の主キーを使ったURLが生成されます。
例えば、商品IDが3なら、生成されるURLは一般的に/products/3となります。
クリックすると、その商品に対応する詳細画面へ移動できます。
route()を使うメリット
URLを直接HTMLに書く方法もありますが、名前付きルートを使うとURLの管理がしやすくなります。
例えば、ルートのURLを変更した場合でも、名前付きルートを利用していれば、ルート定義を基準にURLを生成できます。 複数の画面から同じルートへリンクするような開発では、特に便利です。
8. Laravelの商品詳細画面で初心者がつまずきやすいポイント
ここまでで、商品詳細画面を表示する基本的な流れを確認しました。 最後に、実装時に気を付けたいポイントを整理しておきましょう。
① {{ }}と{!! !!}の違いを理解する
Bladeの{{ }}は、通常、HTMLに出力する値を自動的にエスケープします。
これにより、入力された文字列がHTMLやJavaScriptとして意図せず実行されるリスクを減らせます。
一方、{!! !!}は、値をエスケープせずに出力します。
信頼できない入力値に使用すると、クロスサイトスクリプティング(XSS)につながるおそれがあります。
特別な理由がない限り、商品名や説明文などの表示には{{ }}を使用しましょう。
② カテゴリがnullの場合のエラーを防ぐ
商品にカテゴリが設定されていない場合、$product->category->nameのようなコードでエラーが発生することがあります。
そのような場合には、null安全演算子やnull合体演算子を利用できます。
{{ $product->category?->name ?? '未分類' }}
これならカテゴリが取得できない場合にも、代わりの文字列を表示できます。
③ N+1問題を避ける
商品一覧画面で複数の商品を表示し、それぞれのカテゴリ名も取得する場合には、N+1問題に注意しましょう。
例えば、商品を100件取得してから、それぞれの商品について個別にカテゴリ情報を取得すると、データベースへの問い合わせが増えてしまうことがあります。
このような場合には、Eloquentのイーガーローディングを使う方法があります。
$products = Product::with('category')->get();
with('category')を使うことで、商品と関連するカテゴリをまとめて効率よく取得できます。
ただし、実際のクエリ数は取得方法やリレーションの構成によって異なります。
なお、今回のように商品詳細画面で1件の商品を取得する場合と、一覧画面で大量の商品を表示する場合では、最適な取得方法が異なることも覚えておきましょう。
④ ルート・コントローラ・ビューの名前を一致させる
商品詳細画面が表示されないときは、ルートやコントローラ、Bladeファイルの名前が正しく対応しているか確認しましょう。
- ルート名:
products.show - コントローラのメソッド:
show - ビューのパス:
products.show - Bladeファイル:
resources/views/products/show.blade.php
例えば、コントローラでview('products.show')と指定した場合、Laravelは通常、resources/views/products/show.blade.phpを探します。
ファイル名やディレクトリが異なると、ビューが見つからずエラーになるため注意してください。
⑤ 商品が存在しない場合の動作を確認する
ルートモデルバインディングを使っている場合、指定されたIDの商品が見つからなければ、通常は404エラーになります。 開発時には、存在しないIDをURLに指定した場合の動作も確認しておくと安心です。
また、商品一覧画面から詳細画面へ移動する流れだけでなく、直接URLにアクセスした場合にも正しく動作するか確認しましょう。
9. まとめ:Laravelの商品詳細画面は3つの役割を理解しよう
今回は、Laravelで商品詳細画面(Show)を実装する方法について解説しました。 商品とカテゴリの2つのテーブルを使い、ルーティング・コントローラ・Bladeテンプレートを組み合わせることで、商品情報を表示する画面を作れます。
今回覚えておきたい重要ポイント
- ルーティング:URLと実行する処理を結び付ける
- コントローラ:商品情報を取得してビューへ渡す
- モデル:データベースとのやり取りやリレーションを定義する
- Blade:取得した商品情報をHTMLとして表示する
- ルートモデルバインディング:URLのIDに対応するモデルを自動的に取得する
- イーガーローディング:関連データを効率よく取得し、N+1問題を抑える
Laravelを学び始めたころは、コードを1行ずつ追うだけでも大変に感じるかもしれません。 ただ、今回のように小さな機能を実装していくと、それぞれのファイルがどのようにつながっているのか、少しずつ見えてきます。
商品詳細画面が完成したら、次は商品登録機能や編集機能にも挑戦してみましょう。 登録・一覧・詳細・編集・削除というCRUDの流れを一通り理解できれば、Laravelを使ったWebアプリケーション開発の基礎が身に付いていきます。
焦らず一つずつ、実際にコードを書いて動かしながら学んでいきましょう!







0 件のコメント:
コメントを投稿