Laravel5.5のルーティングパラメータが勝手に変換される仕組みを調べようとした


前段

基盤にしているのはこちらの記事

ついでにこれを見ながらあれこれメモした記事も貼っておきます。

ルーティングがよくわからない

Laravelのテンプレートで、1行で済ませるやつがあるじゃないですか。

web.php
Route::resource('posts', 'PostController');

こういうの。
簡単なのは良いんですが、具体的に何やってるの?
ってのと、修正したいときにイミワカンナイってなったので読み解こうと努力しました。

(調べればいい記事が転がっている気がするけど調べ方がわからない)

わからないところ

具体的にはここ。

editで$postを受け取ってる?

editはこんな感じです。

PostController.php
    public function edit(Post $post)
    {
        return view('posts.edit', ['post' => $post]);
    }

しれっとPost型の$postを受け取っています。

ちょっと唐突過ぎて、どうやって?という感覚が拭えません。

というわけでここを調べました。

(きっとドキュメントに普通に書いてあるんだろうなとは思いつつも)

(あとたぶんresourceは関係なさそうだなとも思いつつ)

調べてみた

デバッグで止めてみる

止めてみると、確かにPost型で何かを受け取ってます。

idは42。
urlで指定してる数字です。

ルーティングの確認

php artisan route:listを実行すると、editは以下のようになってます。

|        | GET|HEAD  | posts/{post}/edit             | posts.edit            | App\Http\Controllers\PostController@edit                                  | web,auth                                     |

posts/{$post}/editになってます。
僕の拙いLaravelの知識によると、ここで{}でくくった変数は、指定した関数の引数として受け取ることになるはずです。

つまりこの場合は、PostControllerのeditという関数で、$postという名前の文字列を受け取るはず。

普通に受け取ってみる

試しにPost型ではなく、特に型を指定しないで受け取ってみます。

すると、ただの42という文字列が飛んできました。

なるほどなるほど……?

勝手に変換されてるっぽい?

どうやら、引数をテーブルにするとwhereIdした結果を返してくれるっぽいですね。

勝手に。

きっとconstructするときとかに引数を指定した扱いになって、主キーであるidと照合した結果を返してくれるとかそんな感じでしょうか。

見てみたらわかるかな、Modelを覗いてみたんですけどよくわかりませんでした。

正直よくわからないのでもう少し実験します。

 実験

他のテーブルでもできるのか?

Postじゃなくても受け取れるのでしょうか。

この関数自体はGET、つまりurlを直接叩いてもアクセスできるので、適当に叩いてみます。
http://homestead.test/posts/10/editとかで。

エラー

初手はエラーになりました。

ReflectionException
Class App\Http\Controllers\User does not exist

参照不足です。
そりゃそうだ。

use App\User;を追加して、再挑戦します。

再挑戦

Userが受け取れました。

Route:resourceを使っているからとかそういうことではなくて、

普通の関数の引数でもできるのか

単純に同じことが、普通の関数呼び出しでもできるのでしょうか?

PostController.php
    public function edit(Post $post)
    {
        $post = $this->hoge(11);
        return view('posts.edit', ['post' => $post]);
    }

    private function hoge(User $a)
    {
        return $a;
    }

ダメでした

まあそうですよね。
普通に考えてダメですよねこんな挙動。

そもそも、普通に考えてダメな挙動してるから混乱したというのが最初の話ですし。

ルーティングで指定した関数なら?

GETで受け取るところから真似すればできたりするのでしょうか?

web.php
Route::get('posts/{post}/test', 'PostController@test');

PostController.php
    public function test(User $post)
    {
        return dd($post);
    }

できた。

できました。

まとめ

ルーティングパラメータをDBのテーブル型で受け取ると勝手にwhereIdした結果に変換してくれる。

さももっともらしく書いてますけど、ちゃんとドキュメント読んでる人からすると何言ってんだこいつって感じな気がします。
あんまり説明書読まないタイプなんで……ほら……(言い訳)

あとやっぱりresourceは関係なかったです。