Skip to main content

实体服务 API 到文档服务 API 迁移参考

¥Entity Service API to Document Service API migration reference

在 Strapi 5 中,文档服务 API 取代了 Strapi v4 中的实体服务 API(参见 重大变更描述)。

¥In Strapi 5, the Document Service API replaces the Entity Service API from Strapi v4 (see breaking change description).

本页面旨在让开发者了解如何从实体服务 API 迁移,通过描述自定义代码中的哪些更改将由 升级工具 中的 codemods 处理,哪些更改必须手动处理。

¥The present page is intended to give developers an idea of how to migrate away from the Entity Service API, by describing which changes in custom code will be handled by codemods from the upgrade tool and which will have to be handled manually.

使用升级工具进行迁移

¥Migration using the upgrade tool

使用 升级工具 时,将运行 codemod 并处理 entityService 迁移的某些部分。

¥When using the upgrade tool, a codemod is run and handles some parts of the entityService migration.

提醒

codemod 仅更改函数调用和一些参数。这不能被视为完整的迁移,因为 codemod 永远无法将 entityId 转换为 documentId

¥The codemod is only changing the function calls and some parameters. This can not be considered as a complete migration as the codemod will never be able to convert an entityId into a documentId.

Codemod 范围

¥Codemod scope

以下列表解释了 codemod 自动处理的内容(✅)、codemod 未处理的内容且必须 100% 手动处理的内容(❌)以及 codemod 运行后仍需要手动干预的内容(🚧):

¥The following list explains what is automatically handled by the codemod (✅), what is not handled by the codemod and must be handled 100% manually (❌) and what will still require manual intervention after the codemod has run (🚧):

话题由 codemod 处理?要执行的手动步骤
代码结构✅ 是的没什么。
代码结构会自动迁移。
publicationState 被删除,改为 status✅ 是的没什么。
codemod 会自动对其进行转换。
使用 documentId 代替 Strapi v4 唯一标识符🚧 部分:
  • codemod 将新的 documentId 属性添加到你的代码中,因为 documentId 是 Strapi 5 中使用的新唯一标识符。
  • 但实际的 documentId 值无法猜测,因此在 codemod 运行后,你会在代码中找到 __TODO__ 占位符值。
👉 __TODO__ 占位符值需要手动更新。

例如,你可能会将
documentId: "__TODO__"
更改为
documentId: "ln1gkzs6ojl9d707xn6v86mw" 之类的内容。
更新 published_at 以触发发布❌ 未处理。
👉 更新你的代码以改用文档服务 API 的新 publish()unpublish()discardDraft() 方法。

函数调用迁移示例

¥Examples of function calls migration

以下示例显示了升级工具中的 codemod 如何更新各种函数调用的代码。

¥The following examples show how the codemod from the upgrade tool updates the code for various function calls.

findOne

之前:

¥Before:

strapi.entityService.findOne(uid, entityId);


之后:

¥After:

strapi.documents(uid).findOne({
documentId: "__TODO__"
});

findMany

之前:

¥Before:

strapi.entityService.findMany(uid, {
fields: ["id", "name", "description"],
populate: ["author", "comments"],
publicationState: "preview",
});

之后:

¥After:

strapi.documents(uid).findMany({
fields: ["id", "name", "description"],
populate: ["author", "comments"],
status: "draft",
});

create

之前:

¥Before:

strapi.entityService.create(uid, {
data: {
name: "John Doe",
age: 30,
},
});

之后:

¥After:

strapi.documents(uid).create({
data: {
name: "John Doe",
age: 30,
},
});

update

之前:

¥Before:

strapi.entityService.update(uid, entityId, {
data: {
name: "John Doe",
age: 30,
}
});

之后:

¥After:

strapi.documents(uid).update({
documentId: "__TODO__",
data: {
name: "John Doe",
age: 30,
}
});

delete

之前:

¥Before:

strapi.entityService.delete(uid, entityId);


之后:

¥After:

strapi.documents(uid).delete({
documentId: "__TODO__"
});

count

之前:

¥Before:

strapi.entityService.count(uid);

之后:

¥After:

strapi.documents(uid).count();

手动迁移

¥Manual migration

  • 喜欢手动迁移的用户可以通过复制 codemod 的操作来实现(请参阅 codemod 范围函数调用示例 以供参考)。

    ¥Users who prefer to manually migrate can do so by replicating what the codemod does (see codemod scope and function calls examples for reference).

  • 在 Strapi v4 中,挂接到 redux 存储以调整 RBAC 权限的插件开发者需要根据所述更改更新其代码。以下示例让你了解它们的工作原理,更多信息可以在专用的 文档服务中间件文档 中找到:

    ¥Plugin developers who use Entity Service decorators in their code must replace them by Document Service middlewares. The following example gives you an idea of how they work, and additional information can be found in the dedicated Document Service middlewares documentation:

    在 Strapi v4 中:

    ¥In Strapi v4:

    strapi.entityService.decorate((service) => {

    return Object.assign(service, {

    findOne(entityId, params = {}) {
    // e.g., exclude soft deleted content
    params.filters = { ...params.filters, deletedAt: { $notNull: true } }
    return service.findOne(entityId, params)
    }
    });
    })

    在 Strapi 5 中

    ¥In Strapi 5

    strapi.documents.use((ctx, next) => {
    if (ctx.uid !== "api::my-content-type.my-content-type") {
    return next();
    }

    if (ctx.action === 'findOne') {
    // customization
    ctx.params.filters = { ...params.filters, deletedAt: { $notNull: true } }
    const res = await next();
    // do something with the response if you want
    return res;
    }

    return next();
    });
  • 更新单一类型上 findMany() 的自定义代码,同时考虑到:

    ¥Update your custom code for findMany() on single types, taking into account that:

    • 在 Strapi v4 中,findMany() 函数在单个类型上调用时返回单个项目。

      ¥In Strapi v4, the findMany() function returns a single item when called on a single type.

    • 在 Strapi 5 中,findMany() 函数是通用的,并且始终返回数组,无论是在单个类型还是在集合类型上调用。要使用 findMany() 调用获取单一类型的数据,请从返回的数组中提取第一个项目。

      ¥In Strapi 5, the findMany() function is generic and always returns arrays, whether called on a single type or on a collection type. To get data for a single type with a findMany() call, extract the first item from the returned array.