테스트에서 Without Middleware가 왜 Route Model Binding을 사용하지 않는지 확인했습니다.

11791 단어 Laravel

2021/06/24 추기


현재 테스트를 자동으로 실행할 때 VerifyCsrfToken을 닫기 때문에 지금부터 Laravel을 사용하는 사람들은 빠져들지 않을 것 같습니다.만약 이 문장을 참고로 읽을 수 있다면 큰 도움이 될 것이다.
https://readouble.com/laravel/8.x/ja/csrf.html

입문


Laravel Advent Calendar 2019 - Qiita의 3일째 보도.
이번에는 Route Model Binding의 컨트롤러와 관련된 테스트가 떨어지는 현상으로 한 시간 동안 빠져들었기 때문에 이 일을 기사로 써보려고 했습니다.

라우트 모델 바인딩이란?


갑작스럽지만 get 매개 변수로 사용자로부터 ID를 받은 후 해당 사용자의 이메일로 돌아가는 예는 이런 느낌을 준다.
// Route Model Bindingなしバージョン
Route::get('api/users/{id}', function (int $id) {
    $user = Entity\User::find($id);
    return $user->email;
});
Route Model Binding으로 쓰면 이런 느낌이에요.
// Route Model Bindingありバージョン
Route::get('api/users/{user}', function (Entity\User $user) {
    return $user->email;
});
컨트롤러에서 상응하는 사용자 모델을 쓰지 않고 처리하는 것은 매우 편리하다
공식적인 설명은 여기 있습니다.
https://laravel.com/docs/6.x/routing#route-model-binding

해결 방법


테스트 코드에서 use WithoutMiddleware 를 설명하면 모든 Middleware가 비활성화되지만, 이로 인해 Route Model Binding 기능도 비활성화된 것 같습니다.아래와 같은 Middleware 사용 안 함으로 축소하면 해결됩니다.
$this->withoutMiddleware([VerifyCsrfToken::class, YourAwesomeMiddleware::class]);
이쪽의 해결 방법은 예전@gomaaa 씨도Qiita로 귀결되었습니다.
Route Model Binding 경로 테스트 팁

어렵기 때문에 깊이 파보았다


어떤 middleware가 Route Model Binding의 역할을 맡고 있는지 궁금해서 조사를 해봤습니다.
Laravel의 버전은 v6.5.1 입니다.

1. /app/Http/Kernel.php를 확인한 후 $route Middleware의 수조에서 다음과 같은 설명을 발견하였다

'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
Laravel5.3에 추가된 Route Model Binding 기능을 담당하는 Middleware입니다.이 링크를 참고하도록 허락해 주십시오.Laravel-Qiita 경감을 위한 Laravel 중간부품 구성
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $this->router->substituteBindings($route = $request->route());

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

        return $next($request);
    }
감사합니다.

2. 코드를 따르면substituteImplicitBindings()에서 Illuminate\Routing\Router.php의 실제 코드 발견

    /**
     * Substitute the implicit Eloquent model bindings for the route.
     *
     * @param  \Illuminate\Routing\Route  $route
     * @return void
     *
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
     */
    public function substituteImplicitBindings($route)
    {
        ImplicitRouteBinding::resolveForRoute($this->container, $route);
    }

substituteImplicitBindings 내용

    /**
     * Resolve the implicit route bindings for the given route.
     *
     * @param  \Illuminate\Container\Container  $container
     * @param  \Illuminate\Routing\Route  $route
     * @return void
     *
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
     */
    public static function resolveForRoute($container, $route)
    {
        $parameters = $route->parameters();

        foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) {
            if (! $parameterName = static::getParameterName($parameter->name, $parameters)) {
                continue;Container.php
            }

            $parameterValue = $parameters[$parameterName];

            if ($parameterValue instanceof UrlRoutable) {
                continue;
            }

            $instance = $container->make($parameter->getClass()->name);

            if (! $model = $instance->resolveRouteBinding($parameterValue)) {
                throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
            }

            $route->setParameter($parameterName, $model);
        }
    }
resolveForRoute()에서 Laravel의 DI 구조를 사용하여 Eloquent 모델을 얻은 후$instance = $container->make($parameter->getClass()->name);Illuminate/Database/Eloquent/Model.php로 실제 데이터를 얻는다.
    /**
     * Retrieve the model for a bound value.
     *
     * @param  mixed  $value
     * @return \Illuminate\Database\Eloquent\Model|null
     */
    public function resolveRouteBinding($value)
    {
        return $this->where($this->getRouteKeyName(), $value)->first();
    }

총결과 반성

  • 테스트에서 Middleware 처리를 사용하지 않으려면 사용하지 않으려는 Middleware
  • 만 사용하지 않는 것이 좋다
  • 도움으로 코드를 읽었으니 이번에는 혼자 읽을 수 있다
  • 끝내다


    끝까지 읽어주셔서 감사합니다!

    좋은 웹페이지 즐겨찾기