Laravel投稿サイト構築.64 記事詳細、collectionの結合にハマる
前回
モーダル画面表示を一旦諦めて。
改めて調べると他にもやり方はあるようなので、情報集めつつ保留。
■仕様変更~記事詳細表示
やりたいのはTwitterの表示に近い。
投稿の詳細を表示して、紐づくテーマとしたにぶら下がる返信を表示する。
返信は詳細を表示中の投稿のみ可能とする。
現状はテーマについてしか返信できないので、返信に対しても返信できるようにする。
■返信テーブル項目追加
返信テーブルには親となるテーマIDしかなく、
返信に返信できるようにするためにテーブルに返信先の返信IDを追加する。
-----
$php artisan make:migration replies_add_reply_id --table=replies
-----
$table->bigInteger('reply_id');
-----
$php artisan migrate
■コントローラ作成
詳細を表示するためのコントローラを作成
$php artisan make:controller DetailController
show関数で詳細表示。
テーマIDと返信IDから表示するデータ一覧を取得する。
モデルは既存を使うので作成しない。
■ルーティング設定
web.php
Route::resource('/detail', 'App\Http\Controllers\DetailController');
■詳細画面に遷移するボタン
テーマと返信にそれぞれボタンを表示して、ボタン押下時に詳細画面に遷移する。
テーマを選択した場合のクエリパラメータは
thread_id = テーマのID
reply_id = 0 とする。
返信を選択した場合のパラメータは
thread_id = テーマID
reply_id = 選択した返信データのID
とする。
これによりreply_idが0の場合はテーマが選択されたものと判断する。
■詳細画面での一覧表示
twitterでもツイートを選択すると、まずツイートの詳細が表示されて、
ツイートが何かのツイートへの返信である場合、元ツイートも上に表示される。
また、ツイートへの返信も下部に表示される。
ので、それと同様の考え方で選択したデータと関連したデータを取得する。
- テーマのデータを取得
- 返信データを選択した場合、返信IDのデータを取得
- 返信IDの返信元データを取得。返信データが無くなるまで遡る。
- 返信データへの返信データを取得
↑のデータを取得して全部繋げて表示する。
■collection のmergeに注意
ここでハマったのが、それぞれ取得したデータはCollectionで取得されるのだが、
先に取得したコレクションに次に取得したデータを追加していく処理。
$col_a = $col_a->merge($col_b);
としても、後のデータで上書きされてしまい想定の結果にならなかった。
さんざん調べて3日ほど沼にはまってようやく解決。
$col_a = collect($col_a)->merge($col_b);
とすれば望んだ結果になった。
mergeは同じデータを上書きしてしまうので、collectで新しいコレクションを作成することで回避している、という認識。
そんなこんなで詳細画面で、テーマに対する返信、
返信に対する返信ができるようになった。
見た目が地味すぎて違いがわからんね。
■次回の宿題
- 詳細画面で書き込んだ時は再表示
- 再表示の際に、該当の書き込みにスクロールを合わせる
- テーマと返信で枠を分けて表示
- 返信のインデントを分かりやすく
地道にいきましょうー
続く