4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravel SubstituteBindingsミドルウェア

Posted at

Laravel SubstituteBindingsミドルウェアについて調べてみた。
SubstituteBindingsミドルウェアは、Kernel.phpでwebとapiグループのミドルウェアとして指定されている。
Substitute = 代替(代わりに使う)。Binding = 紐づける

Kernel.php
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

SubstituteBindingsは

ルートモデルバインディング用の機能。
https://laravel.com/docs/6.x/routing#route-model-binding

routeにfunctionを入れてモデルを引数にすると、pathの値を元に自動でfindOrFailして引数として渡してくれる。
{user} pathでUserが取得できない場合は404エラーが返される。

api.php
Route::get('/user/{user}', function (\App\Models\User $user) {
    return $user;
});
curl http://127.0.0.1:8000/api/user/1
{"id":1,"name":"aaa","email":"hoge@co.jp","email_verified_at":null,"api_token":"WzLJB6Djg7HS9vDp8Ss8RqcIKYPYvs2pJBUl8CYMwsnVCHXK3FeIEdLBFq8Q","created_at":"2020-12-04T14:46:11.000000Z","updated_at":"2020-12-04T14:46:11.000000Z"}%     

SubstituteBindingsをミドルウェアから外した状態で再度アクセスするとLaravelコンテナによってUserモデルがインスタンス化された状態で引数に追加される。($userはnullではないが$user->idとかはnullになる)

SubstituteBindings読む

SubstituteBindingsのコンストラクタでRegisterを引数でもらっている。

SubstituteBindings.php
    public function __construct(Registrar $router)
    {
        $this->router = $router;
    }

handle関数では、bindingを行っている。
binding処理はコンストラクタで受け取ったRegisterクラスで行っている。

    public function handle($request, Closure $next)
    {
        $this->router->substituteBindings($route = $request->route());

        $this->router->substituteImplicitBindings($route);

        return $next($request);
    }

Register

Illuminate\Foundation\Application.phpのregisterCoreContainerAliases関数でRegisterのaliasが設定されている。
Registerクラスは\Illuminate\Routing\Router::classの型を使ってDIされる。

Application.php
'router'               => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],

substituteBindings

substituteBindingsは明示的なpathとModelの結合の処理に使用される。
substituteBindingsの関数を見ると、routeのparameterを元にパラメータを設定している。
Routerにはpath名と型を紐づけるbinderを管理するbidnersプロパティがあり、そこに該当するbinderが設定されているとperformBinding関数を使ってパラメータを取得し、setParameterでセットしている。
binderはbind関数で追加されるが、これはmodel関数で使用されている。
model関数は Route::model('user', \App\Models\User::class); のように使われる。

Router.php
    public function substituteBindings($route)
    {
        foreach ($route->parameters() as $key => $value) {
            if (isset($this->binders[$key])) {
                $route->setParameter($key, $this->performBinding($key, $value, $route));
            }
        }

        return $route;
    }

↓routeのパラメータはpathを分解した時のpath名をkeyに値をvalueにした配列になっている。

Route::get('hoge/{hogeId}', [\App\Http\Controllers\HogeController::class, 'hoge']);
↓route->parameters()の値
{"hogeId":"11"}

substituteImplicitBindings

substituteImplicitBindingsは暗黙的なpathとモデルの結合に使用される。
Implicit = 暗黙的

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?