不建议使用文档服务 API 更新可重复组件

页面摘要: 在 Strapi 5 中,文档的草稿版本和已发布版本使用不同的数字组件 id。重用已发布响应中的 id 来更新草稿通常会失败。在出现稳定的组件标识之前,建议替换完整的组件数组(或针对草稿 id 进行编辑)。

在 Strapi 5 中,不建议通过重用已发布 API 响应中的组件 id 来更新可重复组件,原因在于草稿与发布功能与文档服务 API 的交互方式。

本页面是破坏性变更数据库的一部分,提供有关该破坏性变更的信息,以及从 Strapi v4 迁移到 Strapi 5 的附加说明。

破坏性变更说明

在 Strapi v4 中

你可以通过传入数字 id 来部分更新可重复组件。

在 Strapi 5 中

文档使用稳定的 documentId,但嵌套组件仍使用与状态相关的数字 id。发布操作会创建新的组件行,因此同一区块的草稿版本和已发布版本具有不同的 id。你不能将已发布的组件 id 当作文档级标识符对待。

迁移

本节汇总了关于该破坏性变更的有用说明和操作步骤。

说明

启用草稿与发布后,典型的内容 API 流程如下:

// 请求:内容 API 默认返回已发布版本
GET /api/articles

// 响应(已发布)
{
  data: {
    documentId: '…',
    components: [
      { id: 2, name: 'component-1' },
      { id: 4, name: 'component-2' },
    ],
  },
}

使用那些已发布的 id 进行更新会写入草稿,而草稿具有不同的组件行 id:

PUT /api/articles/{documentId}
{
  data: {
    components: [
      { id: 2, name: 'component-1-updated' }, // 已发布 id,对草稿通常无效
    ],
  },
}

这通常失败并出现类似 Some of the provided components in components are not related to the entity 的错误,因为 id: 2 并未链接到草稿条目。这与 REST API 响应中组件和动态区域不再返回 id 这一变更有关。

文档服务 在读取/更新时默认针对草稿,因此当你使用草稿组件 id 时,按 id 进行原地更新可以生效(在内容管理器中也一样)。陷阱在于将已发布 id 与草稿写入混用。

推荐的变通方案

在出现稳定的嵌套标识之前,请使用以下方案之一。

1. 替换完整的组件数组(内容 API 推荐)

省略组件 id 并发送完整的期望列表。Strapi 会在草稿上重新创建这些组件。这是面向 REST/GraphQL 客户端(它们只看到已发布数据)的受支持且不易出错的方案:

// 文档服务
await strapi.documents('api::article.article').update({
  documentId,
  data: {
    components: [
      { name: 'component-1-updated' },
      { name: 'component-2' },
    ],
  },
});
// REST 内容 API
PUT /api/articles/{documentId}
{
  "data": {
    "components": [
      { "name": "component-1-updated" },
      { "name": "component-2" }
    ]
  }
}
TIP

包含所有希望保留的组件。数组中省略的条目会从草稿中移除。

2. 针对草稿组件 id 进行编辑(文档服务 / 管理面板风格)

如果你控制后端(自定义路由、脚本、文档服务),先加载草稿,再使用这些 id 进行更新:

const draft = await strapi.documents('api::article.article').findOne({
  documentId,
  status: 'draft',
  populate: ['components'],
});

await strapi.documents('api::article.article').update({
  documentId,
  data: {
    components: draft.components.map((component) =>
      component.id === targetDraftId
        ? { id: component.id, name: 'component-1-updated' }
        : { id: component.id, name: component.name }
    ),
  },
});

不要在此模式下重用默认内容 API GET(已发布)返回的 id。

3. 禁用草稿与发布

如果在内容类型上禁用了草稿与发布,则只有一组组件行,因此基于 id 的更新问题较少。但为了客户端代码更简单,仍建议优先使用完整数组替换模式。