laravel中的Api版本控制:路由取决于“;接受“;头球


Api versioning in laravel: routing depending on the "Accept" Header

由于我想在accept头上激发端点,我创建了一个中间件来识别使用客户端的版本:

// ApiVersionMiddleware
public function handle($request, Closure $next)
{
    $route = $request->route();
    $actions = $route->getAction();
    $actions['uses'] = str_replace(
        '{api}',
        $request->header('api-version'),
        $actions['uses']
    );
    $route->setAction($actions);
    return $next($request);
}

然后我更改了默认的RouteServiceProvider名称空间:

class RouteServiceProvider extends ServiceProvider {
//  protected $namespace = 'App'Http'Controllers'; // default value
    protected $namespace = null;
        .
        .     
}

最后,在我的routes.php文件中,我有:

Route::group(['middleware' => 'api-version'], function()
{
    Route::resource('items', 'App'Http'Controllers'{api}'ItemsController', ['only' => ['show', 'index', 'store', 'destroy']]);
});

我尝试在HttpKernel类中注册中间件,而不是对路由定义进行分组,但没有成功。

我想知道是否有更好的方法来实现API版本控制。

  • 我希望每个版本都有一个routes.php文件:v1-routes.phpv2-routes.php等等
  • 我不喜欢为了访问{api}值而在routes.php中对路由定义进行分组的想法。有没有其他方法可以确定我应该解雇哪个管制员

谢谢。

我想你可以在你的routes.php上尝试这样的东西。我还没有测试过,但应该可以使用

switch (Request::header('api-version')) {
    case 'v2':
        include_once('routes_v2.php');
        break;
    default:
        include_once('routes_v1.php');
}

在route_v。。。。php文件按照您通常的方式定义路由。

更新

正确的方法是使用RouteServiceProvider的映射函数。您将只有两个路由文件。

您可以在dingo/api包中轻松管理多个版本的api。这会为你节省很多时间。

适用于那些只想要一些简单代码的人。这在默认的RouteServiceProvider中。只需添加几行即可。

$this->routes(function () {
            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
            $max_api_version = 6; // how many files should be loaded
            $all_headers = getallheaders(); // request object is not available. use php function
            $client_version =  intval($all_headers['Api-Version']??1);
            for ($i = 1; $i <= $max_api_version; $i++){
                $file_path = base_path('routes/api_v'.$i.'.php');
                if ($client_version >= $i && file_exists($file_path)){
                    Route::prefix('api')
                        ->group($file_path);
                }
            }
        });

在拉拉威尔,你不可能有两条相同的路线。Laravel将使用$method.$domain.$uri来确定相同的路由,稍后的路由将简单地覆盖以前的路由。因此,用上述代码按升序加载不同版本的路线将导致:

  1. 如果客户端版本为3。然后按升序加载api_v1、api_v2、api_v3。并且api_v4、api_v5…未加载
  2. 如果uri出现在1,3,10中,并且客户端版本为6。然后将使用v3中的路由,因为它覆盖了v1中的路由并且没有被v10覆盖,因为v10甚至没有被加载
  3. 如果一个uri出现在4,5中,并且客户端版本为2。那么它只是一个404,因为v4和v5没有加载