Entity Service API 到 Document Service API 迁移参考
页面摘要: Document Service API 在 Strapi 5 中取代了 Entity Service API。升级工具的 codemod 会自动转换函数调用以及将
publicationState转换为status,但对于documentId值以及publish()、unpublish()等发布方法,仍需手动干预。
在 Strapi 5 中,Document Service API 取代了 Strapi v4 的 Entity Service API(参见 破坏性变更说明)。
本页面的目的是让开发者了解如何迁移离开 Entity Service API,通过说明自定义代码中的哪些变更会由 upgrade tool(升级工具)的 codemods 处理、哪些必须手动处理。
使用升级工具进行迁移
使用 upgrade tool(升级工具)时,会运行一个 codemod 来处理 entityService 迁移的部分工作。
codemod 只会更改函数调用和某些参数。这不能被视作一次完整的迁移,因为 codemod 永远无法将 entityId 转换为 documentId。
Codemod 适用范围
以下列表说明了什么由 codemod 自动处理(✅)、什么未被 codemod 处理而必须 100% 手动完成(❌),以及什么在 codemod 运行后仍需手动干预(🚧):
| 主题 | 是否由 codemod 处理? | 需执行的手动步骤 |
|---|---|---|
| 代码结构 | ✅ 是 | 无。 |
| 代码结构会被自动迁移。 | ||
弃用 publicationState 改用 status | ✅ 是 | 无。 |
| codemod 会自动转换它。 | ||
使用 documentId 而非 Strapi v4 的唯一标识符 | 🚧 部分: |
- codemod 会向你的代码中添加新属性
documentId,因为documentId是 Strapi 5 中应使用的新唯一标识符。 - 但实际的
documentId值无法被猜测,因此在 codemod 运行后,你会在代码中找到__TODO__占位符值。 | 👉__TODO__占位符值需要手动更新。
例如,你可能需要将
documentId: "__TODO__"
改为类似
documentId: "ln1gkzs6ojl9d707xn6v86mw" 的值。 |
| 更新 published_at 以触发发布 | ❌ 未处理。
| 👉 更新你的代码,改用 Document Service API 新的 publish()、unpublish() 和 discardDraft() 方法。 |
函数调用迁移示例
以下示例展示了升级工具的 codemod 如何针对各种函数调用更新代码。
findOne
迁移前:
strapi.entityService.findOne(uid, entityId);
迁移后:
strapi.documents(uid).findOne({
documentId: "__TODO__"
});
findMany
迁移前:
strapi.entityService.findMany(uid, {
fields: ["id", "name", "description"],
populate: ["author", "comments"],
publicationState: "preview",
});
迁移后:
strapi.documents(uid).findMany({
fields: ["id", "name", "description"],
populate: ["author", "comments"],
status: "draft",
});
create
迁移前:
strapi.entityService.create(uid, {
data: {
name: "John Doe",
age: 30,
},
});
迁移后:
strapi.documents(uid).create({
data: {
name: "John Doe",
age: 30,
},
});
update
迁移前:
strapi.entityService.update(uid, entityId, {
data: {
name: "John Doe",
age: 30,
}
});
迁移后:
strapi.documents(uid).update({
documentId: "__TODO__",
data: {
name: "John Doe",
age: 30,
}
});
delete
迁移前:
strapi.entityService.delete(uid, entityId);
迁移后:
strapi.documents(uid).delete({
documentId: "__TODO__"
});
count
迁移前:
strapi.entityService.count(uid);
迁移后:
strapi.documents(uid).count();
手动迁移
-
偏好手动迁移的用户,可以通过复现 codemod 所执行的操作来完成(参见 codemod 适用范围 与 函数调用示例 作为参考)。
-
在其代码中使用 Entity Service 装饰器(decorators)的插件开发者,必须将它们替换为 Document Service 中间件(middlewares)。以下示例让你了解它们的工作方式,更多信息可在专属的 Document Service 中间件文档 中找到:
在 Strapi v4 中:
strapi.entityService.decorate((service) => { return Object.assign(service, { findOne(entityId, params = {}) { // 例如,排除软删除的内容 params.filters = { ...params.filters, deletedAt: { $notNull: true } } return service.findOne(entityId, params) } }); })在 Strapi 5 中
strapi.documents.use((ctx, next) => { if (ctx.uid !== "api::my-content-type.my-content-type") { return next(); } if (ctx.action === 'findOne') { // 自定义 ctx.params.filters = { ...params.filters, deletedAt: { $notNull: true } } const res = await next(); // 如需,对响应做一些处理 return res; } return next(); });
-
更新你对单一类型(single type)调用
findMany()的自定义代码,并考虑到以下差异:- 在 Strapi v4 中,对单一类型调用
findMany()函数时返回单个条目。 - 在 Strapi 5 中,
findMany()函数是通用的,无论对单一类型还是集合类型调用,都始终返回数组。若要使用findMany()调用获取单一类型的数据,请从返回的数组中提取第一个条目。
- 在 Strapi v4 中,对单一类型调用