ここでは,/comments/1 や /comments/2 のようにコメントの ID を指定してアクセスすれば投稿コメントの詳細情報が個別に表示されるようなページを作成します.
まずは,routes/web.php にルート定義を追加します.具体的には次のように記載します.つまり,URL で /comments/ の後に文字列が指定されていれば,それを comment_id
として認識し,CommentsController の show
という関数に渡す,という定義です.
routes/web.php(抜粋)
Route::get('/', function () {
return view('welcome');
});
Route::get('/comments', [CommentsController::class, 'index']) -> name('comments.index');
Route::get('/comments/{comment_id}', [CommentsController::class, 'show']) -> name('comments.show');
次に,CommentsController に show 関数を追加します.とりあえずの動作を確認したいので,show 関数では受け取った comment_id
をそのまま表示するだけの機能を持たせておきます.
app/HTTP/Controllers/CommentsController.php(抜粋)
class CommentsController extends Controller
{
public function index()
{
$comments = Comment::get(); // SELECT * FROM comments; のイメージ
return view('comments.index')
->with('comments', $comments);
}
public function show($comment_id)
{
dd($comment_id);
}
}
Web サーバを起動します.(Web サーバを終了するには Ctrl + C を押下してください)
vagrant@ubuntu2204 comment_app $ php artisan serve --host=192.168.56.101 --port=8000 ⏎
INFO Server running on [http://192.168.56.101:8000].
Press Ctrl+C to stop the server
/comments/2,/comments/3 や /comments/abc などにアクセスしてみます.現時点ではIDの値が正しいかどうかを判定することなく指定したIDがそのまま表示されていることがわかります.
指定した ID のコメントを CommentsController の show 関数でデータベースから取得してみます.なお,検索条件は where()
で指定することができます.また,index 関数では get()
によって検索条件に合致する全てのレコード(行)を取得しているのに対し,show 関数では first()
によって検索条件に合致した結果から最初の1件だけを取得します.条件を指定しても合致件数が複数になることが考えられる場合,合致件数が1件のときと2件以上のときでは得られる結果のデータ形式が異なってしまうため,これがバグの原因となってしまいます.したがって,ここでは first()
を利用して1件のみを取得するようにしています.また,得られる件数が1件であるため,次の4行目と6行目の $comment
は単数形にしていることにも注意してください(複数形でも動作しますが,自分自身も含めて後日ソースを見た開発者が混乱するだけです).
app/HTTP/Controllers/CommentsController.php(抜粋)
public function show($comment_id)
{
// SELECT * FROM comments WHERE id = 2; のイメージ
$comment = Comment::where('id', '=', $comment_id)
->first();
dd($comment);
}
実行すれば次のような結果になります.つまり,IDが正しければ Comment オブジェクトを取得することができ, 不正な ID(たとえば abc)を指定した場合には null
となります.
Comment オブジェクトを取得できることがわかったので,取得したオブジェクトをビューに渡すように記載します.
app/HTTP/Controllers/CommentsController.php(抜粋)
public function show($comment_id)
{
// SELECT * FROM comments WHERE id = 2; のイメージ
$comment = Comment::where('id', '=', $comment_id)
->first();
return view('comments.show')
->with('comment', $comment);
}
上の6行目では comments.show
と入力したので,/resources/views/comments ディレクトリに show.blade.php という名前のファイルを作成します.内容は index.blade.php と大きく変わらないので,index.blade.php のコードをコピーしてから適宜変更しても良いでしょう.たとえば ubuntu のコマンドを使ってファイルをコピーする場合は次のようにします.
vagrant@ubuntu2204 comment_app $ ls resources/views/comments/ ⏎ index.blade.php vagrant@ubuntu2204 comment_app $ cp resources/views/comments/index.blade.php resources/views/comments/show.blade.php ⏎ vagrant@ubuntu2204 comment_app $ ls resources/views/comments/ ⏎ index.blade.php show.blade.php vagrant@ubuntu2204 comment_app $
リモート (ubuntu) でファイルを作成した後には忘れずにローカルへの同期を行なってください.なお,Visual Stuido Code でファイルをコピーしても構いません.
show.blade.php は次のように修正します.
resources/views/comments/show.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>コメント</title>
</head>
<body>
<h1>コメント</h1>
<dl>
<dt>ID:</dt>
<dd>{{ $comment->id }}</dd>
<dt>Title:</dt>
<dd>{{ $comment->title }}</dd>
<dt>Body:</dt>
<dd>{{ $comment->body }}</dd>
</dl>
</body>
</html>
この時点で,/comments/2 や /comments/3 のように正しい ID を指定すれば,コメントの詳細情報を個別に表示できるようになりました.
しかしながら,/commments/10 や /comments/abc のように存在しない ID を指定した場合にはエラーとなってしまいます.
存在しない不正な ID が指定された時には /comments へ強制的に移動(リダイレクト)するような処理を CommentsController の show 関数に追加します.実際にリダイレクトされることも確認してください.
app/HTTP/Controllers/CommentsController.php(抜粋)
public function show($comment_id)
{
// SELECT * FROM comments WHERE id = 2; のイメージ
$comment = Comment::where('id', '=', $comment_id)
->first();
if (!$comment) {
return redirect('/comments');
}
return view('comments.show')
->with('comment', $comment);
}
個別のコメントをうまく表示できるようになったので,コメント一覧のページ /comments の各コメントタイトルにリンクを設置します.具体的には,index.blade.php を次のように修正します.つまり,リンク先の生成において,route()
を使って,routes/web.php に記載された name
が 'comments.show'
であるルートに $comment->id
を 'comment_id'
というキーで渡す,ということを意味してます.
/resources/views/comments/index.blade.php(抜粋)
<body>
<h1>コメント一覧</h1>
<ul>
@foreach ($comments as $comment)
<li>
<a href="{{ route('comments.show', ['comment_id' => $comment->id]) }}">
{{ $comment->title }}
</a>
</li>
@endforeach
</ul>
</body>
一覧ページ /comments を開くとタイトルにリンクが設置され,そのリンクをクリックすると個別コメントの詳細ページにジャンプできるようになりました.