由于我想在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.php
、v2-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
来确定相同的路由,稍后的路由将简单地覆盖以前的路由。因此,用上述代码按升序加载不同版本的路线将导致:
- 如果客户端版本为3。然后按升序加载api_v1、api_v2、api_v3。并且api_v4、api_v5…未加载
- 如果uri出现在1,3,10中,并且客户端版本为6。然后将使用v3中的路由,因为它覆盖了v1中的路由并且没有被v10覆盖,因为v10甚至没有被加载
- 如果一个uri出现在4,5中,并且客户端版本为2。那么它只是一个404,因为v4和v5没有加载