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
./api
folder 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
models
folder 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.json
file to./src/api/<apiName>/content-types/<contentTypeName>/schema.json
files.在每个
<contentTypeName>/schema.json
文件中,更新info
对象,现在需要声明 3 个新的singularName
、pluralName
和displayName
键并遵守一些大小写格式约定:¥In each
<contentTypeName>/schema.json
file, update theinfo
object, which now requires declaring the 3 newsingularName
,pluralName
anddisplayName
keys 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
type
attribute value to"relation"
.使用
relation
属性定义关系类型。
该值应该是以下可能选项中的字符串:"oneToOne"
、"oneToMany"
、"manyToOne"
或"manyToMany"
。¥Define the type of relation with the
relation
property.
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
target
property.
The value should be a string following theapi::api-name.content-type-name
orplugin::plugin-name.content-type-name
syntax convention.(可选)在 双向关系 中,为每个内容类型定义
mappedBy
和inversedBy
属性。¥(optional) In bidirectional relations, define
mappedBy
andinversedBy
properties 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>.js
in./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.js
file, 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
event
object documentation):
所有 Strapi v3
params
都放置在 Strapi v4 中的event
对象中(例如event.params
)。¥All Strapi v3
params
are placed in anevent
object 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.result
that 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.