什么是资源路由
项目中有很多资源路由,如:
Route::resource("shop", 'ShopController');
这个资源路由默认的参数名是shop
,即请求shop/111
时,通过route->parameters()
获取路由参数得到的是["shop"=>111]
.资源处理器各个动作如图:
为什么要自己处理资源路由验证?
这种资源路由无法使用laravel的全局范围内的路由参数正则表达式校验,因为定义这种校验规则需要写死一个参数名,如下:
/**
* 定义路由模型绑定,模式过滤器等
*
* @param \Illuminate\Routing\Router $router
* @return void
* @translator https://xueyuanjun.com
*/
public function boot()
{
Route::pattern('id', '[0-9]+');
parent::boot();
}
所以想要全局统一验证这个资源路由中id格式是否正确,不能用这个方法.
可行的方法有:
二选一即可.
1.通过写中间件进行校验
...
public function handle(Request $request, Closure $next)
{
$route = $request->route();
//检查资源路由器上的id,
//如:Route::resource("shop", 'ShopController'); ,请求shop/111时,如果111是非数字字符,则会走此校验
$actionMethod = $route->getActionMethod();
if ($actionMethod == "show") {
$firstRouterParam = Arr::first(($route->parameters()));
if ($firstRouterParam) {
if (!preg_match('/\d/', $firstRouterParam)) {
//ResourceException 是我自己封装的异常
throw new ResourceException("无效的查询参数:".$firstRouterParam);
//或者 App::abort(404);
// throw new Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
}
}
}
}
...
2. 通过重写异常处理者处理
重写异常处理者 Illuminate\Foundation\Exceptions\Handler.
然后判断异常做特殊处理:
if ($exception instanceof QueryException) {
if (str_contains($exception->getMessage(), "Invalid text representation:")) {
$requestId = $exception->getBindings()[0] ?? "";
App::abort(404);
// Or this one
throw new Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
//我代码中是: throw new ResourceException("查询参数错误,无效的id:".$requestId);
} else {
throw $exception;
}
}
网友评论