v4 代码迁移:更新内容类型架构
¥v4 code migration: Updating content-type schemas
本指南是 v4 代码迁移指南 的一部分,旨在帮助你将 Strapi 应用的代码从 v3.6.x 迁移到 v4.0.x
¥This guide is part of the v4 code migration guide designed to help you migrate the code of a Strapi application from v3.6.x to v4.0.x
Strapi v4 中的模型已被彻底修改:模型文件位于 /content-types/ 文件夹中,各种键和设置已被删除,并且关系语法已完全更改。
¥Models in Strapi v4 have been completely overhauled: model files are located in /content-types/ folders, various keys and settings have been removed, and the relation syntax has completely changed.
迁移到 Strapi v4 需要:
¥Migrating to Strapi v4 requires:
和 更新生命周期钩子。
¥and updating lifecycle hooks.
将模型转换为内容类型
¥Convert models to content-types
Strapi v3 在 models 文件夹中找到的 <model-name>.settings.json 文件中声明模型。
¥Strapi v3 declares models in <model-name>.settings.json files found in a models folder.
在 Strapi v4 中,content-types 在 ./src/api/<apiName>/content-types/<contentTypeName> 文件夹中的 schema.json 文件中声明。schema.json 文件引入了一些新属性(请参阅 模式文档)。
¥In Strapi v4, content-types are declared in schema.json files found in ./src/api/<apiName>/content-types/<contentTypeName> folder. The schema.json files introduce some new properties (see schema documentation).
内容类型可以使用 交互式 CLI 命令 strapi generate 自动创建。
¥Content-types can be created automatically with the interactive CLI command strapi generate.
要将 Strapi v3 模型转换为 v4 内容类型:
¥To convert Strapi v3 models to v4 content-types:
将项目根目录下的
./api文件夹移动到./src中:¥Move the
./apifolder at the root of your project into./src:mkdir src # Only if you haven't created the `./src` folder
mv api/ src/api/将每个内容类型
models文件夹移动/重命名为./src/api/<apiName>/content-types/:¥Move/rename each content-types
modelsfolder to./src/api/<apiName>/content-types/:mv src/api/<apiName>/models/ src/api/<apiName>/content-types/
Strapi 代码模块 可用于将 v3 模型转换为 v4 内容类型。
¥Strapi codemods can be used to convert v3 models to v4 content-types.
将每个模型的
<modelName>.settings.json文件移动/重命名为./src/api/<apiName>/content-types/<contentTypeName>/schema.json文件。¥Move/rename each model's
<modelName>.settings.jsonfile to./src/api/<apiName>/content-types/<contentTypeName>/schema.jsonfiles.在每个
<contentTypeName>/schema.json文件中,更新info对象,现在需要声明 3 个新的singularName、pluralName和displayName键并遵守一些大小写格式约定:¥In each
<contentTypeName>/schema.jsonfile, update theinfoobject, which now requires declaring the 3 newsingularName,pluralNameanddisplayNamekeys and respecting some case-formatting conventions:./src/api/<apiName>/content-types/<contentTypeName>/schema.json
// ...
"info": {
"singularName": "content-type-name", // kebab-case required
"pluralName": "content-type-names", // kebab-case required
"displayName": "Content-type name",
"name": "Content-type name",
};
// ...
更新内容类型关系
¥Updating content-type relations
Strapi v3 使用模型设置中的 via、model 和 collection 属性定义内容类型之间的关系。
¥Strapi v3 defines relations between content-types with the via, model and collection properties in the model settings.
在 Strapi v4 中,关系应在内容类型的 schema.json 文件中明确描述(参见 关系文档)。
¥In Strapi v4, relations should be explicitly described in the schema.json file of the content-types (see relations documentation).
如果内容类型有关系,则需要通过更新内容类型的 schema 来手动将它们迁移到 Strapi v4。
¥If the content-type has relations, it's required to manually migrate them to Strapi v4, by updating the schema of the content-types.
要更新内容类型关系,请使用以下过程更新每个内容类型的 ./src/api/<apiName>/content-types/<contentTypeName>/schema.json 文件:
¥To update content-type relations, update the ./src/api/<apiName>/content-types/<contentTypeName>/schema.json file for each content-type with the following procedure:
通过将
type属性值设置为"relation"来显式声明关系。¥Declare the relation explicitly by setting the
typeattribute value to"relation".使用
relation属性定义关系类型。
该值应该是以下可能选项中的字符串:"oneToOne"、"oneToMany"、"manyToOne"或"manyToMany"。¥Define the type of relation with the
relationproperty.
The value should be a string among the following possible options:"oneToOne","oneToMany","manyToOne"or"manyToMany".使用
target属性定义内容类型目标。
该值应该是遵循api::api-name.content-type-name或plugin::plugin-name.content-type-name语法约定的字符串。¥Define the content-type target with the
targetproperty.
The value should be a string following theapi::api-name.content-type-nameorplugin::plugin-name.content-type-namesyntax convention.(可选)在 双向关系 中,为每个内容类型定义
mappedBy和inversedBy属性。¥(optional) In bidirectional relations, define
mappedByandinversedByproperties on each content-type.
Example of all possible relations between an article and an author content-types:
// Attributes for the Article content-type
// oneWay relation
"articleHasOneAuthor": {
"type": "relation",
"relation": "oneToOne",
"target": "api::author.author"
},
// oneToOne relation
"articleHasAndBelongsToOneAuthor": {
"type": "relation",
"relation": "oneToOne",
"target": "api::author.author",
"inversedBy": "article"
},
// oneToMany relation
"articleBelongsToManyAuthors": {
"type": "relation",
"relation": "oneToMany",
"target": "api::author.author",
"mappedBy": "article"
},
// manyToOne relation
"authorHasManyArticles": {
"type": "relation",
"relation": "manyToOne",
"target": "api::author.author",
"inversedBy": "articles"
},
// manyToMany relation
"articlesHasAndBelongsToManyAuthors": {
"type": "relation",
"relation": "manyToMany",
"target": "api::author.author",
"inversedBy": "articles"
},
// manyWay relation
"articleHasManyAuthors": {
"type": "relation",
"relation": "oneToMany",
"target": "api::author.author"
}
// Attributes for the Author content-type
// inversed oneToMany relation
"article": {
"type": "relation",
"relation": "manyToOne",
"target": "api::article.article",
"inversedBy": "articleBelongsToManyAuthors"
},
// inversed manyToOne or manyToMany relation
"articles": {
"type": "relation",
"relation": "manyToMany",
"target": "api::article.article",
"inversedBy": "articlesHasAndBelongsToManyAuthors"
}
更新生命周期钩子
¥Updating lifecycle hooks
Strapi v3 在 models 文件夹中找到的 <model-name>.js 文件中声明模型生命周期钩子。
¥Strapi v3 declares model lifecycle hooks in <model-name>.js files found in a models folder.
在 Strapi v4 中,生命周期钩子 在 ./src/api/<apiName>/content-types/<contentTypeName>/ 文件夹中的 lifecycles.js 文件中声明。lifecycles.js 文件在结构上类似,但不再需要将生命周期封装在 lifecycles: {} 对象中,并且新参数将传递给钩子(请参阅 生命周期钩子文档)。
¥In Strapi v4, lifecycle hooks are declared in a lifecycles.js file found in ./src/api/<apiName>/content-types/<contentTypeName>/ folder. The lifecycles.js file is similar in structure but no longer needs lifecycles to be wrapped in a lifecycles: {} object, and new parameters are passed to the hooks (see lifecycle hooks documentation).
要将 Strapi v3 模型生命周期钩子转换为 v4 生命周期钩子:
¥To convert Strapi v3 model lifecycle hooks to v4 lifecycle hooks:
将
./src/api/<apiName>/content-types/中的<modelName>.js移动/重命名到你在内容类型迁移的 步骤 3 中创建的正确内容类型文件夹,同时将其名称更改为lifecyles.js:¥Move/rename the
<modelName>.jsin./src/api/<apiName>/content-types/to the proper content-type folder you created in step 3 of the content-type migration, while changing its name tolifecyles.js:cd src/api/<apiName>
mv content-types/<modelName>.js content-types/<contentTypeName>/lifecycles.js在每个
lifecycles.js文件中,调整结构并将每个生命周期移到旧lifecycles: {}对象之外,如下例所示:¥In each
lifecycles.jsfile, adjust the structure and move each lifecycle outside of the legacylifecycles: {}object, like in the following examples:
Example of a Strapi v3 lifecycles file:
```jsx
module.exports = {
lifecycles: {
async beforeCreate() {
// ...
},
},
};
```
Example of a Strapi v4 lifecycles file:
```jsx
module.exports = {
async beforeCreate() {
// ...
},
};
```
重构模型生命周期钩子以使用新的输入变量(参见 钩子
event对象文档):¥Refactor the model lifecycle hooks to use the new input variables (see hook
eventobject documentation):
所有 Strapi v3
params都放置在 Strapi v4 中的event对象中(例如event.params)。¥All Strapi v3
paramsare placed in aneventobject in Strapi v4 (e.g.event.params).嵌套在此 params 对象内部,你可以访问
data、select(也称为字段)、where(也称为过滤器)、orderBy(也称为排序)、limit、offset和populate。¥Nested inside of this params object, you have access to
data,select(also known as fields),where(also known as filters),orderBy(also known as sort),limit,offset, andpopulate.或者,对于所有
after*事件,你可以访问包含数据库结果响应的event.result。¥Optionally, for all
after*events, you have access toevent.resultthat contains the result response from the database.
Example of a Strapi v3 lifecycle:
module.exports = {
lifecycles: {
async beforeCreate(data) {
data.isTableFull = data.numOfPeople === 4;
},
async afterCreate(result, data) {
// do something with result
}
},
};
Example of a Strapi v4 lifecycle:
module.exports = {
beforeCreate(event) {
let { data, where, select, populate } = event.params;
data.isTableFull = data.numOfPeople === 4;
},
afterCreate(event) {
const { result, params } = event;
// do something to the result
},
};
Strapi 的 迁移后端代码 到 v4 还需要至少迁移 Strapi 服务器的核心功能,例如 configuration、dependencies、routes、controllers 和 services。
¥Migrating the backend code of Strapi to v4 also requires to at least migrate the core features of the Strapi server, such as the configuration, dependencies, routes, controllers, and services.