登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  php教程

Laravel 13 JSON API 资源怎么迁移:响应结构与客户端兼容边界

来源:17golang原创

时间:2026-08-31 17:08:38 236浏览 收藏

Laravel 13 的 JSON:API Resource 迁移,真正容易出问题的地方不是把类名改成 JsonApiResource,而是客户端突然面对新的 datatypeidrelationshipslinks 结构。稳妥的做法是先把资源转换层固定下来,再用兼容适配层承接旧响应,最后逐项切换客户端。

如果旧客户端还依赖扁平字段,就不要一次性替换响应外壳;先让 JSON:API Resource 成为唯一事实来源,再在边界处保留一层可删除的旧格式适配。

实践要点

  • Resource 负责模型到响应文档的转换,不等于直接暴露模型全部字段。
  • 集合响应、单条响应和关系字段必须分别确认,不能只测一个订单详情。
  • 迁移期间把旧格式适配放在控制器边界,避免 Resource 同时维护两套业务规则。
  • 兼容验证至少覆盖字段路径、空关系、分页与客户端缓存键。

先确认失配发生在响应外壳还是字段语义

Laravel 官方文档把 Eloquent Resource 定义为模型与 JSON 响应之间的转换层;Laravel 13 的更新说明又明确列出了 JSON:API resources。两者合起来,迁移重点是响应契约,而不是把数据库模型直接序列化。

假设旧接口返回:

{
  "id": 42,
  "status": "paid",
  "total": "199.00"
}

新客户端可能期待:

{
  "data": {
    "type": "orders",
    "id": "42",
    "attributes": {
      "status": "paid",
      "total": "199.00"
    }
  }
}

这不是简单的字段改名:旧客户端读取 response.id,新客户端读取 response.data.id;缓存键、列表解包、关系预加载也可能随之变化。先列出调用方的读取路径,才能判断是需要适配,还是可以直接升级。

旧客户端为什么会在迁移后失配

把迁移拆成三层看会更容易定位:旧客户端(Legacy Client)只知道旧字段路径,兼容适配层(Compatibility Adapter)负责保留旧响应形状,JSON:API Resource 负责稳定地产出新契约。适配层不应重新查询数据库,也不应复制订单状态判断。

旧客户端、兼容适配层与 JSON API Resource 的静态关系框图,展示 data、type、id 字段边界
图1:旧客户端只通过兼容适配层读取新资源,data、type、id 仍由 JSON:API Resource 统一定义。

一个简单的边界写法如下:

public function show(Order $order): JsonResponse
{
    $resource = (new OrderJsonApiResource($order))->response();

    return response()->json([
        'id' => $order->getKey(),
        'status' => $resource->getData(true)['data']['attributes']['status'],
        'total' => $resource->getData(true)['data']['attributes']['total'],
    ]);
}

这段兼容代码只是过渡示例。生产代码应把旧格式转换器单独命名并覆盖测试,避免控制器逐渐变成第二个 Resource。

把订单资源写成稳定的 JSON:API 契约

Laravel 13 文档的 JSON:API Resource 章节把属性、关系、资源类型与 ID、稀疏字段集、包含关系、链接和元数据分开说明。迁移时也按这个边界写,先只暴露客户端真正需要的订单字段。这里的 Order Model 只提供订单状态、金额和关系数据,资源类负责决定哪些内容进入响应:

use Illuminate\Http\Request;
use Illuminate\Http\Resources\JsonApi\JsonApiResource;

class OrderJsonApiResource extends JsonApiResource
{
    public $attributes = [
        'status',
        'total',
    ];

    public $relationships = [
        'customer',
        'items',
    ];

    public function toType(Request $request): string
    {
        return 'orders';
    }
}

Laravel 13 文档给出的 JSON:API Resource 生成方式是 make:resource --json-api,生成类使用 $attributes$relationships 声明边界;typeid 默认可由资源类名与模型主键解析,需要不同命名时再覆盖 toTypetoId。订单金额保留字符串,是为了避免客户端把金额当作二进制浮点数处理。

订单模型、JSON API 资源转换层、属性和关系之间的静态结构框图
图2:订单模型进入资源转换层后,被拆成属性与关系;图中字段就是本节代码需要稳定测试的边界。

单条资源、资源集合和关系要分开回归

单条订单通过 Resource 返回,列表则通过资源集合返回。不要因为详情页成功,就认为列表页已经兼容;集合还会引入分页、集合级 links/meta 以及空列表行为。

Route::get('/api/orders/{order}', function (Order $order) {
    return new OrderJsonApiResource($order);
});

Route::get('/api/orders', function () {
    return OrderJsonApiResource::collection(
        Order::query()->latest()->paginate(20)
    );
});

关系字段也要单独核对。只在请求明确需要时加载 customeritems,并把“未加载”和“确实为空”区分开;否则客户端可能把缺失关系误判成空关系,或者触发额外查询。

兼容切换怎样留下回滚点

建议把切换拆成三个可观测版本:第一阶段 Resource 只服务新路径;第二阶段旧路径经过适配器读取同一 Resource;第三阶段客户端完成切换后删除适配器。每阶段都保留同一订单样本,比较字段路径、类型、空值、关系和分页链接。

回归测试至少覆盖:

  • 单条订单的 data.typedata.id 是否稳定;
  • 金额、状态和时间字段是否保持约定类型;
  • 无客户、无明细、空列表时的响应形状;
  • 分页链接和元数据是否仍能被客户端读取;
  • 旧客户端的缓存键是否仍能通过适配器命中。

如果发现新 Resource 需要查询额外字段,不要在适配器里偷偷补查询;回到控制器或查询对象处理预加载,再让 Resource 只负责呈现。

常见问题与最终检查

能不能直接把 Eloquent 模型返回给客户端?

不建议。官方文档强调 Resource 提供更细粒度的 JSON 序列化控制。直接返回模型会把字段白名单、关系加载和版本兼容交给隐式行为。

JSON:API Resource 会自动兼容旧响应吗?

不会。它解决的是新的资源响应表达;旧客户端能否继续工作,取决于适配层或客户端迁移。不要把框架能力当成协议转换器。

什么时候可以删除兼容适配层?

当调用方清单已经切换,单条、集合、关系、分页和空值测试都通过,并且观察窗口内没有旧字段路径请求时,再删除。删除前保留一次接口契约快照,方便回滚。

小结

Laravel 13 JSON:API Resource 的迁移,核心是把响应契约从模型序列化中抽出来:Resource 管字段与关系,集合管列表语义,适配层管旧客户端。先统一事实来源,再逐步切换边界,才能让新协议带来的结构变化变成可验证、可回滚的工程改动。

参考:Laravel 官方 March Product UpdatesLaravel 13 Eloquent: API Resources

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>