【Laravel】掲示板を作成する(6)投稿・編集画面のカテゴリーをプルダウンメニュー化、特定カテゴリーの記事を検索して表示
Laravelによる掲示板の作成、第6回です。
今回は投稿・編集画面のカテゴリーを「プルダウン」にする方法と「特定カテゴリー投稿を表示」する方法についてポストします。
(第1回)1.各種設定
(第1回)2.マイグレーションでDBを作成する
(第2回)3.Eloquent機能を使いモデルのリレーションを設定する
(第2回)4.LaravelのSeed機能とFakerを使ってDBにテストデータを登録する
(第3回)5.一覧画面の作成
(第3回)6.詳細画面の作成
(第4回)7.新規投稿機能の作成
(第4回)8.コメント投稿機能の作成
(第5回)9.投稿編集機能の作成
(第5回)10.投稿の物理削除機能の作成
(今回)11.投稿・編集画面のカテゴリーをプルダウンメニュー化する
(今回)12.特定カテゴリーの記事を検索して表示する
11.投稿・編集画面のカテゴリーをプルダウンメニュー化する
カテゴリーの入力にセレクトボックスを使えるようにします。
Categoriesテーブルのレコードを取得してセット出来るようにします。
モデルファイルに一覧取得用のメソッドを追加
編集ファイル:app\Category.php
1 2 3 4 5 6 7 8 9 |
/** * カテゴリーの一覧を取得 */ public function getLists() { $categories = Category::orderBy('id','asc')->pluck('name', 'id'); return $categories; } |
検索時にpluckメソッドを使用することで、任意のキーのみを取得します。
https://qiita.com/jacksuzuki/items/eae943735bda747be09c
Postsコントローラーを編集
編集ファイル:app\Http\Controllers\PostsController.php
1 |
use App\Post, App\Category; // 「App\Category」を追記 |
createメソッド
1 2 3 4 5 6 7 8 9 10 |
/** * 投稿フォーム */ public function create() { $category = new Category; $categories = $category->getLists()->prepend('選択', ''); return view('bbs.create', ['categories' => $categories]); } |
↑ prependメソッドで、作成した配列の先頭に任意の項目(選択というテキスト)を先頭に追加しています。
https://readouble.com/laravel/6.x/ja/collections.html?header=pluck()#method-prepend
editメソッド
投稿編集用画面にもカテゴリーのプルダウンを追加します。
1 2 3 4 5 6 7 8 9 10 11 |
/** * 編集フォーム */ public function edit($id) { $category = new Category; $categories = $category->getLists(); $post = Post::findOrFail($id); return view('bbs.edit', ['post' => $post, 'categories' => $categories]); } |
ビューを編集
新規投稿フォーム
編集ファイル:resources\views\bbs\create.blade.php
1 2 3 4 5 6 7 8 9 10 |
<select id="category_id" name="category_id" class="form-control {{ $errors->has('category_id') ? 'is-invalid' : '' }}" value="{{ old('category_id') }}" > @foreach($categories as $id => $name) <option value="{{ $id }}">{{ $name }}</option> @endforeach </select>} |
投稿編集画面
編集ファイル:resources\views\bbs\edit.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<select id="category_id" name="category_id" class="form-control {{ $errors->has('category_id') ? 'is-invalid' : '' }}" > @foreach($categories as $id => $name) <option value="{{ $id }}" @if ($post->category_id == $id) selected @endif >{{ $name }}</option> @endforeach </select> |
編集画面キャプチャ
12.特定カテゴリーの記事を検索して表示する
一覧ページにカテゴリーを絞るためのボタンを設け、同一カテゴリのみの一覧を作成してみます。
ビューの編集
カテゴリーのリンクを追加
編集ファイル:resources\views\bbs\index.blade.php
indexビューに以下を追加。
ついでに、何件の投稿が表示されるのかをカウントするメッセージも付けてみます。
1 2 3 4 5 6 7 8 9 |
<div class="mt-4 mb-4"> <p>{{ $posts->total() }}件が見つかりました。</p> </div> <div class="mt-4 mb-4"> @foreach($categories as $id => $name) <span class="btn"><a href="{{ route('bbs.index', ['category_id'=>$id]) }}" title="{{ $name }}">{{ $name }}</a></span> @endforeach </div> |
ページ送りを編集
カテゴリーのを指定しながらページ送りが出来るよう修正します。
1 2 3 |
<div class="d-flex justify-content-center mb-5"> {{ $posts->appends(['category_id' => $category_id])->links() }} </div> |
Postsコントローラーを編集
リンクを作成するためのカテゴリマスターをindexメソッドでも取得するようにし、投稿を取得する部分にWHEREを使ってみます。
indexメソッドの引数にrequestを追加し、カテゴリーを指定している / してしないをif文で分けています。
編集ファイル:app\Http\Controllers\PostsController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** * 一覧 */ public function index(Request $request) { // カテゴリ取得 $category = new Category; $categories = $category->getLists(); $category_id = $request->category_id; if (!is_null($category_id)) { $posts = Post::where('category_id', $category_id)->orderBy('created_at', 'desc')->paginate(10); } else { $posts = Post::orderBy('created_at', 'desc')->paginate(10); } return view('bbs.index', [ 'posts' => $posts, 'categories' => $categories, 'category_id'=>$category_id ]); } |
一覧画面キャプチャ
全件表示
ひとまずここまでの結果をキャプチャします。
「WEBサービス」で絞った場合
↑ ページ送りで2ページ目に入っても、WEBサービスカテゴリーはきちんと保持されています。
ローカルスコープを使ってみる
このままでも良さそうですが、せっかくなのでLaravel(Eloquent)の機能である「ローカルスコープ」を使ってみます。
モデルファイルへ 『"scope" + アクション名』という形のメソッドを作成します。
引数($category_id)が空の場合は何もせず return させます。
Postモデルを編集
編集ファイル:app\Post.php
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * 任意のカテゴリを含むものとする(ローカル)スコープ * */ public function scopeCategoryAt($query, $category_id) { if (empty($category_id)) { return; } return $query->where('category_id', $category_id); } |
Postコントローラーを編集
編集ファイル:app\Http\Controllers\PostsController.php
1 2 3 4 5 6 7 8 9 10 11 12 |
if (!empty($category_id)) { $posts = Post::where('category_id', $category_id)->orderBy('created_at', 'desc')->paginate(10); } else { $posts = Post::orderBy('created_at', 'desc')->paginate(10); } ↓↓↓↓↓ 以下に変更 ↓↓↓↓↓ // scopeを利用した検索 $posts = Post::orderBy('created_at', 'desc') ->categoryAt($category_id) // ←★これ ->paginate(10); |
ifの判定がなくなったのと、チェーンメソッド形式なので見やすくなった気がしますね。