# 模型

由于 Strapi 是一个无头内容管理系统 (CMS),因此为内容创建数据结构是使用该软件最重要的方面之一。模型定义数据结构的表示形式。

Strapi中有2种不同类型的模型:

  • 内容类型,可以是集合类型或单个类型,具体取决于它们管理的条目数
  • 和作为可在多种内容类型中重用的数据结构的组件。

如果你刚刚开始,直接在管理面板中使用 Content-type Builder 能很方便地生成一些模型。用户界面接管了许多验证任务,并展示了可用于创建内容数据结构的所有选项。然后,可以使用本文档在代码级别查看生成的模型映射。

# 模型创建

内容类型和组件模型的创建和存储方式不同。

# 内容类型

以下方式可以创建 Strapi 中的内容类型:

内容类型使用以下文件:

  • schema.json 表示模型的 schema 定义。(使用任一方法创建内容类型时自动生成)
  • lifecycles.js 表示 lifecycle hooks。必须手动创建此文件。

这些模型文件存储在 ./src/api/[api-name]/content-types/[content-type-name]/中,在这些文件夹中找到的任何 JavaScript 或 JSON 文件都将作为内容类型的模型加载 (参见 project structure).

✏️ NOTE

在启用了 TypeScript 的项目中,可以使用 ts:generate-types 命令生成架构类型。

# 组件

无法使用 CLI 工具创建组件模型。使用 Content-type Builder 或手动创建它们。

组件模型存储在 ./src/components 文件夹中。每个组件都必须位于子文件夹中,以组件所属的类别命名(参见 项目结构)。

# 模型架构

schema.json 文件包括:

  • settings 例如,型表示的内容类型或应存储数据的表名
  • information 主要用于在管理面板中显示模型,并通过 REST 和 GraphQL API 访问它
  • attributes 描述了模型的数据结构
  • options 用于定义模型上的特定行为

# 模型设置

可以使用以下参数配置模型的常规设置:

参数 类型 描述
tableName String 应在其中存储数据的数据库表名称
kind

Optional,
only for content-types
String 定义内容类型是否为:
  • 集合类型 (collectionType)
  • 或单一类型 (singleType)
// ./api/[api-name]/content-types/restaurant/schema.json

{
  "kind": "collectionType",
  "tableName": "Restaurants_v1",
}

# 模型信息

模型架构中的 info 键描述用于在管理面板中显示模型并通过内容 API 访问模型的信息。它包括以下参数:

参数 类型 描述
displayName String 在管理面板中使用的默认名称
singularName String 内容类型名称的单数形式。
用于生成 API 路由和数据库/表集合。

应该是 kebab-case 命名
pluralName String 内容类型名称的复数形式。
用于生成 API 路由和数据库/表集合。

应该是 kebab-case 命名
description String 模型说明
icon

Optional,
only for Components
String FontAwesome (opens new window) (v5) 图标名称,用于管理面板中的组件图标
// ./src/api/[api-name]/content-types/restaurant/schema.json

  "info": {
    "displayName": "Restaurant",
    "singularName": "restaurant",
    "pluralName": "restaurants",
    "description": ""
  },

# 模型属性

模型的数据结构由属性列表组成。每个属性都有一个 type 参数,该参数描述其性质并将属性定义为一段简单的数据或 Strapi 使用的更复杂的结构。

有许多类型的属性可用:

  • 标量类型(例如 strings, dates, numbers, booleans 等)

属性的 type 参数应为以下值之一:

Type categories Available types
String types
  • string
  • text
  • richtext
  • enumeration
  • email
  • password
  • uid
Date types
  • date
  • time
  • datetime
  • timestamp
Number types
  • integer
  • biginteger
  • float
  • decimal
Other generic types
  • boolean
  • array
  • json
Special types unique to Strapi
Internationalization (i18n)-related types

Can only be used if the i18n plugin is installed
  • locale
  • localizations

# 验证

可以使用以下参数将基本验证应用于属性:

参数 类型 描述 默认
required Boolean 如果为 true,则为此属性添加所需的验证程序 false
max Integer 检查该值是否大于或等于给定的最大值 -
min Integer 检查值是否小于或等于给定的最小值 -
minLength Integer 字段输入值的最小字符数 -
maxLength Integer M字段输入值的最大字符数 -
private Boolean 如果为 true,则该属性将从服务器响应中删除。

💡 这对于隐藏敏感数据非常有用。
false
configurable Boolean 如果为 false,则无法从内容类型生成器插件中配置该属性。 true
// ./src/api/[api-name]/content-types/restaurant/schema.json

{
  // ...
  "attributes": {
    "title": {
      "type": "string",
      "minLength": 3,
      "maxLength": 99,
      "unique": true
    },
    "description": {
      "default": "My description",
      "type": "text",
      "required": true
    },
    "slug": {
      "type": "uid",
      "targetField": "title"
    }
    // ...
  }
}

# 数据库验证和设置

✋ 🚧 此 API 被视为实验性 API。

这些设置应保留给高级用法,因为它们可能会破坏某些功能。没有计划使这些设置稳定。

数据库验证和设置是在模式迁移期间直接传递到 tableBuilder Knex.js函数上的自定义选项。数据库验证允许对设置自定义列设置进行高级控制。以下选项在每个属性的 column: {} 对象中设置:

参数 类型 描述 默认
name string 更改数据库中列的名称 -
defaultTo string 将数据库设置为 defaultTo,通常与 notNullable 一起使用 -
notNullable boolean 设置数据库 notNullable,确保列不能为空 false
unsigned boolean 仅适用于数字列,删除了负数的能力,但最大长度加倍 false
unique boolean 强制数据库级别唯一,与草稿和发布功能一起使用时要小心 false
type string 更改数据库类型,如果 type 有参数,则应在 args 中传递它们 -
args array 传递到 Knex 的参数.js函数,用于更改 type 等内容 []
// ./src/api/[api-name]/content-types/restaurant/schema.json

{
  // ...
  "attributes": {
    "title": {
      "type": "string",
      "minLength": 3,
      "maxLength": 99,
      "unique": true,
      "column": {
        "unique": true // enforce database unique also
      }
    },
    "description": {
      "default": "My description",
      "type": "text",
      "required": true,
      "column": {
        "defaultTo": "My description", // set database level default
        "notNullable": true // enforce required at database level, even for drafts
      }
    },
    "rating": {
      "type": "decimal",
      "default": 0,
      "column": {
        "defaultTo": 0,
        "type": "decimal", // using the native decimal type but allowing for custom precision
        "args": [
          6,1 // using custom precision and scale
        ]
      }
    }
    // ...
  }
}

# uid 类型

uid 类型用于根据 2 个可选参数,使用唯一标识符 (UID)(例如,文章的 slug)自动预填充管理面板中的字段值:

  • targetField (string): 如果使用,定义为目标的字段的值将用于自动生成 UID。
  • options (string): 如果使用,UID 将基于传递给 底层 uid 生成器 (opens new window) 的一组选项生成。生成的 uid 必须与以下正则表达式模式匹配:/^[A-Za-z0-9-_.~]*$

# 关系

关系将内容类型链接在一起。关系在模型的 attributes 中显式定义,type: 'relation' 并接受以下附加参数:

参数 描述
relation 这些值之间的关系类型:
  • oneToOne
  • oneToMany
  • manyToOne
  • manyToMany
target 接受字符串值作为目标内容类型的名称
mappedBy and inversedBy

Optional
在双向关系中,所属方声明 inversedBy 键,而反置方声明 mappedBy

# 组件

组件字段创建内容类型和组件结构之间的关系。组件在模型的 attributes 中显式定义,type: 'component' 并接受以下附加参数:

参数 类型 描述
repeatable Boolean 可以是 truefalse,具体取决于组件是否可重复
component String 按照以下格式定义相应的组件:
<category>.<componentName>
// ./src/api/[apiName]/restaurant/content-types/schema.json

{
  "attributes": {
    "openinghours": {
      "type": "component",
      "repeatable": true,
      "component": "restaurant.openinghours"
    }
  }
}

# 动态区域

动态区域根据 组件 的混合列表创建一个灵活的空间来撰写内容。

动态区域在具有 type: 'dynamiczone' 的模型的 attributes 中显式定义。它们还接受一个 components 数组,其中每个组件应按照以下格式命名:<category>.<componentName>.

// ./src/api/[api-name]/content-types/article/schema.json

{
  "attributes": {
    "body": {
      "type": "dynamiczone",
      "components": ["article.slider", "article.content"]
    }
  }
}

# 模型选项

options 键用于定义特定行为,并接受以下参数:

参数 类型 描述
privateAttributes Array of strings 允许将一组属性视为私有属性,即使它们实际上并未在模型中定义为属性。它可用于从 API 响应时间戳中删除它们。

模型中定义的 privateAttributes 与全局 Strapi 配置中定义的 privateAttributes 合并。
draftAndPublish Boolean 启用草稿和发布功能。

默认值:true(如果内容类型是从交互式创建的,则为 false)。
// ./src/api/[api-name]/content-types/restaurant/schema.json

{
  "options": {
    "privateAttributes": ["id", "created_at"],
    "draftAndPublish": true
  }
}

# 生命周期 hooks

生命周期钩子是在调用 Strapi 查询时触发的函数。当通过管理面板管理内容或使用 query 开发自定义代码时,它们会自动触发。

生命周期 hooks 可以通过声明方式或编程方式进行自定义。

✋ CAUTION

当直接使用 knex (opens new window) 库而不是 Strapi 函数时,不会触发生命周期 hooks。

# 可用的生命周期事件

以下生命周期事件可用:

  • beforeCreate
  • beforeCreateMany
  • afterCreate
  • afterCreateMany
  • beforeUpdate
  • beforeUpdateMany
  • afterUpdate
  • afterUpdateMany
  • beforeDelete
  • beforeDeleteMany
  • afterDelete
  • afterDeleteMany
  • beforeCount
  • afterCount
  • beforeFindOne
  • afterFindOne
  • beforeFindMany
  • afterFindMany

# Hook event 对象

生命周期挂钩是采用 event 参数的函数,该参数是具有以下键的对象:

类型 描述
action String 已触发的生命周期事件 (参见 list)
model Object 模型对象
params Object 接受以下参数:
  • data
  • select
  • where
  • orderBy
  • limit
  • offset
  • populate
result Object 可选,仅适用于 afterXXX 事件

包含操作的结果。
state Object 查询状态,可用于在查询的 beforeXXXafterXXX 事件之间共享状态。query.

# 声明式和编程用法

若要配置内容类型生命周期挂钩,请在 ./api/[api-name]/content-types/[content-type-name]/ 文件夹中创建一个 lifecycles.js 文件。

每个事件侦听器都是按顺序调用的。它们可以是同步的,也可以是异步的。

使用数据库层 API,还可以注册订阅者并以编程方式侦听事件:

// ./src/api/[api-name]/content-types/[api-name]/lifecycles.js

// registering a subscriber
strapi.db.lifecycles.subscribe({
  models: [], // optional;

  beforeCreate(event) {
    const { data, where, select, populate } = event.params;

    event.state = 'doStuffAfterWards';
  },

  afterCreate(event) {
    if (event.state === 'doStuffAfterWards') {
    }

    const { result, params } = event;

    // do something to the result
  },
});

// generic subscribe for generic handling
strapi.db.lifecycles.subscribe((event) => {
  if (event.action === 'beforeCreate') {
    // do something
  }
});