#laravelのRoute-Controller間のパラメーター間違い
##言い訳
youtubeなんかの動画や初心者用のwebページなどをみてlaravelにおけるroute-controller間のパラメーターの受け渡しを学びました。(学んだつもりでした。)
まさか他の人が沼にハマるまいとは思いますが、救済する1本の蜘蛛の糸になれば幸いです。
##科学の力ってスゲー
フレームワークを利用し始めた当初簡単にsqliteのようなデータベースと接続し、簡単にSELECTできる(値を引っ張ってこれる)ことに感心していました。
「(データがあるテーブル名がposts
の場合)え?Post::find(1)
だけでid=1の(レコードの)データをもって来れるの!?科学の力ってスゲー。」
###間違い
実際にハマっていた間違い↓
<?php
use Illuminate\Support\Facades\Route;
Route::get('/post','PostsController@index');
Route::post('/post/{id}','PostsController@detail');
//ルートの設定postで一覧画面、その後ろに数字をつけることで、そのidの詳細画面に行けるようにする
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostsController extends Controller
{
public function index()
{
$posts = Post::all();
//postsテーブルの全データ取得
return view('ichiran',['posts' => $posts]);
//表示は「ichiran.blade.php」の方に引数postsを渡して任せる
}
public function detail(Post $post)
{
$title = $post->title;
$body = $post->body;
//例えば/postページから/post/1へと遷移した時は$id=1のデータが勝手に取得される
return view('shousai',['title' => $title,'body' => $body]);
//表示は「shousai.blade.php」の方に引数title,bodyを渡して任せる
//普段は$postをビューの方に渡してそっちで{{ $post->title }}としていますよ、念為。
}
}
/postページから/post/1へと遷移した時は$id=1のデータが勝手に取得される
なんて程、人生は甘くはないんですねぇ。
何万回試そうが、$id=1のデータは取れず…
###最初に見つけた解決策1
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostsController extends Controller
{
//略
public function detail(Post $post,$id)//<-new
{
$post = Post::find($id);
//routeの方で{id}と指定したためcontrollerで使いたい時にはfunctionの引数に指定すれば使える
//よって/post/1へと遷移したら$id=1のデータをfindすることができる
$title = $post->title;
$body = $post->body;
return view('shousai',['title' => $title,'body' => $body]);
}
}
でもこれなんかスマート(ここで言うスマートとは「引数が多くなってるなぁ、function内の記述もちょっと多いし…なんかもっと削れないんかなぁ」程度のこと)でないなぁ…
###試行錯誤し、行きついた解決策2
まずrouteをちょっと変更し、{id}ではなく{post}にします。
そうすると…
<?php
use Illuminate\Support\Facades\Route;
Route::get('/post','PostsController@index');
Route::post('/post/{post}','PostsController@detail');
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostsController extends Controller
{
//略
public function detail(Post $post)//<-new
{
$title = $post->title;
$body = $post->body;
return view('shousai',['title' => $title,'body' => $body]);
}
}
これだけで$title
には{post}に渡された数字のデータが入るんですね。ビックリです。
いつも{id}で指定していたので、「なんでリソースコントローラー作るとeditには勝手に任意のデータが読み込まれるのだろう…リソースコントローラー専用なのか、ずるいな」と思っていました。
##からくり
detailファンクションの引数にPostモデルのインスタンスを指定してあげた(いわゆるDI)変数名とrouteで指定した変数名を合わせることで、URL内で指定した数値のデータをモデルから持ってくることができるんですね。
え?それの次が知りたい?
それはもっと偉い人に聞いてください。