現在Laravelの教材を鋭意制作中です!完成まで今しばらくお待ちください

#25 詳細ページを作成する

前章で投稿されたお問い合わせフォームを表示させることはできるようになりました。

この章からは、お問い合わせフォームに投稿された内容を確認できる一覧ページから詳細ページへリンクできるように実装していきたいと思います。

1. pullとブランチの作成

まずは・・・。作業に入る前に前回mergeしたメインブランチを更新しておきましょう。

# ブランチをpullする
git pull origin main

以上で完了です。mainブランチが前章で作成されたブランチと同じになれば、次に進みます。

git switch -C make-show

今回はshowページを作成するので、安直ですがmake-showと言う名前のブランチを作成しました。ブランチ名は任意となりますので、お好きなブランチ名を付けて構いません。

2.ContactControllerの実装

public function show($id)
{
  $contact = Contact::findOrFail($id);
  
  return view('show', compact('contant')); 
}

コードの解説

public function show($id)

このメソッドは、個別のお問い合わせデータを1件だけ取得して表示するための処理です。

index() で一覧が表示され、その中の「詳細」リンクを押すことで show() が呼び出されます。

$id には、表示したいレコード(お問い合わせ)の ID が渡されます(例:/contacts/3) 。つまりURLを参照しています。

$contact = Contact::findOrFail($id);

この一文は Laravel の Eloquent モデルから、特定のレコード(ここでは「お問い合わせ内容」)を1件取得するためのコードです。

このコードは「お問い合わせテーブル(contacts)から、指定された $id のデータを1件だけ取り出して $contact に代入する」という処理です。

たとえば $id5 なら、IDが5のレコードが1件取り出されます。

findOrFail()

データが見つかった場合は対応するレコード(例:IDが5の問い合わせ)が $contact に代入されます。

しかしデータが見つからなかった場合は、Laravelが自動で 404 エラー(Not Found)を返します。

ユーザーが「存在しないIDを指定したURL」にアクセスしても、エラー画面で安全に処理されます。

find()

find() だけだと、データが存在しないときに null が返ってきてしまい、画面が「何も表示されない」だけになることがあります。

findOrFail() を使えば、「なかったら404を出す」という明確な対応が自動で行われるため、安全性が高まります。

その命名に関しては、実は意図的に $contact という単数形を使っているんです。これには理由があります👇

なぜ$contactsではなく$contact なのか?

ここではなぜ変数として指定している$contactについて言及しておきたいと思います。

まず、1つ目の理由として「中身が単一のレコードだから」という理由が挙げられます。

Contact::findOrFail($id) の戻り値は、1件の Contact モデルインスタンスです。

つまり「お問い合わせの1件分」なので、単数形の $contact が自然です。

2つ目に「一覧と明確に区別するため」という理由が挙げられます。

もし index() メソッドで一覧表示するときに $contacts を使っていた場合、一覧は$contacts(複数のレコード)、詳細は $contact(1件のレコード)と、命名を分けておくことで、視聴者にも違いが直感的に伝わりやすくなります

3つ目の理由として「Blade側でも意味がはっきりする」が挙げられます。

<h1>{{ $contact->name }} さんの詳細</h1> 

このように使う場合、$contact のほうが人やレコードを指している感じが伝わりやすいですよね。

つまり、一覧画面では複数の $contacts を使って、1件表示では単数の $contact にすることで、読み手にも『今何を扱っているか』が自然に伝わる設計になります。

3.show.blade.phpの実装


@extends('layouts.app')

@section('title', 'お問い合わせ詳細')

@section('content')
<h2>お問い合わせ詳細</h2>

<table border="1" cellpadding="8" cellspacing="0">
  <tr>
    <th>ID</th>
    <td>{{ $contact->id }}</td>
  </tr>
  <tr>
    <th>名前</th>
    <td>{{ $contact->name }}</td>
  </tr>
  <tr>
    <th>メール</th>
    <td>{{ $contact->email }}</td>
  </tr>
  <tr>
    <th>年齢</th>
    <td>{{ $contact->age }}</td>
  </tr>
  <tr>
    <th>性別</th>
    <td>{{ $contact->gender }}</td>
  </tr>
  <tr>
    <th>興味のある分野</th>
    <td>{{ $contact->interests }}</td>
  </tr>
  <tr>
    <th>お問い合わせ内容</th>
    <td>{{ $contact->message }}</td>
  </tr>
  <tr>
    <th>送信日時</th>
    <td>{{ $contact->created_at->format('Y-m-d H:i') }}</td>
  </tr>
</table>

<a href="/">一覧へ戻る</a>
@endsection

showページで表示するデータは一覧表示ではなく、1件ずつのデータの表示となるので、$contact が使用されています。

4.index.blade.phpの修正

<table border="1" cellpadding="8" cellspacing="0">
  <tbody>
  @foreach ($contacts as $contact)
    <tr>
      <td>{{ $contact->id }}</td>
      <td>{{ $contact->name }}</td>
      <td>{{ $contact->email }}</td>
      <td>{{ $contact->age }}</td>
      <td>{{ $contact->gender }}</td>
      <td>{{ $contact->created_at }}</td>
      <td><a href="/contacts/{{ $contact->id }}">詳細</a></td>
    </tr>
  @endforeach
  </tbody>
</table>
@endif
@endsection

最後にindex.blade.phpの修正を行います。と言っても「詳細」のリンクを付与するだけです。

コードの解説

<td><a href="/contacts/{{ $contact->id }}">詳細</a></td>

例えば、IDが5の場合、 /contacts/5 のようなリンクが作られるので、正しい詳細ページへ案内できるようになります。

以下のように書くこともできます。

<td><a href="{{ url('/contacts/' . $contact->id) }}">詳細</a></td>
    • ルート名を使わないぶん、URLの構造が変更されるとリンクも手動で修正しないといけない点に注意。
  • 名前付きルートのほうがメンテナンス性は高いけれど、シンプルな小規模プロジェクトなどではこの方法でも十分使えます。

5.Git push

以上が完了したら、ここでGitを共有しておきましょう。

git add -A
git commit -m "コメントを入力する"
git push origin make-show

git pushが無事完了したら、GitHub上で操作を行います。

pull requestが来ているので、mergeしましょう。

次章:#26 routeとnameの関係 へ進む