테스트에서 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();
}
총결과 반성
끝내다
끝까지 읽어주셔서 감사합니다!
Reference
이 문제에 관하여(테스트에서 Without Middleware가 왜 Route Model Binding을 사용하지 않는지 확인했습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/NakanishiTetsuhiro/items/a4507cb147355b3d8895텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)