想咨询一下不使用 dingo/API 如何实现路由的版本控制?

Route::get('v1/xxx', 'xxx@xxx');
Route::get('v2/xxx', 'xxx@xxx');

这种方式也可以实现版本控制,不过不太好。
希望能通过header来实现版本控制,只是不知道如何实现,求帮助。

理想的效果是 同一个路由,header不一样可以走入两个不同的控制器。

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 5

這部分因為我們公司要實作微服務,因此我有一些初步的想法,但未經過實作,供您參考看看
我們知道 Laravel 的 route 是在 RouteServiceProvider 中定義的

其中,我們會看到這樣一段程式碼

public function map()
    {
        $this->mapApiRoutes();

        $this->mapWebRoutes();

        //
    }
...
protected function mapApiRoutes()
    {
        Route::prefix('api')
            ->middleware('web')
            ->namespace($this->namespace)
            ->group(base_path('routes/api.php'));
    }

也就是說,只要我們能改變 $this->namespace 就可以改變不同 API 版本
再往下深入,會發現 map 這個方法被調用是在 Illuminate\Foundation\Support\Providers\RouteServiceProvider 中的 boot 方法

public function boot()
    {
        ...
            $this->loadRoutes();
        ...
    }
...
protected function loadRoutes()
    {
        if (method_exists($this, 'map')) {
            $this->app->call([$this, 'map']);
        }
    }

而這個 boot 方法被調用的時機又要回到我們的 RouteServiceProvider

public function boot()
    {
        //

        parent::boot();
    }

也就是說,只要我們能在 parent::boot() 執行之前,修改 $this->namespace 的值就能動態切換版本
基於以上,我們可以這樣做

public function boot()
    {
        $this->switchApiVersion();

        parent::boot();
    }
    ...
    protected function switchApiVersion(){
        switch(Request::header('Version')){
            case 'v1':
                $this->namespace = 'Api\V1';
        }
    }

因為我還沒進入實作,一直沒把這篇文章發出來
若樓主有成功的話再告訴我,我發成教學文跟大家分享?

6年前 评论

@leochien 感谢你的回答,还有个问题。

因为版本控制可能有一个特点是 v2新增的路由 v1是没有的,或者v2是可以删除掉v1的路由的。
按照你的办法,虽然访问不到会抛出404异常,不过我觉得可能不太友好。
其实我也有个想法,是每个版本的路由都拆分出一个文件(可以直接拷贝,再新增路由),
可以按照你上面的思路,判断header里面的version,动态载入routes文件,
但是有一个问题,这样不知如何用 route:catch 来缓存路由
6年前 评论

請問 v2 的路由 v1 不存在的話,拋出 404 異常不是很正確的回應嗎?
不過您的方案也蠻好的,將每個版本拆分文件
但 route:catch 的話,因為我沒有很深入了解他背後的實現方式,我也不知道這樣做會不會有什麼影響

6年前 评论

@leochien 404是对的,我说错了,按照你一开始的方案 ,是所有版本共用路由,那样会抛出 class not found 不是404。

6年前 评论

@cherrytools 確實是有您講的問題,沒有想到那麼深入?,看來我們的微服務之路還有很多挑戰?

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!