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

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

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

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

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 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年前 评论

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