拦截Laravel路由

gvh*_*een 2 php laravel laravel-routing laravel-5 laravel-middleware

我正忙于在Laravel 5.1中构建Restful API,其中API版本通过标头传递.这样我就可以对功能进行版本控制,而不是复制和粘贴整个路径组并增加版本号.

我遇到的问题是我想要版本化的方法,IE:

public function store_v1 (){  }
Run Code Online (Sandbox Code Playgroud)

我在路由中添加了一个中间件,我从头部捕获了版本,但现在需要修改请求以从控制器中选择正确的方法.

应用程序/ HTTP/routes.php文件

Route::group(['middleware' => ['apiversion']], function()
{
    Route::post('demo', 'DemoController@store');
}
Run Code Online (Sandbox Code Playgroud)

应用程序/ HTTP /中间件/ ApiVersionMiddleware.php

public function handle($request, Closure $next)
{
    $action = app()->router->getCurrentRoute()->getActionName();

    //  dd($action)
    //  returns "App\Http\Controllers\DemoController@store"
}
Run Code Online (Sandbox Code Playgroud)

从这里开始,我会将标题版本附加到$ action,然后通过$ request传递它,以便它到达正确的方法.

嗯,无论如何这就是理论.

关于如何将行动注入路线的任何想法?

jed*_*ylo 6

我认为中间件可能不是最好的地方.您可以访问该路由,但它不提供修改将被调用的控制器方法.

更简单的选择是注册一个自定义路由调度程序,它根据请求和路由处理调用控制器方法的逻辑.它可能看起来像这样:

<?php

class VersionedRouteDispatcher extends Illuminate\Routing\ControllerDispatcher {
  public function dispatch(Route $route, Request $request, $controller, $method)
  {
    $version = $request->headers->get('version', 'v1'); // take version from the header
    $method = sprintf('%s_%s', $method, $version); // create target method name
    return parent::dispatch($route, $request, $controller, $method); // run parent logic with altered method name
  }
}
Run Code Online (Sandbox Code Playgroud)

获得此自定义调度程序后,请在AppServiceProvider中注册它:

public function register() {
  $this->app->singleton('illuminate.route.dispatcher', VersionedRouteDispatcher::class);
}
Run Code Online (Sandbox Code Playgroud)

这样,您将使用自己的路由调度程序覆盖默认路由调度程序,该调度程序将使用从请求标头中获取的版本对控制器方法名称进行后缀.