【问题标题】:A different way to version api output with laravel?使用 laravel 版本化 api 输出的另一种方法?
【发布时间】:2018-11-21 15:11:05
【问题描述】:

我要...

  1. 使用 Http/Json/V1/MyModel.php 扩展我的 App/Orm/MyModel.php,这样我就可以将 $appends、$hides、toArray() 整齐地隐藏在 V1 中
  2. V1 的命名空间和一些路由前缀
  3. 可能会为路由模型绑定做一些自定义解析器

我在想……真的吗?他们还没有建立这个......我在这里错过了什么?必须有一个快速的,交钥匙的。我很想知道其他人是如何做到这一点的,所以请插话。

【问题讨论】:

  • 您已经需要 v2 了吗?很可能你不会通过 v1,所以只要坚持使用非版本化 API,到时候你可以重构。
  • @Kyslik 只是提前计划。
  • 浪费你的时间,想象一下你有 v1 并且它做得很好;现在您决定开发 v2;过程是什么?您需要复制“所有文件”并更改命名空间和上面的其他内容(中间件/服务提供者/路由),现在您可以开始使用 v2.2 了。你不能在以后真正需要的时候这样做吗? v1 没有特殊的命名空间,v2 就是这样。
  • @Kyslik 这仅用于输出版本控制。
  • @Kyslik 如果您真的在明年签到,那将非常有趣 - 哈哈。如果我发现自己仍然坐在同一个地方敲击键盘,我会感到非常难过。

标签: laravel api versioning


【解决方案1】:

尝试资源而不是模型

查看资源: https://laravel.com/docs/5.7/eloquent-resources

并将您的逻辑添加到资源中,以便根据 API 版本显示不同版本的模型。您仍然可以使用$appends$hidden

通过这种方法,我们返回模型的资源而不是模型本身。

以下是不同 API 版本的 UserResource 示例:

class UserResource extends JsonResource
{
    private $apiVersion;

    public function __construct($resource, int $apiVersion = 2) {
        $this->apiVersion = $apiVersion; // OPTION 1: Pass API version in the constructor
        parent::__construct($resource);
    }

    public function toArray($request): array
    {
        // OPTION 2: Get API version in the request (ideally header)
        // $apiVersion = $request->header('x-api-version', 2);

        /** @var User $user */
        $user = $this->resource;

        return [
            'type' => 'user',
            'id' => $user->id,
            $this->mergeWhen($this->apiVersion < 2, [
                'name' => "{$user->first_name} {$user->last_name}",
            ], [
                'name' => [
                    'first' => $user->first_name,
                    'last' => $user->last_name
                ],
            ]),
            'score' => $user->score,
        ];
    }
}

你可以打电话:

$user = User::find(5);
return new UserResource($user);

如果您需要不同的连接,您可以这样做:

$user = User::on('second_db_connection')->find(5);

所以 V1 API 得到:

{
    id: 5,
    name: "John Smith",
    score: 5
}

而 V2 API 获得:

{
    id: 5,
    name: {
         first: "John",
         last: "Smith",
    },
    score: 5
}

现在,如果稍后您想将分数重命名为数据库中的点,并且在 API 的 V3 中您还想更改 JSON 输出,但保持向后兼容性,您可以这样做:

   $this->mergeWhen($this->apiVersion < 3, [
       'score' => $user->points,    
   ], [
       'points' => $user->points,
   ])

前缀路线

您可以轻松地为这里提到的路由添加前缀:https://laravel.com/docs/5.7/routing#route-group-prefixes

Route::prefix('v1')->group(function () {
    Route::get('users', function () {
        // ...
    });
});

显式路由模型绑定

要做自定义路由模型绑定看看:https://laravel.com/docs/5.7/routing#route-model-binding

例如

Route::bind('user', function ($value) {
    return App\User::where('name', $value)->first() ?? abort(404); // your customer logic
});

【讨论】:

  • Eloquent 资源在正确的轨道上,谢谢。看起来很有限,但有时限制可能是件好事。干杯!
  • @TarekAdam 如果解决了您的问题,请将此答案标记为正确
  • 仍在调查问题。
  • 又看了看,但我只是没有看到好处〜除了......它很轻。在缺点方面,我无法设置连接 - 这是一个交易破坏者,因为 Json 输出命名空间模型将从奴隶读取。
  • 知道了。您可以通过编辑数据库配置文件来指定不同的读/写连接,如下所述:laravel.com/docs/5.7/database#read-and-write-connections
猜你喜欢
  • 1970-01-01
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 2020-10-04
  • 1970-01-01
相关资源
最近更新 更多