# 账户账单详情
Source: https://docs.strapi.io/cloud/account/account-billing
# 账户账单与发票 {#account-billing--invoices}
🌐 Account billing & invoices
通过 *个人资料* 页面,可通过点击界面右上角的头像,然后点击 **个人资料** 访问,你可以进入 [ *账单*](#account-billing) 和 [ *发票*](#account-invoices) 标签页。
## 账户计费 {#account-billing}
🌐 Account billing
*账单*标签显示并允许你修改账户设置的账单详细信息和付款方式。
*账单*标签的*支付方式*部分允许你管理可用于 Strapi Cloud 项目的信用卡。*账单详情*部分需要填写,至少要填写必填字段,因为这些信息将作为与你的账户相关的所有 Strapi Cloud 项目的默认账单详情。
### 添加新的信用卡 {#adding-a-new-credit-card}
🌐 Adding a new credit card
1. 在 *账单*选项卡的*付款方式*部分,点击**添加银行卡**按钮。
2. 填写以下字段:
| 字段名称 | 描述 || --- | --- || 卡号 | 输入要添加为支付方式的信用卡号码。 || 到期日 | 输入信用卡的到期日期。 || CVC | 输入显示在信用卡背面的三位数代码。 |
3. 点击 **保存** 按钮。
:::tip
第一个被添加为账户付款方式的信用卡默认将是主要信用卡。然而,可以通过点击 图标,然后选择**设为主要**来将另一张信用卡设为主要信用卡。
:::
### 删除信用卡 {#deleting-a-credit-card}
🌐 Deleting a credit card
要从账户的支付方式列表中移除信用卡:
🌐 To remove a credit card from the list of payment methods for the account:
1. 点击你希望删除的信用卡的 图标。
2. 点击 **移除卡片**。卡片会立即被删除。
:::note
你无法删除主要信用卡,因为至少必须有一张信用卡可用作支付方式,而主要信用卡默认就是那一张。如果你希望删除的信用卡当前是主要信用卡,则必须先将另一张信用卡设为主要信用卡,然后再删除它。
🌐 You cannot delete the primary card as at least one credit card must be available as payment method, and the primary card is by default that one. If the credit card you wish to delete is currently the primary card, you must first define another credit card as primary, then delete it.
:::
## 账户发票 {#account-invoices}
🌐 Account invoices
*发票* 选项卡显示你所有 Strapi Cloud 项目的完整发票列表。
:::strapi Invoices are also available per project.
在任何项目的 *设置 > 发票* 选项卡中,你将只找到该项目的发票。请随时查看[专门文档](/cloud/projects/settings#invoices)。
🌐 In the *Settings > Invoices* tab of any project, you will find the invoices for that project only. Feel free to check the [dedicated documentation](/cloud/projects/settings#invoices).
:::
# 个人资料设置
Source: https://docs.strapi.io/cloud/account/account-settings
# 个人资料设置 {#profile-settings}
🌐 Profile settings
*个人资料* 页面使你能够管理你的账户详细信息和偏好设置。你可以通过点击界面右上角的个人头像,然后选择 **个人资料** 来访问该页面。
🌐 The *Profile* page enables you to manage your account details and preferences. It is accessible by clicking on your profile picture, on the top right hand corner of the interface, and **Profile**.
*个人资料*界面中有3个可用选项卡: [*常规*](#general)、 *账单* 和 发票(后两个在本指南的[账户账单详情](/cloud/account/account-billing)部分有说明)。
## 一般 {#general}
🌐 General
“ *常规*”选项卡允许你编辑账户资料的以下详细信息:
- 详情:查看与你的账户关联的名称。
- 已连接的账户:用于管理与你的 Strapi Cloud 账户关联的 Google、GitHub、GitLab 和电子邮件账户(请参阅 [管理已连接的账户](#managing-connected-accounts))。
- 删除账户:永久删除你的 Strapi Cloud 账户(参见 [删除 Strapi Cloud 账户](#deleting-strapi-cloud-account))。
### 管理已连接的账户 {#managing-connected-accounts}
🌐 Managing connected accounts
你可以将 Google、GitLab、GitHub 和电子邮件账户连接到你的 Strapi Cloud 账户。_已连接账户_ 部分列出了当前已连接到你的 Strapi Cloud 账户的账户。在此处,如果尚未连接,你也可以连接新的 Google、GitLab、GitHub 和电子邮件账户。
🌐 You can connect a Google, GitLab, GitHub and email account to your Strapi Cloud account. The _Connected accounts_ section lists accounts that are currently connected to your Strapi Cloud account. From there you can also connect a new Google, GitLab, GitHub and email account if one is not already connected.
要将新的 Google、GitLab、GitHub 或电子邮件账户连接到你的 Strapi Cloud 账户,请点击 **连接账户** 按钮,并按照相应网站上的下一步操作进行操作。
🌐 To connect a new Google, GitLab, GitHub or email account to your Strapi Cloud account, click on the **Connect account** button and follow the next steps on the corresponding website.
你还可以点击已连接账户的三点按钮,然后点击“在……上管理”按钮,直接在相应网站上管理你的 GitHub、GitLab 或 Google 账户。
🌐 You can also click on the three dots button of a connected account and click on the "Manage on" button to manage your GitHub, GitLab or Google account directly on the corresponding website.
### 删除 Strapi Cloud 账户 {#deleting-strapi-cloud-account}
🌐 Deleting Strapi Cloud account
你可以删除你的 Strapi Cloud 账户,但这是永久且不可逆的。所有相关的项目及其数据也将被删除,项目的订阅将自动取消。
🌐 You can delete your Strapi Cloud account, but it will be permanent and irreversible. All associated projects and their data will be deleted as well and the subscriptions for the projects will automatically be canceled.
1. 在 *常规*选项卡的*删除账户*部分,点击**删除账户**按钮。
2. 在对话框中,在文本框里输入 `DELETE`。
3. 通过点击 **删除** 按钮确认删除你的账户。
# 数据库
Source: https://docs.strapi.io/cloud/advanced/database
# 数据库 {#database}
🌐 Database
Strapi Cloud 默认提供预配置的 PostgreSQL 数据库。但是,如果需要,你也可以将其配置为使用外部 SQL 数据库。
🌐 Strapi Cloud provides a pre-configured PostgreSQL database by default. However, you can also configure it to utilize an external SQL database, if needed.
:::prerequisites
- 一个在 `v4.8.2+` 上运行的本地 Strapi 项目。
- 外部数据库的凭证。
- 如果使用现有数据库,模式必须与 Strapi 项目的模式匹配。
:::
:::caution
虽然可以在 Strapi Cloud 中使用外部数据库,但在使用时应考虑以下事项:
🌐 While it's possible to use an external database with Strapi Cloud, you should do it while keeping in mind the following considerations:
- Strapi Cloud 已经提供了一个为 Strapi 优化的托管数据库。
- 使用外部数据库可能导致意外行为和/或性能问题(例如,网络延迟可能影响性能)。出于性能原因,建议将外部数据库托管在与你的 Strapi Cloud 项目所在地区接近的位置。你可以在项目设置中找到你的 Strapi Cloud 项目托管位置(见 [项目设置 > 常规 > 选择的地区](/cloud/projects/settings#general))。
- Strapi 无法为与 Strapi Cloud 一起使用的外部数据库提供安全性或支持。
:::
:::warning
任何添加到你的项目中以 `DATABASE_` 开头的环境变量都将导致 Strapi Cloud 假定你将使用外部数据库,并且所有 Strapi Cloud 特定的数据库变量都不会被注入!
🌐 Any environment variable added to your project that starts with `DATABASE_` will cause Strapi Cloud to assume that you will be using an external database and all Strapi Cloud specific database variables will not be injected!
:::
## 配置 {#configuration}
🌐 Configuration
项目 `./config/database.js` 或 `./config/database.ts` 文件必须与 [数据库配置中的环境变量](https://strapi.nodejs.cn/cms/configurations/database#environment-variables-in-database-configurations) 部分中的配置匹配。
🌐 The project `./config/database.js` or `./config/database.ts` file must match the configuration found in the [environment variables in database configurations](https://strapi.nodejs.cn/cms/configurations/database#environment-variables-in-database-configurations) section.
在推送更改之前,将环境变量添加到 Strapi Cloud 项目中:
🌐 Before pushing changes, add environment variables to the Strapi Cloud project:
1. 登录 Strapi Cloud,然后在“项目”页面上点击相应的项目。
2. 点击 **设置** 标签,然后在左侧菜单中选择 **变量**。
3. 添加以下环境变量:
| 变量 | 值 | 详情 || -------------------------------- | ---------------- | ---------- || `DATABASE_CLIENT` | your_db | 应该是 `mysql`、`postgres` 或 `sqlite` 之一。 || `DATABASE_HOST` | your_db_host | 数据库主机的 URL 或 IP 地址 || `DATABASE_PORT` | your_db_port | 用于访问数据库的端口 || `DATABASE_NAME` | your_db_name | 数据库名称 || `DATABASE_USERNAME` | your_db_username | 用于访问数据库的用户名 || `DATABASE_PASSWORD` | your_db_password | 与该用户名关联的密码 || `DATABASE_SSL_REJECT_UNAUTHORIZED` | false | 是否应拒绝未经授权的连接 || `DATABASE_SCHEMA` | public | - |
4. 点击 **保存**。
:::caution
为了确保顺利部署,建议不要更改环境变量的名称。
🌐 To ensure a smooth deployment, it is recommended to not change the names of the environment variables.
:::
## 部署 {#deployment}
🌐 Deployment
要部署项目并使用外部数据库,请推送之前的更改。这将触发 Strapi Cloud 项目的重新构建和新的部署。
🌐 To deploy the project and utilize the external database, push the changes from earlier. This will trigger a rebuild and new deployment of the Strapi Cloud project.
一旦应用完成构建,项目将使用外部数据库。
🌐 Once the application finishes building, the project will use the external database.
## 恢复到默认数据库 {#reverting-to-the-default-database}
🌐 Reverting to the default database
要恢复到默认数据库,请从 Strapi Cloud 项目仪表板中删除之前添加的与外部数据库相关的环境变量,然后保存。要使更改生效,你必须重新部署 Strapi Cloud 项目。
🌐 To revert back to the default database, remove the previously added environment variables related to the external database from the Strapi Cloud project dashboard, and save. For the changes to take effect, you must redeploy the Strapi Cloud project.
# 电子邮件提供商
Source: https://docs.strapi.io/cloud/advanced/email
# Strapi Cloud 的电子邮件提供商配置 {#email-providers-configuration-for-strapi-cloud}
🌐 Email Providers configuration for Strapi Cloud
Strapi Cloud 开箱即用自带一个基础的电子邮件提供商。不过,如果需要,它也可以配置为使用其他电子邮件提供商。
🌐 Strapi Cloud comes with a basic email provider out of the box. However, it can also be configured to utilize another email provider, if needed.
:::caution
请注意,Strapi 无法为第三方电子邮件提供商提供支持。
🌐 Please be advised that Strapi is unable to provide support for third-party email providers.
:::
:::prerequisites
- 一个在 `v4.8.2+` 上运行的本地 Strapi 项目。
- 另一个电子邮件提供商的凭据(请参见
:::caution
文件结构必须与上述路径完全匹配,否则配置将不会应用到 Strapi 云。
🌐 The file structure must match the above path exactly, or the configuration will not be applied to Strapi Cloud.
:::
每个提供商将有不同的配置设置可用。请查看
:::tip
在将上述更改推送到 GitHub 之前,向 Strapi Cloud 项目添加环境变量,以防在更改完成之前触发项目的重建和新部署。
🌐 Before pushing the above changes to GitHub, add environment variables to the Strapi Cloud project to prevent triggering a rebuild and new deployment of the project before the changes are complete.
:::
### Strapi 云配置 {#strapi-cloud-configuration}
🌐 Strapi Cloud Configuration
1. 登录 Strapi Cloud,然后在“项目”页面上点击相应的项目。
2. 点击 **设置** 标签,然后在左侧菜单中选择 **变量**。
3. 添加电子邮件提供商特定的所需环境变量。
4. 点击 **保存**。
**示例:**
## 部署 {#deployment}
🌐 Deployment
要部署项目并使用其他方的电子邮件提供商,请推送之前的更改。这将触发 Strapi Cloud 项目的重建和新部署。
🌐 To deploy the project and utilize another party email provider, push the changes from earlier. This will trigger a rebuild and new deployment of the Strapi Cloud project.
一旦应用构建完成,项目将使用新的电子邮件提供商。
🌐 Once the application finishes building, the project will use the new email provider.
:::strapi Custom Provider
如果你想创建自定义电子邮件提供商,请参阅 CMS 文档中的 [电子邮件提供商](/cms/features/email#providers) 文档。
🌐 If you want to create a custom email provider, please refer to the [Email providers](/cms/features/email#providers) documentation in the CMS Documentation.
:::
# 为 Strapi Cloud 上传提供商配置
Source: https://docs.strapi.io/cloud/advanced/upload
# 为 Strapi Cloud 上传提供商配置 {#upload-provider-configuration-for-strapi-cloud}
🌐 Upload Provider Configuration for Strapi Cloud
Strapi Cloud 开箱即用带有本地上传提供者。不过,如果需要,它也可以配置为使用第三方上传提供者。
🌐 Strapi Cloud comes with a local upload provider out of the box. However, it can also be configured to utilize a third-party upload provider, if needed.
:::caution
请注意,Strapi 无法为第三方上传提供商提供支持。
🌐 Please be advised that Strapi is unable to provide support for third-party upload providers.
:::
:::prerequisites
- 一个在 `v4.8.2+` 上运行的本地 Strapi 项目。
- 第三方上传提供者的凭证(参见
:::caution
文件结构必须与上述路径完全匹配,否则配置将不会应用到 Strapi 云。
🌐 The file structure must match the above path exactly, or the configuration will not be applied to Strapi Cloud.
:::
每个提供商将有不同的配置设置可用。请查看
### 配置安全中间件 {#configure-the-security-middleware}
🌐 Configure the Security Middleware
由于 Strapi 安全中间件的默认设置,你需要修改 `contentSecurityPolicy` 设置才能在媒体库中正确查看缩略图预览。
🌐 Due to the default settings in the Strapi Security Middleware you will need to modify the `contentSecurityPolicy` settings to properly see thumbnail previews in the Media Library.
在你的 Strapi 项目中执行此操作:
🌐 To do this in your Strapi project:
1. 在你的 Strapi 项目中,导航到 `./config/middlewares.js` 或 `./config/middlewares.ts`。
2. 用上传提供者提供的对象替换默认的 `strapi::security` 字符串。
**示例:**
:::tip
在将上述更改推送到 GitHub 之前,向 Strapi Cloud 项目添加环境变量,以防在更改完成之前触发项目的重建和新部署。
🌐 Before pushing the above changes to GitHub, add environment variables to the Strapi Cloud project to prevent triggering a rebuild and new deployment of the project before the changes are complete.
:::
### Strapi 云配置 {#strapi-cloud-configuration}
🌐 Strapi Cloud Configuration
1. 登录 Strapi Cloud,然后在“项目”页面上点击相应的项目。
2. 点击 **设置** 标签,然后在左侧菜单中选择 **变量**。
3. 添加特定于上传提供者的所需环境变量。
4. 点击 **保存**。
**示例:**
## 部署 {#deployment}
🌐 Deployment
要部署项目并使用第三方上传提供商,请推送之前的更改。这将触发 Strapi Cloud 项目的重新构建和新部署。
🌐 To deploy the project and utilize the third-party upload provider, push the changes from earlier. This will trigger a rebuild and new deployment of the Strapi Cloud project.
一旦应用构建完成,项目将使用新的上传提供者。
🌐 Once the application finishes building, the project will use the new upload provider.
:::strapi Custom Provider
如果你想创建自定义上传提供程序,请参阅 CMS 文档中的 [Providers](/cms/features/media-library#providers) 文档。
🌐 If you want to create a custom upload provider, please refer to the [Providers](/cms/features/media-library#providers) documentation in the CMS Documentation.
:::
# 命令行接口 (CLI) {#command-line-interface-cli}
Source: https://docs.strapi.io/cloud/cli/cloud-cli
# 命令行接口 (CLI) {#command-line-interface-cli}
🌐 Command Line Interface (CLI)
Strapi Cloud 配备了一个命令行接口(CLI),允许你登录和登出,并在不需要将本地项目托管在远程 git 仓库的情况下进行部署。CLI 支持 `yarn` 和 `npm` 两种包管理器。
🌐 Strapi Cloud comes with a Command Line Interface (CLI) which allows you to log in and out, and to deploy a local project without it having to be hosted on a remote git repository. The CLI works with both the `yarn` and `npm` package managers.
:::note
建议仅在本地安装 Strapi,这需要在所有以下 `strapi` 命令前加上用于项目设置的包管理器(例如 `npm run strapi help` 或 `yarn strapi help`)或专用的 node 包执行器(例如 `npx strapi help`)。
🌐 It is recommended to install Strapi locally only, which requires prefixing all of the following `strapi` commands with the package manager used for the project setup (e.g `npm run strapi help` or `yarn strapi help`) or a dedicated node package executor (e.g. `npx strapi help`).
:::
## Strapi 登录 {#strapi-login}
🌐 strapi login
**别名:** `strapi cloud:login`
登录 Strapi 云。
🌐 Log in Strapi Cloud.
```bash
strapi login
```
此命令会自动打开一个浏览器窗口,首先要求你确认浏览器窗口和终端中显示的代码是否相同。然后,你将能够通过 Google、GitHub 或 GitLab 登录 Strapi Cloud。一旦浏览器窗口确认登录成功,就可以安全关闭。
🌐 This command automatically opens a browser window to first ask you to confirm that the codes displayed in both the browser window and the terminal are the same. Then you will be able to log into Strapi Cloud via Google, GitHub or GitLab. Once the browser window confirms successful login, it can be safely closed.
如果浏览器窗口没有自动打开,终端将显示一个可点击的链接以及可手动输入的代码。
🌐 If the browser window doesn't automatically open, the terminal will display a clickable link as well as the code to enter manually.
## strapi 部署 {#strapi-deploy}
🌐 strapi deploy
**别名:** `strapi cloud:deploy`
在 Strapi Cloud 中部署一个新的本地项目(< 100MB)。
🌐 Deploy a new local project (< 100MB) in Strapi Cloud.
```bash
strapi deploy
```
此命令必须在 `login` 命令之后使用。它可以将本地 Strapi 项目部署到 Strapi Cloud,而无需事先将其托管在远程 git 仓库中。终端将在项目成功部署到 Strapi Cloud 时通知你。
🌐 This command must be used after the `login` one. It deploys a local Strapi project on Strapi Cloud, without having to host it on a remote git repository beforehand. The terminal will inform you when the project is successfully deployed on Strapi Cloud.
通过 CLI 部署 Strapi 项目会在免费计划上创建一个项目。
🌐 Deploying a Strapi project through the CLI creates a project on the Free plan.
一旦项目首次通过 CLI 部署到 Strapi Cloud,`deploy` 命令可以被重复使用以触发同一项目的新部署。
🌐 Once the project is first deployed on Strapi Cloud with the CLI, the `deploy` command can be reused to trigger a new deployment of the same project.
:::note
一旦你部署了你的项目,如果你访问 Strapi Cloud 仪表板,你可能会看到一些限制,以及由于创建了一个不在远程仓库中的 Strapi Cloud 项目并通过 CLI 部署而产生的影响。
🌐 Once you deployed your project, if you visit the Strapi Cloud dashboard, you may see some limitations as well as impacts due to creating a Strapi Cloud project that is not in a remote repository and which was deployed with the CLI.
- 仪表板中通常用于显示关于 Git 提供者信息的某些区域将会是空白的。
- 某些按钮,例如 **触发部署** 按钮,将会是灰色且无法点击,因为除非你已经[将 Git 仓库连接到你的 Strapi 云项目](/cloud/getting-started/deployment-cli#automatically-deploying-subsequent-changes)。
:::
## strapi 链接 {#strapi-link-newbadge-}
🌐 strapi link
**别名:** `strapi cloud:link`
将当前文件夹中的项目链接到 Strapi Cloud 中的现有项目。
🌐 Links project in the current folder to an existing project in Strapi Cloud.
```bash
strapi link
```
此命令将你当前目录中的本地项目与你 Strapi Cloud 账户上的现有项目连接。系统将提示你从 Strapi Cloud 上托管的可用项目列表中选择你希望链接的项目。
🌐 This command connects your local project in the current directory with an existing project on your Strapi Cloud account. You will be prompted to select the project you wish to link from a list of available projects hosted on Strapi Cloud.
## strapi 项目 {#strapi-projects-newbadge-}
🌐 strapi projects
**别名:** `strapi cloud:projects`
列出与你的账户关联的所有 Strapi Cloud 项目。
🌐 Lists all Strapi Cloud projects associated with your account.
```bash
strapi projects
```
此命令检索并显示托管在你的 Strapi Cloud 账户上的所有项目的列表。
🌐 This command retrieves and displays a list of all projects hosted on your Strapi Cloud account.
## strapi 登出 {#strapi-logout}
🌐 strapi logout
**别名:** `strapi cloud:logout`
退出 Strapi Cloud。
🌐 Log out of Strapi Cloud.
```bash
strapi logout
```
此命令会将你从 Strapi Cloud 登出。一旦运行 `logout` 命令,浏览器页面将会打开,终端将显示你已成功登出的确认信息。你将无法再使用 `deploy` 命令。
🌐 This command logs you out of Strapi Cloud. Once the `logout` command is run, a browser page will open and the terminal will display a confirmation message that you were successfully logged out. You will not be able to use the `deploy` command anymore.
# 缓存与性能 {#caching--performance}
Source: https://docs.strapi.io/cloud/getting-started/caching
# 缓存与性能 {#caching--performance}
🌐 Caching & Performance
对于具有大量可缓存内容(如图片、视频和其他静态资源)的 Strapi Cloud 应用,通过
# Strapi 云基础 {#strapi-cloud-fundamentals}
Source: https://docs.strapi.io/cloud/getting-started/cloud-fundamentals
# Strapi 云基础 {#strapi-cloud-fundamentals}
🌐 Strapi Cloud fundamentals
在进一步阅读此 Strapi Cloud 文档之前,我们建议你先了解以下主要概念。它们将帮助你理解 Strapi Cloud 的工作原理,并确保顺利使用 Strapi Cloud。
🌐 Before going any further into this Strapi Cloud documentation, we recommend you to acknowledge the main concepts below. They will help you to understand how Strapi Cloud works, and ensure a smooth Strapi Cloud experience.
- **托管平台** Strapi Cloud 是一个托管平台,可用于部署已经使用 Strapi CMS(内容管理系统)创建的现有 Strapi 项目。Strapi Cloud *不是* Strapi CMS 的 SaaS()版本,而应被视为 PaaS()。如需了解有关 Strapi CMS 的更多信息,请随时参考 [CMS 文档](https://strapi.nodejs.cn/cms/intro)。
- **Strapi Cloud 定价方案** 作为 Strapi Cloud 用户,你可以在 4 种方案中进行选择:免费版、基础版、专业版和企业版。根据不同的方案,你可以访问不同的功能、支持和自定义选项(更多详细信息请参见 [定价页面](https://strapi.io/pricing-cloud))。在本 Strapi Cloud 文档中, 、 和 标签可以显示在章节标题下方,以表示该功能仅从对应的付费方案开始可用。如果未显示任何标签,则该功能在免费版中也可用。
- **Strapi Cloud 用户类型** 在 Strapi Cloud 项目中可以有两种类型的用户:所有者和维护者。所有者是创建项目的人,因此可以访问该项目的所有功能和选项。维护者是被项目所有者邀请来为已创建的项目做出贡献的用户。正如[协作](/cloud/projects/collaboration)页面所述,维护者无法查看和访问 Strapi Cloud 仪表板中的所有功能和选项。
- **支持** Strapi 支持团队提供的支持级别取决于你订阅的 Strapi Cloud 计划。免费计划不包括访问支持。Essential 和 Pro 计划包含基础支持,而 Scale 计划包含标准支持。有关支持级别的所有详细信息,请参阅[专门的支持文章](https://support.strapi.io/support/solutions/articles/67000680833-what-is-supported-by-the-strapi-team#Not-Supported)。
- **Strapi Cloud 与自托管环境中的 API 访问** REST 和 GraphQL API 在 Strapi Cloud 和自托管服务器上的表现是相同的。唯一的区别是 URL:
- 基础 API 域:在 Strapi Cloud 上,你的 API 使用环境的域(例如 `https://.strapiapp.com/api/...`),或者如果你设置了自定义域,则使用你的自定义域(参见 [域文档](/cloud/projects/settings#domains))。自托管项目将使用你所暴露的任何域。
- 媒体库网址:来自 Strapi Cloud 的 REST 和 GraphQL 响应中的媒体字段始终使用项目媒体域(例如 `.media.strapiapp.com`),即使你通过自定义域访问 API。自托管项目会返回配置的上传提供商的 URL,因此域名可以与你自己的网站或 CDN 匹配。当你将项目从自托管迁移到 Strapi Cloud 时,请确保你的前端读取 API 返回的绝对 URL 或接受 Strapi Cloud 的媒体域。
# Strapi 云端 - 仪表板部署
Source: https://docs.strapi.io/cloud/getting-started/deployment
# 使用云仪表板进行项目部署 {#project-deployment-with-the-cloud-dashboard}
🌐 Project deployment with the Cloud dashboard
这是一个使用云仪表板首次在 Strapi Cloud 部署你的项目的逐步指南。
🌐 This is a step-by-step guide for deploying your project on Strapi Cloud for the first time, using the Cloud dashboard.
:::prerequisites
在你可以使用 Cloud 仪表板将 Strapi 应用部署到 Strapi Cloud 之前,你需要具备以下先决条件:
🌐 Before you can deploy your Strapi application on Strapi Cloud using the Cloud dashboard, you need to have the following prerequisites:
* Strapi 版本 `4.8.2` 或更高
* 项目数据库必须与 PostgreSQL 兼容。Strapi 不支持也不推荐使用任何外部数据库,尽管可以配置一个(参见 [高级数据库配置](/cloud/advanced/database))。
* 项目源代码托管在
5. 设置你的 Strapi Cloud 项目。
5.a. 填写以下信息:
| 设置名称 | 说明 ||--------------|--------------------------------------------------------------------------------------------------|| 显示名称 | 名称会根据你选择的仓库自动填充,但你可以根据需要编辑它。 || Git 分支 | 从下拉菜单中选择你想要部署的分支。 || 推送时部署 | 勾选此框将在向所选分支推送更改时自动触发部署。禁用时,你需要手动部署最新的更改。 || 地区 | 选择托管你的 Strapi 应用的服务器地理位置。可选地区包括美国(东部)、欧洲(西部)或亚洲(东南部)。 |
:::note
Git 分支和“在推送时部署”设置可以随后通过项目设置进行修改。然而,托管区域只能在创建项目时选择(参见 [项目设置](/cloud/projects/settings))。
:::
5.b.(可选)点击 **显示高级设置** 来填写以下选项:
| Setting name | Instructions |
|--------------|---------------------------------------------------------------------------------------------------------|
| Base directory | Write the name of the directory where your Strapi app is located in the repository. This is useful if you have multiple Strapi apps in the same repository or if you have a monorepo. |
| Environment variables | Click on **Add variable** to add environment variables used to configure your Strapi app (see [Environment variables](/cms/configurations/environment/) for more information). You can also add environment variables to your Strapi application by adding a `.env` file to the root of your Strapi app directory. The environment variables defined in the `.env` file will be used by Strapi Cloud. |
| Node version | Choose a Node version from the drop-down. The default Node version will automatically be chosen to best match the version of your Strapi project. If you manually choose a version that doesn't match with your Strapi project, the build will fail but the explanation will be displayed in the build logs. |
:::strapi Using Environment Variables
你可以使用环境变量将你的项目连接到外部数据库,而不是 Strapi Cloud 使用的默认数据库(更多详情请参见 [数据库配置](/cms/configurations/database#environment-variables-in-database-configurations))。如果你想回退并再次使用 Strapi 的默认数据库,请删除你的 `DATABASE_` 环境变量(不涉及自动迁移)。
你也可以在这里设置自定义电子邮件提供商。Sendgrid 被设置为在 Strapi Cloud 上托管的 Strapi 应用的默认提供商(更多详情请参见 [providers configuration](/cms/features/email#providers))。
:::
## 设置账单详情 {#setting-up-billing-details}
🌐 Setting up billing details
:::strapi No billing step for the Free plan
如果你选择免费计划,此结算步骤将被跳过,因为在创建项目时你不会被要求提供信用卡信息。
🌐 If you chose the free plan, this billing step will be skipped as you will not be asked to share your credit card details at the creation of the project.
跳到下面部分的第5步以完成项目创建。
:::
1. 点击 **继续到付款** 按钮。你将被重定向到付款页面,在那里你可以输入你的付款信息并查看你的发票。
2. 在*付款方式*部分,添加一张信用卡。此卡将用于所有与项目相关的事务,包括附加项目和超额费用。
3. 在*账单信息*部分,填写你的付款信息和账单地址。
4. 查看*发票*部分。购买月度订阅时,订阅价格将按当前计费周期剩余天数按比例计算。也可以展开*折扣码*部分以输入代码。
:::note
根据你的账单地址,可能会在你的发票上加收税费:
- 在欧盟和英国,提供有效的增值税编号可免除增值税。如果未提供有效的增值税编号,增值税将被添加到你的发票中。
- 在美国,适用的销售税是根据你的州和地址计算的。
:::
5. 点击 **订阅** 按钮以完成新 Strapi Cloud 项目的创建。
## 部署你的项目 {#deploying-your-project}
🌐 Deploying your project
确认项目创建后,你将被重定向到你的*项目仪表板*,在这里你将能够跟踪其创建和首次部署。
🌐 After confirming the project creation, you will be redirected to your *Project dashboard* where you will be able to follow its creation and first deployment.
在你的项目部署时,你 already 可以开始配置一些 [项目设置](/cloud/projects/settings)。
🌐 While your project is deploying, you can already start configuring some of your [project settings](/cloud/projects/settings).
:::note
如果在项目创建过程中发生错误,进度指示器将停止并显示错误消息。你将在失败步骤旁看到一个**重试**按钮,允许你重新启动创建过程。
🌐 If an error occurs during the project creation, the progress indicator will stop and display an error message. You will see a **Retry** button next to the failed step, allowing you to restart the creation process.
:::
一旦你的项目成功部署,创建跟踪器将被你的部署列表取代,你将能够访问你的云托管项目。不要忘记在分享你的 Strapi 项目之前创建第一个管理员用户。
🌐 Once your project is successfully deployed, the creation tracker will be replaced by your deployments list and you will be able to visit your Cloud hosted project. Don't forget to create the first Admin user before sharing your Strapi project.
## 接下来做什么? {#icon-namefast-forward--what-to-do-next}
现在你已经通过云控制面板部署了项目,我们鼓励你探索以下想法,以获得更完整的 Strapi 云体验:
🌐 Now that you have deployed your project via the Cloud dashboard, we encourage you to explore the following ideas to have an even more complete Strapi Cloud experience:
- 邀请其他用户[协作你的项目](/cloud/projects/collaboration)。
- 查看 [部署管理文档](/cloud/projects/deploys) 以了解如何为你的项目触发新的部署。
# Strapi 云端 - CLI 部署
Source: https://docs.strapi.io/cloud/getting-started/deployment-cli
# 使用命令行接口 (CLI) 进行项目部署 {#project-deployment-with-the-command-line-interface-cli}
🌐 Project deployment with the Command Line Interface (CLI)
这是一个逐步指南,教你如何首次使用命令行接口在 Strapi Cloud 上部署你的项目。
🌐 This is a step-by-step guide for deploying your project on Strapi Cloud for the first time, using the Command Line Interface.
:::prerequisites
在使用命令行接口将你的 Strapi 应用部署到 Strapi Cloud 之前,你需要具备以下先决条件:
🌐 Before you can deploy your Strapi application on Strapi Cloud using the Command Line Interface, you need to have the following prerequisites:
- 拥有一个 Google、GitHub 或 GitLab 账号。
- 拥有一个已创建的 Strapi 项目(参见 CMS 文档中的 [从 CLI 安装](/cms/installation/cli)),存储在本地。项目必须小于 100MB。
- 确保你的硬盘中有可用存储空间,用于存放操作系统的临时文件夹。
:::
## 登录 Strapi 云 {#logging-in-to-strapi-cloud}
🌐 Logging in to Strapi Cloud
1. 打开你的终端。
2. 导航到存储在本地电脑上的 Strapi 项目的文件夹。
3. 输入以下命令以登录 Strapi Cloud:
4. 在自动打开的浏览器窗口中,确认显示的代码与终端消息中写的代码相同。
5. 仍然在浏览器窗口中,选择通过 Google、GitHub 或 GitLab 登录。窗口应在不久后确认登录成功。
## 部署你的项目 {#deploying-your-project}
🌐 Deploying your project
1. 在你的终端中,仍然在你的 Strapi 项目文件夹中,输入以下命令来部署项目:
2. 在终端中关注进度条,直到确认项目已成功使用 Strapi Cloud 部署。部署项目将会在免费计划下创建一个新的 Strapi Cloud 项目。
### 自动部署后续更改 {#automatically-deploying-subsequent-changes}
🌐 Automatically deploying subsequent changes
默认情况下,当使用 Cloud CLI 创建和部署项目时,每次进行更改后,都需要通过运行相应的 `deploy` 命令手动再次部署所有后续更改。
🌐 By default, when creating and deploying a project with the Cloud CLI, you need to manually deploy again all subsequent changes by running the corresponding `deploy` command everytime you make a change.
另一种选择是通过 git 仓库启用自动部署。操作步骤如下:
🌐 Another option is to enable automatic deployment through a git repository. To do so:
1. 将你的代码托管在 git 仓库上,例如 或 。
2. 将你的 Strapi Cloud 项目连接到仓库(请参阅 [项目设置 > 常规](/cloud/projects/settings#general) 中的 _已连接仓库_ 设置)。
3. 仍然在 _项目设置 > 常规_ 选项卡中,勾选“在每次推送到此分支的提交时部署项目”设置框。从现在起,每当提交推送到已连接的 Git 仓库时,都会触发一次新的 Strapi Cloud 部署。
:::note
自动部署与所有其他部署方法兼容,因此一旦连接了 git 仓库,你可以从 [Cloud 仪表板](/cloud/projects/deploys)、[CLI](/cloud/cli/cloud-cli#strapi-deploy) 或通过向已连接的仓库推送新提交来触发对 Strapi Cloud 的新部署。
🌐 Automatic deployment is compatible with all other deployment methods, so once a git repository is connected, you can trigger a new deployment to Strapi Cloud [from the Cloud dashboard](/cloud/projects/deploys), [from the CLI](/cloud/cli/cloud-cli#strapi-deploy), or by pushing new commits to your connected repository.
:::
## ⏩ 接下来做什么? {#-what-to-do-next}
🌐 ⏩ What to do next?
既然你已经通过命令行接口部署了项目,我们鼓励你探索以下想法,以获得更完整的 Strapi Cloud 体验:
🌐 Now that you have deployed your project via the Command Line Interface, we encourage you to explore the following ideas to have an even more complete Strapi Cloud experience:
- 访问 Cloud 仪表板以查看你 Strapi 项目的[有用指标和信息](/cloud/projects/overview)。
- 请查看完整的 [命令行接口文档](/cloud/cli/cloud-cli) 以了解其他可用命令。
# 项目部署
Source: https://docs.strapi.io/cloud/getting-started/deployment-options
# 使用 Strapi Cloud 部署项目 {#project-deployment-with-strapi-cloud}
🌐 Project deployment with Strapi Cloud
你有两种选择可以使用 Strapi Cloud 部署你的项目:
🌐 You have 2 options to deploy your project with Strapi Cloud:
- 要么通过用户界面(UI),这意味着你将直接在 Strapi Cloud 仪表板上执行所有操作,
- 或者使用云评论命令行接口(CLI),这意味着你将只与终端进行交互。
下面的指南将引导你完成每种部署选项的所有步骤。
🌐 The guides below will guide you through all the steps for each of the deployment options.
# 欢迎使用 Strapi Cloud 文档! {#welcome-to-the-strapi-cloud-documentation}
Source: https://docs.strapi.io/cloud/getting-started/intro
# 欢迎使用 Strapi Cloud 文档! {#welcome-to-the-strapi-cloud-documentation}
🌐 Welcome to the Strapi Cloud Documentation!
Strapi Cloud 文档包含与你的 Strapi Cloud 账户和应用的设置、部署、更新和自定义相关的所有信息。
🌐 The Strapi Cloud documentation contains all information related to the setup, deployment, update and customization of your Strapi Cloud account and applications.
:::strapi What is Strapi Cloud?
构建在开源无头 CMS Strapi 之上。
:::
:::prerequisites
Strapi 团队推荐的典型工作流程是:
🌐 The typical workflow, which is recommended by the Strapi team, is:
1. 在本地创建你的 Strapi 应用(版本 4.8.2 或更高)。
2. 可以选择通过插件或自定义代码扩展应用。
3. 通过你的 git 提供商(GitHub 或 GitLab)对应用的代码库进行版本控制。
4. 使用 Strapi Cloud 部署应用。
:::
Strapi Cloud 文档按主题组织,顺序应与你使用产品的流程相对应。以下卡片,你可以点击,将重定向到主要主题和步骤。
🌐 The Strapi Cloud documentation is organised in topics in a order that should correspond to your journey with the product. The following cards, on which you can click, will redirect you to the main topics and steps.
:::strapi Welcome to the Strapi community!
Strapi Cloud 构建在 Strapi 之上,Strapi 是一个开源的、以社区为导向的项目。Strapi 团队秉持着分享他们的愿景,并与 Strapi 社区共同打造 Strapi 的未来。这就是为什么 是开放的:因为所有的见解都非常重要,并将帮助引导项目朝着正确的方向发展。任何社区成员都非常欢迎在这里分享想法和意见。
你也可以加入 、 和 ,并从Strapi社区整体多年来的经验、知识和贡献中受益。
:::
# 账单和使用信息 {#information-on-billing--usage}
Source: https://docs.strapi.io/cloud/getting-started/usage-billing
# 账单和使用信息 {#information-on-billing--usage}
🌐 Information on billing & usage
此页面包含与你的 Strapi Cloud 账户和项目的使用及计费相关的一般信息。
🌐 This page contains general information related to the usage and billing of your Strapi Cloud account and projects.
Strapi Cloud 提供 1 个免费计划和 3 个付费计划:Essential、Pro 和 Scale(见 [定价页面](https://strapi.io/pricing-cloud))。下表总结了 Strapi Cloud 基于使用量的定价计划,涵盖一般功能和使用情况:
🌐 Strapi Cloud offers 1 Free plan and 3 paid plans: Essential, Pro and Scale (see [Pricing page](https://strapi.io/pricing-cloud)). The table below summarizes Strapi Cloud usage-based pricing plans, for general features and usage:
| 功能 | 免费 | 基础版 | 专业版 | 企业版 || --- | --- | --- | --- | --- || **数据库条目** | 500 | 无限* | 无限* | 无限* || **资源存储** | 10GB | 50GB | 250GB | 1,000GB || **资源带宽(每月)** | 10GB | 50GB | 500GB | 1,000GB || **API 请求(每月)** | 2,500 | 50,000 | 1,000,000 | 10,000,000 || | | | | || **备份** | 不适用 | 不适用 | 每周 | 每日 || **自定义域名** | 不适用 | 包含 | 包含 | 包含 || **环境** | 不适用 | 不适用 | 包含 0 个(最多可增加 99 个) | 包含 1 个(最多可增加 99 个) || **电子邮件(每月)** | 100 | 无限* | 无限* | 无限* |
:::strapi Additional information on usage and features
- 一般特性与使用方式:
- 数据库条目是你的数据库中的条目数量。
- 资源存储是你的资源所使用的存储量。
- 资源带宽是你的资源所使用的带宽量。
- API 请求是对你的 API 发出的请求数量。这包括对 GraphQL 和 REST API 的请求,但不包括计入 CDN 带宽和存储的文件和媒体资源请求。所有 API 请求都计入你的每月使用量,无论响应类型如何。
- 云特定功能:
- 备份指的是 Strapi Cloud 项目的自动备份(有关此功能的更多信息,请参见 [备份文档](/cloud/projects/settings#backups))。
- 自定义域名是指为你的 Strapi 云定义自定义域名的能力(参见 [自定义域名](/cloud/projects/settings#connecting-a-custom-domain))。
- 环境是指计划中包含的环境数量,除默认的生产环境之外(有关该功能的更多信息,请参见[环境](/cloud/projects/settings#environments)文档)。
:::
:::caution The Free Plan is for personal, non-commercial use only
商业用途是指任何为了经济利益而进行的项目,包括:
🌐 Commercial use means any project made for financial gain, including:
- 在你的网站上接受或处理付款
- 接受或收取创建、更新或托管网站的付款
- 广告、推广或销售产品或服务
- 为任何第三方托管或投放广告
欲了解更多信息,请访问 [Strapi Cloud-法律](https://strapi.io/cloud-legal)
:::
:::info Scale-to-zero and cold start on the Free plan
在免费计划中,项目在短时间不活跃后会自动缩减到零。当应用再次被访问时——无论是通过前端还是通过 API 请求——返回响应可能需要几秒钟(最长可达一分钟)。
升级到付费计划将禁用缩减到零和冷启动,从而始终实现即时响应时间。
🌐 On the Free plan, projects automatically scale down to zero after a short period of inactivity. When the application is accessed again—either through the frontend or via an API request—it may take a few seconds (up to a minute) before a response is returned.
Upgrading to a paid plan disables scaling to zero and cold starts, resulting in instant response times at all times.
:::
## 环境管理 {#environments-management}
🌐 Environments management
环境是你的 Strapi Cloud 项目的隔离实例。所有项目都有一个默认的生产环境,但对于 Pro 或 Scale 计划的项目,可以从项目设置的 *环境* 标签中配置其他额外环境(请参见 [Environments](/cloud/projects/settings#environments))。Strapi Cloud 项目可以配置的额外环境数量没有限制。
🌐 Environments are isolated instances of your Strapi Cloud project. All projects have a default production environment, but other additional environments can be configured for projects on a Pro or Scale plan, from the *Environments* tab of the project settings (see [Environments](/cloud/projects/settings#environments)). There is no limit to the number of additional environments that can be configured for a Strapi Cloud project.
额外环境的使用限制与项目的生产环境相同(例如,Pro 计划中的额外环境在资源存储上将限制为 250GB,超出部分将按照与生产环境相同的方式收费)。但请注意,资源带宽和 API 调用是基于项目的,而不是基于环境的,因此即使有额外环境,这些使用限制也不会改变。
🌐 The usage limits of additional environments are the same as for the project's production environment (e.g. an additional environment on the Pro plan will be limited at 250GB for asset storage, and overages will be charged the same way as for the production environment). Note however that the asset bandwidth and API calls are project-based, not environment-based, so these usage limits do not change even with additional environments.
## 账单 {#billing}
🌐 Billing
计费基于你 Strapi Cloud 项目的使用情况。项目计划和附加组件会根据你的计费周期按月或按年计费,而超额部分按月计费。你可以在项目设置的*计费与使用情况*部分查看你的使用和计费信息。
🌐 Billing is based on the usage of your Strapi Cloud projects. Project plans and addons are either billed monthly or yearly, depending on your billing cycle, while overages are billed monthly. You can view your usage and billing information in the *Billing & Usage* section of your project settings.
### 税收 {#taxes}
🌐 Taxes
对于美国、英国和欧盟的账单地址,本地税费可能会被加到你的发票上。税额根据你的账单地址和增值税/税务识别号状态计算,并在结账时和发票上显示。
🌐 For billing addresses in the US, UK and EU, local taxes may be added to your invoices. Tax amounts are calculated based on your billing address and VAT/Tax ID status, and are displayed during checkout and on invoices.
你可以在你的 [账户账单](/cloud/account/account-billing) 设置中添加或更新你的增值税/税号。
🌐 You can add or update your VAT/Tax ID from your [Account Billing](/cloud/account/account-billing) settings.
### 超额 {#overages}
🌐 Overages
:::caution
免费计划不允许超额使用。
🌐 Overages are not allowed on the Free plan.
:::
如果你超出了 API 请求、资源带宽或资源存储的计划限制,你将被收取相应的超额费用。
🌐 If you exceed the limits of your plan for API Requests, Asset Bandwidth, or Asset Storage, you will be charged for the corresponding overages.
例如,如果你在专业版计划的资源带宽中超过 500GB 的限制,超出部分将在当前计费周期结束时或项目删除时收费。超额部分不按比例计算,将全额收费。
🌐 For example, if you exceed the 500GB limit in asset bandwidth of the Pro plan, you will be charged for the excess bandwidth at the end of the current billing period or on project deletion. Overages are not prorated and are charged in full.
超出部分按月收费,费率如下:
🌐 Overages are charged monthly, according to the following rates:
| 功能 | 价格 || --- | --- || **API 请求** | $1.50 / 25,000 次请求 || **资源带宽** | $30.00 / 100GB || **资源存储** | $0.60 / GB 每月 |
### 项目暂停 {#project-suspension}
🌐 Project suspension
项目可能会因各种原因进入**暂停**状态,包括:未付款的发票、超出免费计划的限制,或违反 Strapi Cloud 的 。
如果你的项目被暂停,你将无法再访问 Strapi 管理面板,也无法触发新的部署。你的项目仪表板上将会显示一个横幅,说明暂停的原因。你也会收到电子邮件通知。
🌐 If your project is suspended, you will no longer be able to access the Strapi admin panel, nor trigger new deployments. A banner will appear in your project's dashboard, indicating the cause of the suspension. You will also be notified by email.
#### 由于超出免费计划限制而暂停项目 {#project-suspension-for-exceeding-the-free-plan-limits}
🌐 Project suspension for exceeding the Free plan limits
当使用免费计划托管的项目超过 API 请求或资源带宽限制时,该项目将被暂停,直到下个月初每月配额重置。
🌐 When a project hosted with the Free plan exceeds either the API requests or the Asset Bandwidth limits, it will be suspended until the monthly allowance resets at the beginning of the following month.
在项目暂停期间:
🌐 While the project is suspended:
- 用户无法触发新的部署
- 无法访问该应用
- 用户无法更改项目的设置
要立即重新激活该项目,用户可以升级到付费计划。
🌐 To reactivate the project immediately, users can upgrade to a paid plan.
#### 由于账单问题项目暂停 {#project-suspension-due-to-billing-issues}
🌐 Project suspension due to billing issues
如果你有未支付的发票,你的项目订阅将会自动被取消,项目将会被暂停。
🌐 If you have unpaid invoices, the subscription of your project will automatically be canceled and the project suspended.
要重新激活你项目的订阅,请前往 *设置 > 账单与使用情况* 并点击 **重新激活订阅** 按钮。
🌐 To reactivate your project's subscription, head to *Settings > Billing & Usage* and click on the **Reactivate subscription** button.
:::warning
如果你在30天内不解决该问题,你的暂停项目将被删除,所有数据将永久丢失。
🌐 If you do not resolve the issue within 30 days, your suspended project will be deleted and all its data will be permanently lost.
:::
#### 因其他原因暂停项目 {#project-suspension-for-other-reasons}
🌐 Project suspension for other reasons
如果你的项目因非未支付发票导致订阅取消的原因而被暂停,你可能无法自行重新激活项目。你应该会收到一封包含解决问题说明的电子邮件。如果你没有收到电子邮件通知,请联系 [Strapi 支持](mailto:support@strapi.io)。
🌐 If your project was suspended for reasons other than unpaid invoice leading to subscription cancellation, you may not have the possibility to reactivate your project yourself. You should receive an email with instructions on how to resolve the issue. If you do not receive the email notification, please contact [Strapi Support](mailto:support@strapi.io).
### 取消订阅 {#subscription-cancellation}
🌐 Subscription cancellation
如果你想取消你的 Strapi Cloud 订阅,你有两种选择:
🌐 If you want to cancel your Strapi Cloud subscription, you have 2 options:
- 要么将你的项目订阅更改为免费计划(请参阅 [降级到其他计划](/cloud/projects/settings#downgrading-to-another-plan) 文档),
- 或完全删除你的项目(请参见[删除 Strapi Cloud 项目](/cloud/projects/settings#deleting-a-strapi-cloud-project) 文档)。
# 合作
Source: https://docs.strapi.io/cloud/projects/collaboration
# 项目合作 {#collaboration-on-projects}
🌐 Collaboration on projects
项目由用户通过他们的 Strapi Cloud 账户创建。Strapi Cloud 用户可以将他们的项目分享给任何其他人,因此这些新用户可以访问项目仪表板并在该项目上进行协作,而项目拥有者无需分享他们的凭据。
🌐 Projects are created by a user via their Strapi Cloud account. Strapi Cloud users can share their projects to anyone else, so these new users can have access to the project dashboard and collaborate on that project, without the project owner to ever have to share their credentials.
被邀请协作项目的用户,称为维护者,不具有与项目所有者相同的权限。与项目所有者相反,维护者:
🌐 Users invited to collaborate on a project, called maintainers, do not have the same permissions as the project owner. Contrary to the project owner, maintainers:
- 不能自己将项目分享给他人
- 无法从项目设置中删除项目
- 无法访问项目设置的*计费*部分
## 共享项目 {#sharing-a-project}
🌐 Sharing a project
邀请新的维护者参与项目合作:
🌐 To invite a new maintainer to collaborate on a project:
1. 在*项目*页面上,点击你选择的项目即可跳转到其仪表板。
2. 点击位于仪表板页眉的**分享**按钮。
3. 在 *共享 [项目名称]* 对话框中,在文本框中输入要邀请的人的电子邮件地址。应出现一个下拉菜单,显示“邀请 [电子邮件地址]”。
4. 点击下拉菜单:电子邮件地址应显示在文本框正下方的紫色框中。
5. (可选) 重复步骤3和4以邀请更多人。电子邮件地址只能逐一输入,但邀请可以同时发送给多个电子邮件地址。
6. 点击 **发送** 按钮。
新维护者将收到一封电子邮件,其中包含一个链接,点击该链接即可加入项目。一旦项目被共享,代表维护者的头像将显示在项目仪表板的标题栏中,位于 **共享** 按钮旁边,以查看有多少维护者在该项目上协作以及他们是谁。
🌐 New maintainers will be sent an email containing a link to click on to join the project. Once a project is shared, avatars representing the maintainers will be displayed in the project dashboard's header, next to the **Share** button, to see how many maintainers collaborate on that project and who they are.
:::tip
头像使用 GitHub、Google 或 GitLab 的个人资料图片,但对于待审核用户,只有在维护者账户激活之前显示首字母。你可以将鼠标悬停在头像上以显示维护者的全名。
🌐 Avatars use GitHub, Google or GitLab profile pictures, but for pending users only initials will be displayed until the activation of the maintainer account. You can hover over an avatar to display the full name of the maintainer.
:::
## 管理维护者 {#managing-maintainers}
🌐 Managing maintainers
在通过点击项目仪表板的**共享**按钮可访问的*共享 [项目名称]* 对话框中,项目所有者可以查看已被邀请参与项目协作的维护者完整列表。在那里,可以查看每个维护者的当前状态并对其进行管理。
🌐 From the *Share [project name]* dialog accessible by clicking on the **Share** button of a project dashboard, projects owners can view the full list of maintainers who have been invited to collaborate on the project. From there, it is possible to see the current status of each maintainer and to manage them.
显示全名的维护者是指那些在收到邀请邮件后激活了账户的用户。然而,如果列表中显示的是电子邮件地址的维护者,这意味着他们尚未激活账户,因此无法访问项目仪表板。在这种情况下,应在电子邮件地址旁边标明状态以解释问题:
🌐 Maintainers whose full name is displayed are users who did activate their account following the invitation email. If however there are maintainers in the list whose email address is displayed, it means they haven't activated their accounts and can't access the project dashboard yet. In that case, a status should be indicated right next to the email address to explain the issue:
- 待处理:邀请邮件已发送,但维护者尚未采取行动。
- 已过期:电子邮件已在 72 小时前发送,邀请已过期。
对于已过期的状态,可以通过点击 **管理** 按钮,然后选择 **重新发送邀请** 来发送另一封邀请邮件。
🌐 For Expired statuses, it is possible to send another invitation email by clicking on the **Manage** button, then **Resend invite**.
### 撤销维护者权限 {#revoking-maintainers}
🌐 Revoking maintainers
撤销维护者对项目仪表板的访问权限:
🌐 To revoke a maintainer's access to the project dashboard:
1. 点击项目仪表板标题中的 **分享** 按钮。
2. 在“*有权限的人*”列表中,找到要撤销访问权限的维护者,然后点击**管理**按钮。
3. 点击 **撤销** 按钮。
4. 在确认对话框中,再次点击 **撤销** 按钮。
被撤销的维护者将完全无法访问项目仪表板。
🌐 The revoked maintainer will completely stop having access to the project dashboard.
:::note
被撤销项目访问权限的维护者不会收到任何电子邮件或通知。
🌐 Maintainers whose access to the project has been revoked do not receive any email or notification.
:::
# 部署管理
Source: https://docs.strapi.io/cloud/projects/deploys
# 部署管理 {#deployments-management}
🌐 Deployments management
创建一个新的 Strapi Cloud 项目会自动触发该项目的部署。之后,部署可以是:
🌐 The creation of a new Strapi Cloud project automatically trigger the deployment of that project. After that, deployments can be:
- 在需要时手动触发,[从云仪表板](#triggering-a-new-deployment)或[从命令行接口](/cloud/cli/cloud-cli#strapi-deploy),
- 或者每次向分支推送新提交时自动触发,如果 Strapi Cloud 项目已连接到 git 仓库并且启用了“推送时部署”选项(参见 [项目设置](/cloud/projects/settings#modifying-git-repository--branch))。
如果需要,正在进行的部署也可以[手动取消](#cancelling-a-deployment)。
🌐 Ongoing deployments can also be [manually canceled](#cancelling-a-deployment) if needed.
## 触发新的部署 {#triggering-a-new-deployment}
🌐 Triggering a new deployment
要手动触发项目的新部署,请点击项目仪表板标题右上角始终显示的**触发部署**按钮。此操作将在*部署*标签中添加一个新卡片,你可以在其中监控状态并实时查看部署日志(参见[部署历史和日志](/cloud/projects/deploys-history))。
🌐 To manually trigger a new deployment for your project, click on the **Trigger deployment** button always displayed in the right corner of a project dashboard's header. This action will add a new card in the *Deployments* tab, where you can monitor the status and view the deployment logs live (see [Deploy history and logs](/cloud/projects/deploys-history)).
## 取消部署 {#cancelling-a-deployment}
🌐 Cancelling a deployment
如果出于任何原因你想取消正在进行且未完成的部署:
🌐 If for any reason you want to cancel an ongoing and unfinished deployment:
1. 转到最新触发的部署的*部署详细信息*页面(参见[访问日志详情](/cloud/projects/deploys-history#accessing-deployment-details--logs))。
2. 点击右上角的 **取消部署** 按钮。部署的状态将自动更改为 *已取消*。
:::tip
你也可以从列出部署历史的 *Deployments* 标签中取消部署。处于 *Building* 状态的正在进行的部署卡片将显示一个  按钮,用于取消部署。
🌐 You can also cancel a deployment from the *Deployments* tab which lists the deployments history. The card of ongoing deployment with the *Building* status will display a  button for cancelling the deployment.
:::
# 部署历史和日志
Source: https://docs.strapi.io/cloud/projects/deploys-history
# 部署历史和日志 {#deploy-history-and-logs}
🌐 Deployment history and logs
对于每个 Strapi Cloud 项目,你可以访问所有已发生部署的历史记录及其详细信息,包括构建和部署日志。此信息可在 *部署* 选项卡中查看。
🌐 For each Strapi Cloud project, you can access the history of all deployments that occurred and their details including build and deployment logs. This information is available in the *Deployments* tab.
## 查看部署历史记录 {#viewing-deploy-history}
🌐 Viewing the deployment history
在*部署*选项卡中显示了按时间顺序排列的卡片列表,其中包含你项目的所有历史部署的详细信息。
🌐 In the *Deployments* tab is displayed a chronological list of cards with the details of all historical deployments for your project.
,带有指向你的 git 提供者的直接链接,以及提交信息
- 部署状态:
- *部署*
- *完成*
- *已取消*
- *构建失败*
- *部署失败*
- 上次部署时间(部署触发时间及持续时间)
- 分支
## 访问部署详情和日志 {#accessing-deployment-details--logs}
🌐 Accessing deployment details & logs
在 *Deployments* 标签页中,你可以将鼠标悬停在部署卡片上,使  **显示详情** 按钮出现。点击此按钮将重定向到包含部署详细日志的 *Deployment details* 页面。
🌐 From the *Deployments* tab, you can hover a deployment card to make the  **Show details** button appear. Clicking on this button will redirect you to the *Deployment details* page which contains the deployment's detailed logs.
,并提供指向你的 git 提供者的直接链接,以及用于此部署的提交信息
- *状态*,可以是 *构建中*、*部署中*、*完成*、*已取消*、*构建失败* 或 *部署失败*
- *来源*: 此次部署的分支和提交信息
- *持续时间*:部署所花费的时间以及发生的时间
# 通知
Source: https://docs.strapi.io/cloud/projects/notifications
# 通知 {#notifications}
🌐 Notifications
可以通过点击云仪表板顶部导航中的铃铛图标 来打开通知中心。
它显示你所有现有项目的最新通知列表。点击列表中的通知卡片将重定向到对应部署的*日志详情*页面(更多信息请参见[部署历史与日志](/cloud/projects/deploys-history#accessing-deployment-details--logs))。
🌐 It displays a list of the latest notifications for all your existing projects. Clicking on a notification card from the list will redirect you to the *Log details* page of the corresponding deployment (more information in [Deploy history & logs](/cloud/projects/deploys-history#accessing-deployment-details--logs)).
以下通知可以在通知中心列出:
🌐 The following notifications can be listed in the Notifications center:
- *部署完成*:当部署成功完成时。
- *构建失败*:当部署在构建阶段失败时。
- *部署失败*:当部署阶段的部署失败时。
- *已触发部署*:当连接的仓库有新的推送时,会触发部署。然而,当部署是手动触发时,该通知不会发送。
:::note
所有超过30天的通知将自动从通知中心移除。
🌐 All notifications older than 30 days are automatically removed from the Notification center.
:::
# 项目概览
Source: https://docs.strapi.io/cloud/projects/overview
# 项目概览 {#projects-overview}
🌐 Projects overview
*项目* 页面显示你所有 Strapi Cloud 项目的列表。在这里,你可以管理你的项目并访问相应的应用。
🌐 The *Projects* page displays a list of all your Strapi Cloud projects. From here you can manage your projects and access the corresponding applications.
每个项目卡显示以下信息:
🌐 Each project card displays the following information:
* 项目名称
* 生产环境上一次成功部署的日期
* 项目的当前状态:
* *未连接*,如果项目仓库未连接到 Strapi Cloud
* *已暂停*,如果项目已被暂停(请参阅[项目暂停](/cloud/getting-started/usage-billing#project-suspension)以重新激活项目)
* *版本不兼容*,如果项目使用的 Strapi 版本与 Strapi Cloud 不兼容
每个项目卡还显示一个 菜单图标,以访问以下选项:
* **访问应用**:跳转到应用
* **转到部署**:以跳转到 [*部署*](/cloud/projects/deploys) 页面
* **前往设置**:以被重定向到 [*设置*](/cloud/projects/settings) 页面
:::tip
点击导航栏中的 * 产品更新* 按钮,查看最新发布的功能和修复内容。
:::
## 访问项目仪表板 {#accessing-a-projects-dashboard}
🌐 Accessing a project's dashboard
在 *项目* 页面,点击任意项目卡片以访问其仪表板。它显示项目和环境的详细信息,并可访问部署历史记录以及所有可用的设置。
🌐 From the *Projects* page, click on any project card to access its dashboard. It displays the project and environment details and gives access to the deployment history and all available settings.
在所选项目的仪表板标题中,你可以:
🌐 From the dashboard's header of a chosen project, you can:
- 使用 **共享** 按钮邀请用户协作项目(参见 [协作](/cloud/projects/collaboration))并查看已被邀请的用户图标 ,
- 使用 **设置**按钮访问项目及其现有环境的设置 ,
- 选择要为项目可视化的环境或添加新环境 ,
- 触发新的部署(参见 [部署管理](/cloud/projects/deploys))并访问你的应用 。
你的项目仪表板还显示:
🌐 Your project's dashboard also displays:
- “*部署*” 和 “*运行日志*” 标签,用于查看部署历史(更多详情请参见 [部署历史和日志](/cloud/projects/deploys-history))以及项目的运行日志(参见 [专用文档页面](/cloud/projects/runtime-logs))
- 界面右侧框中的项目和环境详细信息 ,包括:
- API 调用次数,
- 资源带宽和存储的当前使用情况,
- 分支的名称以及一个 **管理** 按钮,用于重定向到分支设置(参见 [修改 git 仓库和分支](/cloud/projects/settings#modifying-git-repository--branch)),
- 基目录的名称,
- Strapi 版本号,
- Strapi 应用的 URL。
# 运行时日志
Source: https://docs.strapi.io/cloud/projects/runtime-logs
# 运行时日志 {#runtime-logs}
🌐 Runtime logs
在选定项目的仪表板中,*运行时日志* 标签显示项目的实时日志。
🌐 From a chosen project's dashboard, the *Runtime logs* tab displays the live logs of the project.
:::note
- 只有在项目成功部署后,才能访问*运行时日志*。
- 免费的计划中的项目运行时日志不是实时的,并且每次由于不活动而将应用缩放为零时都会被重置。
:::
# 项目设置
Source: https://docs.strapi.io/cloud/projects/settings
# 项目设置 {#project-settings}
🌐 Project settings
在所选项目的仪表板中,位于页眉的 **设置**按钮使你能够管理你的 Strapi Cloud 项目及其环境的配置和设置。
界面左侧的设置菜单分为两类:整个项目的设置以及针对项目中配置的任何环境的特定设置。
🌐 The settings' menu on the left side of the interface is separated into 2 categories: the settings for the entire project and the settings specific to any configured environment for the project.
## 项目级设置 {#project-level-settings}
🌐 Project-level settings
项目设置有5个可用的标签页:
🌐 There are 5 tabs available for the project settings:
- [*通用*](#general),
- [*环境*](#environments),
- [*账单与使用*](#billing--usage),
- [计划](#plans),
- 以及 [发票](#invoices)。
### 一般 {#general}
🌐 General
项目级设置的 *常规*选项卡使你能够检查和更新项目的以下选项:
- *基本信息*,请参见:
- 你的 Strapi Cloud 项目的名称——用于在云控制面板、Strapi CLI 和部署 URL 上识别项目——并更改它(参见 [重命名项目](#renaming-project))。
- 你为 Strapi Cloud 项目选择的托管区域,即项目及其数据和资源存储的服务器的地理位置。托管区域在创建项目时设置(参见 [项目创建](/cloud/getting-started/deployment)),之后无法修改。
- 项目的元数据,包括生产应用的内部名称和订阅 ID,这对于调试和支持目的可能很有用。
- *Strapi CMS 许可证密钥*:用于在你的云项目上直接启用和使用某些 CMS 功能(请参阅[定价页面](https://strapi.io/pricing-self-hosted)购买许可证)。
- *已连接的 Git 仓库*:用于更改项目使用的仓库和分支(请参见 [修改 git 仓库与分支](#modifying-git-repository--branch))。还可以启用/禁用“推送时部署”选项。
- *危险区域*,与:
- *转移所有权*:项目所有者将云项目的所有权转移给已存在的维护者(参见[转移项目所有权](#transferring-project-ownership))。
- *删除项目*:永久删除你的 Strapi Cloud 项目(参见 [删除 Strapi Cloud 项目](#deleting-a-strapi-cloud-project))。
#### 重命名项目 {#renaming-project}
🌐 Renaming project
项目名称在项目创建时设置(参见 [项目创建](/cloud/getting-started/deployment)),之后可以通过项目设置进行修改。
🌐 The project name is set at project creation (see [Project creation](/cloud/getting-started/deployment)) and can be modified afterwards via the project settings.
1. 在 *常规*选项卡的*基本信息*部分,点击 编辑按钮。
2. 在对话框中,在*项目名称*文本框中写上你选择的新项目名称。
3. 点击 **重命名** 按钮以确认项目名称的修改。
#### 添加 CMS 许可证密钥 {#adding-cms-license-key}
🌐 Adding a CMS license key
可以将 CMS 许可证密钥添加并连接到 Strapi Cloud 项目,以解锁整个项目环境中的额外 Strapi CMS 功能。通过许可证密钥可访问的 CMS 功能取决于所购买的许可证类型。有关更多信息和/或购买许可证,请参阅 。
:::note
如果你没有看到 *Strapi CMS 许可密钥* 部分,这可能意味着你的订阅是旧版订阅,并且不支持自定义 CMS 许可。这意味着你已经拥有一个会自动包含在你的项目中的许可。
🌐 If you don't see the *Strapi CMS license key* section, it probably means that your subscription is a legacy one and does not support custom CMS licenses. It means that you already have one that is automatically included on your project.
:::
1. 在 *Strapi CMS 许可密钥* 部分,点击 **添加许可** 按钮。
2. 在对话框中,将你的许可密钥粘贴到字段中。
3. 点击 **保存并部署** 按钮以使更改生效。
要从你的 Strapi Cloud 项目中移除 Strapi CMS 许可证,你可以点击 **取消关联许可证** 按钮。这也将移除对之前添加的许可证中包含的 CMS 功能的访问和使用权限。
🌐 To remove the Strapi CMS license from your Strapi Cloud project, you can click on the **Unlink license** button. This will also remove access and usage to the CMS features included in the previously added license.
:::note
许可证密钥已应用于项目中的所有环境。
🌐 The license key is applied to all the environments in the project.
:::
#### 修改 git 仓库和分支 {#modifying-git-repository--branch}
🌐 Modifying git repository & branch
Strapi Cloud 项目的 GitHub 或 GitLab 仓库、分支和基础目录默认在创建项目时选择(参见 [创建项目](/cloud/getting-started/deployment))。在项目创建后,可以通过项目设置更新项目仓库或切换到其他 Git 提供商。
🌐 The GitHub or GitLab repository, branch and base directory for a Strapi Cloud project are by default chosen at the creation of the project (see [Creating a project](/cloud/getting-started/deployment)). After the project's creation, via the project settings, it is possible to update the project repository or switch to another git provider.
:::caution
更新 git 仓库可能导致项目及其数据的丢失,例如如果选择了错误的仓库或旧仓库与新仓库之间的数据结构不匹配。
🌐 Updating the git repository could result in the loss of the project and its data, for instance if the wrong repository is selected or if the data schema between the old and new repository doesn't match.
:::
1. 在 *常规*选项卡的*已连接的 Git 仓库*部分,点击**更新仓库**按钮。你将被重定向到另一个界面。
2. (可选)如果你希望不仅更新仓库,还想切换到另一个 git 提供商,请点击界面右上角的 **切换 Git 提供商** 按钮。在返回 *更新仓库* 界面之前,你将被重定向到所选 git 提供商的授权设置。
3. 在*更新仓库*部分,填写两个可用的设置:
| 设置名称 | 使用说明 || --------------- | ------------------------------------------------------------------------ || 账户 | 从下拉列表中选择一个账户。 || 仓库 | 从下拉列表中选择一个仓库。 |
4. 在 *选择 Git 分支* 部分,为你的任何环境填写可用设置。请注意,每个环境的分支可以通过其自身的设置进行编辑,参见 [常规(环境)](#environments)。
| 设置名称 | 说明 || --------------- | ------------------------------------------------------------------------ || 分支 | 从下拉列表中选择一个分支。 || 基本目录 | 在文本框中填写基本目录的路径。 || 自动部署 | 勾选该框以在向所选分支推送新提交时自动触发新部署。取消勾选以禁用此选项。 |
5. 点击 **保存并部署** 按钮以使更改生效。
#### 转移项目所有权 {#transferring-project-ownership}
🌐 Transferring project ownership
Strapi Cloud 项目的所有权可以转让给其他用户,只要他们是该项目的维护者。这可以由当前项目所有者主动发起,也可以由项目维护者提出请求。一旦所有权转让完成,该转让将是永久的,直到新所有者决定再次将所有权转让给另一位维护者。
🌐 The ownership of the Strapi Cloud project can be transferred to another user, as long as they're a maintainer of the project. It can either be at the initiative of the current project owner, or can be requested by a project maintainer. Once the ownership is transferred, it is permanent until the new owner decides to transfer the ownership again to another maintainer.
:::prerequisites
要转让项目的所有权,必须满足以下要求:
🌐 For the ownership of a project to be transferred, the following requirements must be met:
- 该项目必须使用付费计划,且当前无已过期的卡或未支付的账单。
- 维护者必须已经填写了他们的账单信息。
- 该项目不得有任何现有的所有权转让在进行中。
请注意,当在订阅续订的同一天(即每月的1日)进行所有权转让时,转让可能会失败。如果当天转让失败,但所有先决条件已满足,你应等待几小时后再尝试。
🌐 Note that ownership transfers might fail when done the same day of subscription renewal (i.e. 1st of every month). If the transfer fails that day, but all prerequisites are met, you should wait a few hours and try again.
:::
1. 在 *常规*选项卡的*危险区域*部分,点击**转移所有权**按钮。
2. 在对话中:
- 如果你是项目拥有者:通过点击其名字旁的 **...** > **转让所有权** 来选择应被转让所有权的维护者。
- 如果你是维护者:在列表中找到自己,然后点击与你的名字相关的 **...** > **转让所有权**。
3. 在新对话框中点击 **转移所有权** 按钮以确认转移/请求。
一封电子邮件将发送给两位用户。需要转让所有权或继承的人员必须点击电子邮件中的 **确认转让** 按钮。完成后,前所有者将收到一封确认电子邮件,确认转让已成功完成。
🌐 An email will be sent to both users. The person who needs to transfer the ownership or inherit it will have to click on the **Confirm transfer** button in the email. Once done, the previous owner will receive a confirmation email that the transfer has successfully been done.
:::tip
只要所有权转移或请求尚未确认,就可以在选择维护者的同一对话框中选择取消。
🌐 As long as the ownership transfer or request hasn't been confirmed, there is the option to cancel in the same dialog that the maintainer was chosen.
:::
:::note
一旦所有权转移完成,项目将与 Strapi Cloud 断开连接。作为新所有者,请确保前往项目设置的 *常规*选项卡以重新连接项目。
:::
#### 删除 Strapi Cloud 项目 {#deleting-a-strapi-cloud-project}
🌐 Deleting a Strapi Cloud project
你可以删除任何 Strapi Cloud 项目,但这是永久且不可逆的。相关的域名、部署和数据将被删除,项目的订阅将自动取消。
🌐 You can delete any Strapi Cloud project, but it will be permanent and irreversible. Associated domains, deployments and data will be deleted and the subscription for the project will automatically be canceled.
1. 在 *常规*选项卡的*危险区域*部分,点击**删除项目**按钮。
2. 在对话框中,选择删除项目的原因。
3. 通过点击 **删除项目** 按钮来确认删除你的项目。
### 环境 {#environments}
🌐 Environments
“环境”选项卡允许查看 Strapi Cloud 项目中配置的所有环境,以及创建新的环境。生产环境是默认环境,无法删除。可以根据项目的订阅计划创建其他环境,以便在 Strapi Cloud 项目的独立实例上更安全地工作(例如,一个暂存环境,用于在上线到生产环境前进行测试)。
:::note
你购买的附加环境的计费周期将与你的计划计费周期相匹配。
🌐 The billing cycle of additional environments you purchase will match the billing cycle of your plan.
:::
要创建一个新环境:
🌐 To create a new environment:
1. 点击 **添加新环境** 按钮。
2. 在设置步骤中,填写可用的设置:
| 设置名称 | 说明 || ---------------- | ------------------------------------------------------------------------ || 环境名称 | (必填)为你的项目新环境写一个名称。 || Git 分支 | (必填)为你的新环境选择正确的分支。 || 基础目录 | 写入你的新环境的基础目录名称。 || 推送时部署 | 勾选此框以在向所选分支推送更改时自动触发部署。若未启用,则需要手动部署最新更改。 || 导入变量 | 勾选此框从现有环境导入变量名称。值不会被导入,所有变量将保持为空。 |
3. 点击 **确认** 以继续到结账步骤。
4. 查看环境价格、适用税费和按比例调整。
5. 点击 **添加环境** 按钮以创建项目的新环境。然后,你将被重定向到你的 *项目仪表板*,在那里你可以跟踪新环境的创建和首次部署。
:::note
如果在环境创建过程中发生错误,进度指示器将停止并显示错误消息。你将在失败步骤旁看到一个**重试**按钮,允许你重新启动创建过程。
🌐 If an error occurs during the environment creation, the progress indicator will stop and display an error message. You will see a **Retry** button next to the failed step, allowing you to restart the creation process.
:::
### 账单与使用情况 {#billing--usage}
🌐 Billing & Usage
“ *账单与使用情况*”标签显示你下次预计付款、当前订阅计划的所有信息以及项目使用情况的详细摘要。它还允许你为项目添加新环境(请 [参考环境部分的文档](#environments))。
通过此标签,你还可以:
🌐 Through this tab, you also have the possibility to:
- 点击 **更改** 按钮将被重定向到 *计划* 标签,在那里你可以更改你的订阅计划或计费周期([参见相关文档](#plans)),
- 点击 **编辑** 按钮以设置新的付款方式(参见 [相关文档](/cloud/account/account-billing))。
:::note
你可以通过直接从此页面选择付款方式,将专用卡附加到你的项目。这样,你可以使用不同的卡管理你的订阅。
🌐 You can attach a dedicated card to your project by choosing the payment method directly from this page. In that way, you can manage your subscriptions with different cards.
:::
:::tip
在 *计费与使用*选项卡的使用情况部分,你可以看到项目当前的每月使用量与项目订阅允许的最大使用量的对比。使用右上角的箭头可以查看项目在任意选定月份的使用情况。
还请注意,如果你的使用情况显示另一种订阅计划更适合你的项目,系统将在 *计费与使用*标签中显示一条消息,建议你可以切换到哪个计划。
:::
### 计划 {#plans}
🌐 Plans
“Plans” 标签显示可用的 Strapi Cloud 计划概览,并允许你更改当前计划或账单周期。
:::info
如果你当前的计划被标记为*旧版*,你将能够切换到新的计划(请参阅[降级部分](#downgrading-to-another-plan))。一旦你切换,你将无法再访问之前的计划。
🌐 If your current plan is labeled as *legacy*, you will be able to sidegrade to a new plan (see [downgrade section](#downgrading-to-another-plan)). Once you sidegrade, you will no longer have access to your previous plan.
:::
#### 升级到其他方案 {#upgrading-to-another-plan}
🌐 Upgrading to another plan
计划升级是即时的,并且可以通过每个项目的项目设置进行管理。
🌐 Plan upgrades are immediate and can be managed, for each project, via the project settings.
要将你当前的计划升级到更高级别,请:
🌐 To upgrade your current plan to a higher one:
1. 在项目设置的 *计划*选项卡中,选择按月或按年计费的频率,然后点击你想升级的计划的**升级**按钮。
2. 在打开的窗口中,查看升级的付款详情和条款。
a.(可选)点击 **编辑** 按钮以选择其他付款方式。
b.(可选)点击 **我有折扣码**,在字段中输入你的折扣码,然后点击 **应用** 按钮。
3. 点击 **升级到 [plan name]** 按钮以确认升级。项目将自动重新部署。
#### 降级到另一个计划 {#downgrading-to-another-plan}
🌐 Downgrading to another plan
每个项目的计划降级可以通过项目设置进行管理。然而,降级不会立即生效:当前计划将继续有效,直到当前计费周期结束。
🌐 Plan downgrades can be managed, for each project, via the project settings. Downgrades are, however, not immediately effective: the current plan will remain active until the end of the current billing period.
:::caution
在降级之前,请确保检查你的 Strapi Cloud 项目的使用情况:如果你当前的使用量超出了较低套餐的限制,你将面临超额收费的风险。你还可能会失去某些功能的访问权限:例如,降级到 Essential 计划将导致你项目的所有备份丢失。有关更多信息,请参阅 [计费与使用信息](/cloud/getting-started/usage-billing)。
🌐 Make sure to check the usage of your Strapi Cloud project before downgrading: if your current usage exceeds the limits of the lower plan, you are taking the risk of getting charged for overages. You may also lose access to some features: for example, downgrading to the Essential plan would result in the loss of all your project's backups. Please refer to [Information on billing & usage](/cloud/getting-started/usage-billing) for more information.
请注意,如果你有额外的付费环境,则无法降级。你需要先删除计划基础价格中未包含的所有额外环境(请参见 [重置与删除环境](#resetting--deleting-environment)),然后才能安排降级。当从Scale降级到Pro时,额外包含的环境将在降级生效时自动删除。
🌐 Note also that you cannot downgrade if you have additional paid environments. You will first need to delete all additional environments that were not included in the base price of you plan (see [Resetting & Deleting environment](#resetting--deleting-environment)) before you can schedule a downgrade. When downgrading from Scale to Pro, the additional included environment will automatically be deleted when the downgrade takes effect.
如果项目连接了 GitHub 组织仓库,则无法降级到免费计划。要降级,请先在 [已连接的 Git 仓库](#modifying-git-repository--branch) 设置中切换到个人仓库。
🌐 You cannot downgrade to the Free plan if a GitHub organization repository is connected to the project. To downgrade, first switch to a personal repository in the [Connected Git repository](#modifying-git-repository--branch) settings.
:::
要将你当前的计划降级到较低的计划:
🌐 To downgrade your current plan to a lower one:
1. 在项目设置的 *计划*选项卡中,选择按月或按年计费频率,然后点击你想降级到的计划的**降级**按钮。
2. 在打开的窗口中,查看降级条款。
3. 点击 **降级** 按钮以确认降级。项目将自动重新部署。
:::tip
降级将在当前计费周期结束时生效。在更改待处理期间,你可以取消已安排的降级并继续使用当前计划。
🌐 Downgrades are effective at the end of the current billing period. Whilst the change is pending, you can cancel the scheduled downgrade and stay on your current plan.
:::
#### 更改账单周期 {#changing-billing-cycle}
🌐 Changing billing cycle
你可以随时在每月和每年计费之间切换项目的计费周期。虽然项目计划和附加组件可以根据你的计费周期按月或按年计费,但超额部分始终按月计费。
🌐 You can switch your project's billing cycle between monthly and yearly billing at any time. While project plans and addons can either be billed monthly or yearly depending on your billing cycle, overages are always billed monthly.
要更改你的计费周期:
🌐 To change your billing cycle:
1. 在项目设置的 *计划*选项卡中,使用计划部分顶部的切换按钮在按月和按年计费之间切换。
2. 点击你当前计划的 **切换到[每月/每年]计费** 按钮。
3. 在打开的窗口中,查看计费周期更改的条款。
4. 点击**确认切换**以确认更改。
:::note
当从年度计费切换到每月计费时,你的计划将在下一个续订日期之前保持年度周期。在更改待处理期间,你可以取消计划中的更改并继续使用当前的计费周期。然而,当从每月计费切换到年度计费时,更改会立即生效。
🌐 When switching from yearly to monthly billing, your plan will remain on its yearly cycle until your next renewal date. Whilst the change is pending, you can cancel the scheduled change and stay on your current billing cycle. When switching from monthly to yearly, however, the change is immediate.
:::
### 发票 {#invoices}
🌐 Invoices
“ *发票*”标签显示你的 Strapi Cloud 项目的全部发票列表及其状态。免费计划不提供发票。
:::strapi Invoices are also available in your profile settings.
在 *个人资料 > 发票* 选项卡中,你将找到所有项目的完整发票列表。欢迎查看[专用文档](/cloud/account/account-billing#account-invoices)。
🌐 In the *Profile > Invoices* tab, you will find the complete list of invoices for all your projects. Feel free to check the [dedicated documentation](/cloud/account/account-billing#account-invoices).
:::
## 环境级设置 {#environment-level-settings}
🌐 Environment-level settings
在项目的环境设置中,你首先需要使用下拉菜单选择要配置其设置的环境。根据所选的环境,通常有3到4个可用的选项卡:
🌐 In the project's environments' settings, you first need to select the environment whose settings you would like to configure, using the dropdown. Depending on the chosen environment, there are 3 to 4 tabs available:
- [*配置*](#configuration),
- [*备份*](#backups),仅适用于生产环境,
- [*字段*](#domains),
- 和 [*变量*](#variables)。
### 配置 {#configuration}
🌐 Configuration
环境级设置的 *配置*选项卡使你能够检查和更新项目的以下选项:
- *基本信息*,请参见:
- 你的 Strapi Cloud 项目的环境名称。环境名称在创建时设置,之后无法修改。
- 环境的 Node 版本:要更改项目的 Node 版本(参见 [修改 Node 版本](#modifying-node-version))。
- 应用用于环境的内部名称,这对于调试和支持目的可能非常有用。
- *已连接的分支*: 用于更改环境所使用的 GitHub 仓库分支(请参阅 [编辑 Git 分支](#editing-git-branch))。还可以启用/禁用“推送时部署”选项。
- *环境数据*:从同一项目内的另一个环境传输数据(参见[在环境之间传输数据](#transferring-data-between-environments))。
- *危险区域*:重置或永久删除你的 Strapi Cloud 项目的环境(参见 [重置和删除环境](#resetting--deleting-environment))。
#### 修改 Node 版本 {#modifying-node-version}
🌐 Modifying Node version
环境的 Node 版本基于创建项目时选择的版本(参见[创建项目](/cloud/getting-started/deployment)),通过高级设置。之后可以为任何环境切换到其他 Node 版本。
🌐 The environment's Node version is based on the one chosen at the creation of the project (see [Creating a project](/cloud/getting-started/deployment)), through the advanced settings. It is possible to switch to another Node version afterwards, for any environment.
1. 在 *配置*选项卡的*基本信息*部分,点击*节点版本*的编辑 按钮。
2. 在对话框中使用 *Node 版本* 下拉菜单,点击你选择的版本。
3. 点击 **保存**,或者如果你希望更改立即生效,就点击 **保存并部署**。
:::tip
在部署之前,确保你在 Strapi 项目中配置的 Node 版本与项目仪表板中显示的 Node 版本匹配。
🌐 Ensure the Node version configured in your Strapi project matches the Node version shown in your project’s dashboard before deploying.
:::
#### 编辑 Git 分支 {#editing-git-branch}
🌐 Editing Git branch
1. 在 *编辑分支* 对话框中,编辑可用的设置。请注意,可以通过项目设置同时编辑所有环境的分支,详见 [常规](#general)。
| 设置名称 | 说明 || --------------- | ------------------------------------------------------------------------ || 选择的分支 | (必填)从下拉列表中选择一个分支。 || 基础目录 | 在文本框中填写基础目录的路径。 || 在每次向此分支推送提交时部署项目 | 选中此框可在向所选分支推送新提交时自动触发新部署。取消选中以禁用该选项。 |
2. 点击 **保存并部署** 按钮以使更改生效。
#### 在环境之间传输数据 {#transferring-data-between-environments}
🌐 Transferring data between environments
数据传输功能允许你将整个 CMS 内容(数据库和资源)从一个环境传输到同一 Strapi Cloud 项目中的另一个环境。这对于在次要环境中使用最新的生产数据测试更改,或在将内容投入生产之前在次要环境中准备和排练内容非常有用。
🌐 The data transfer feature allows you to transfer the entire CMS content (database and assets) from one environment to another within the same Strapi Cloud project. This is useful for testing changes in a secondary environment with up-to-date production data, or for preparing and staging content in a secondary environment before taking it to production.
在环境之间传输数据目前存在以下限制:
🌐 Transferring data between environments currently comes with the following limitations:
- 你只能转移到辅助环境(不能转移到生产环境)。
- 只有项目所有者才能发起和管理正在进行的转移。
- 暂停的项目无法发起转账。
:::caution Data transfers are destructive
将数据传输到某个环境将永久覆盖目标环境中的所有现有数据和资源。源环境的数据不受影响,并且在传输期间可以访问其 CMS。环境设置(例如变量和域)不会受到传输的影响。
🌐 Transferring data to an environment will permanently overwrite all existing data and assets in the target environment. The source environment's data remains unaffected, and its CMS can be accessed during the transfer. Environment settings (such as variables and domains) are not affected by the transfer.
:::
将数据传输到次要环境:
🌐 To transfer data to a secondary environment:
1. 创建并部署源和目标[环境](#environments)。
2. 在 *配置*选项卡的*环境数据*部分,点击**导入数据**按钮。
3. 在打开的模态窗口中,从下拉列表中选择源环境。只有完全创建并部署的环境可用作源。
4. 点击 **导入数据** 以继续,然后按照步骤确认传输。
5. 一旦启动,你将被重定向到环境的仪表板,在那里你可以监控传输的进度。传输完成后,仪表板将刷新,显示正在进行的和历史的部署。
:::note
在传输进行时,目标环境的 CMS 将无法访问。你可以取消正在进行的传输,但这将使目标环境为空。如果在传输过程中发生错误,你将有选项重新尝试或取消。
🌐 The CMS of the target environment will be inaccessible whilst the transfer is ongoing. You can cancel an ongoing transfer, but this will leave the target environment empty. If an error occurs during the transfer, you will have the option to retry or cancel.
:::
#### 重置和删除环境 {#resetting--deleting-environment}
🌐 Resetting & Deleting environment
你可以重置或删除 Strapi Cloud 项目的任何附加环境,但这是永久且不可逆的。然而,默认的生产环境既不能重置也不能删除。
🌐 You can reset or delete any additional environment of your Strapi Cloud project, but it will be permanent and irreversible. The default, production environment, can however neither be reset nor deleted.
##### 重置环境 {#resetting-an-environment}
🌐 Resetting an environment
重置环境会删除所有环境数据,并将变量重置为默认值。操作步骤如下:
🌐 Resetting an environment deletes all environments data and resets the variables to their default. To do so:
1. 在 *配置*选项卡的*危险区域*部分,点击**重置环境**按钮。
2. 在打开的对话框中,点击 **继续** 按钮以确认环境重置。
3. 填写可用字段以重置环境:
| 设置名称 | 说明 || --------------- | ------------------------------------------------------------------------ || 环境名称 | (必填)为项目的新环境写一个名称。 || Git 分支 | (必填)从下拉列表中选择一个分支。 || 基目录 | 在文本框中写入基目录的路径。 || 导入变量 | 勾选此框以从现有环境导入变量名。值不会被导入,所有变量将保持为空。 || 自动部署 | 在每次提交到该分支时部署项目。勾选此框以在新提交推送到所选分支时自动触发新的部署。取消勾选以禁用此选项。 |
4. 点击 **重置** 按钮。
##### 删除环境 {#deleting-an-environment}
🌐 Deleting an environment
1. 在 *配置*选项卡的*危险区域*部分,点击**删除环境**按钮。
2. 在文本框中输入你的*环境名称*。
3. 点击 **删除环境** 按钮以确认删除。
### 备份 {#backups}
🌐 Backups
“ *备份*”标签会通知你 Strapi Cloud 项目的最新备份状态和日期。所有现有 Strapi Cloud 项目关联的数据库确实会自动备份(专业版计划为每周一次,Scale 计划为每日一次)。备份会保留 28 天。此外,你还可以创建单次手动备份。
:::note Notes
- 备份功能在免费或基础计划的 Strapi Cloud 项目中不可用。你需要升级到专业版或扩展版计划,以启用自动备份并访问手动备份选项。
- 备份仅包括你默认生产环境的数据库。上传到你的项目的资源和任何辅助环境的数据库不包括在内。
- 项目首次成功部署后不久,手动备份选项就会可用。
:::
:::tip
对于在2023年10月备份功能发布之前创建的项目,首次备份将在下次项目部署时自动触发。
🌐 For projects created before the release of the Backup feature in October 2023, the first backup will automatically be triggered with the next deployment of the project.
:::
#### 创建手动备份 {#creating-a-manual-backup}
🌐 Creating a manual backup
要创建手动备份,在 *备份*部分,点击**创建备份**按钮。
手动备份应立即开始,在备份完成之前,恢复或创建其他备份将被禁用。
🌐 The manual backup should start immediately, and restoration or creation of other backups will be disabled until the backup is complete.
:::caution
在创建新的手动备份时,任何现有的手动备份都将被删除。你一次只能拥有一个手动备份。
🌐 When creating a new manual backup, any existing manual backup will be deleted. You can only have one manual backup at a time.
:::
#### 恢复备份 {#restoring-a-backup}
🌐 Restoring a backup
如果你需要恢复项目的备份:
🌐 If you need to restore a backup of your project:
1. 在 *备份*部分,点击**恢复备份**按钮。
2. 在对话框中,从*选择备份*下拉菜单中选择你项目的可用备份(自动备份或手动备份)之一。
3. 点击对话框中的 **恢复** 按钮。恢复完成后,你的项目将回到所选备份时的状态。你将能够在 *备份* 标签中看到恢复的时间戳和所恢复的备份。
4. 将显示上次完成恢复的时间戳,以帮助你追踪项目上次恢复的时间。
#### 正在下载备份 {#downloading-a-backup}
🌐 Downloading a backup
如果你需要下载项目的备份:
🌐 If you need to download a backup of your project:
1. 在 *备份*部分,点击**下载备份**按钮。
2. 在对话框中,从*选择备份*下拉菜单中选择你项目的可用备份(自动备份或手动备份)之一。
3. 点击对话框中的 **下载** 按钮,以 `.sql` 格式下载所选备份的归档文件。
:::note
备份文件将仅包含你默认生产环境的数据库。它不会包含资源或任何其他环境的数据库。
🌐 The backup file will include only the database of your default Production environment. It will not include assets or any other environment databases.
:::
### 域名 {#domains}
🌐 Domains
“Domains”选项卡使你能够管理域并连接新的域名。
你 Strapi Cloud 项目的所有现有域都列在 *域*标签中。对于每个域,你可以:
- 查看其当前状态:
- 活跃:该域名当前已确认并处于活跃状态
- 待处理:域名转移正在进行中,正在等待 DNS 变更生效
- 失败:由于发生错误,域更改请求未完成
- 点击 编辑按钮以访问域名设置
- 点击 删除按钮以删除域
#### 连接自定义域名 {#connecting-a-custom-domain}
🌐 Connecting a custom domain
默认域名由两个随机生成的单词加上一个哈希组成。它们可以被你选择的任何自定义域名替换。
🌐 Default domain names are made of 2 randomly generated words followed by a hash. They can be replaced by any custom domain of your choice.
:::note
自定义域名在免费计划中不可用。降级到免费计划将导致应用域名恢复为默认域名。
🌐 Custom domains are not available on the Free plan. Downgrading to the Free plan will result in the application domain's being restored to the default one.
:::
1. 点击 **连接新域名** 按钮。
2. 在打开的窗口中,填写以下字段:
| 设置名称 | 说明 || --- | --- || 域名 | 输入新的域名(例如 *custom-domain-name.com*) || 主机名 | 输入主机名(即终端用户在浏览器中输入的地址,或通过 API 调用的地址)。 || 目标 | 输入目标(即用户输入主机名时重定向到的实际地址)。 || 设置为默认域名 | 勾选此框以将新域名设置为默认域名。 |
3. 点击 **保存并部署** 以使更改生效。
:::tip
要完成自定义域名的设置,请在你的域名注册商或托管平台的设置中,将目标值(例如 `proud-unicorn-123456af.strapiapp.com`)作为 CNAME 别名添加到你域名的 DNS 记录中。
🌐 To finish setting up your custom domain, in the settings of your domain registrar or hosting platform, please add the Target value (e.g., `proud-unicorn-123456af.strapiapp.com`) as a CNAME alias to the DNS records of your domain.
:::
:::info Custom domains and assets
使用自定义域名时,这些域名不适用于已上传资源的 URL。已上传的资源保持 Strapi Cloud 基于项目的 URL。
🌐 When using custom domains, these domains do not apply to the URLs of uploaded assets. Uploaded assets keep the Strapi Cloud project-based URL.
这意味着,如果你的自定义域托管在 `https://my-custom-domain.com`,并且你的 Strapi Cloud 项目名称是 `my-strapi-cloud-instance`,API 调用仍将返回类似 `https://my-strapi-cloud-instance.media.strapiapp.com/example.png` 的 URL。
🌐 This means that, if your custom domain is hosted at `https://my-custom-domain.com` and your Strapi Cloud project name is `my-strapi-cloud-instance`, API calls will still return URLs such as `https://my-strapi-cloud-instance.media.strapiapp.com/example.png`.
通过 REST 或 GraphQL 进行的媒体库查询总是返回 Strapi Cloud 上的项目媒体域。如果你从自托管项目迁移,媒体 URL 将不再与你自己的域或 CDN 匹配。请计划使用 API 返回的绝对 URL,或调整前端以允许 Strapi Cloud 媒体域(更多详情请参见 [Cloud Fundamentals](/cloud/cloud-fundamentals))。
🌐 Media library queries over REST or GraphQL always return the project media domain on Strapi Cloud. If you move from a self-hosted project, media URLs will no longer match your own domain or CDN. Plan to use the absolute URLs returned by the API, or adjust your frontend to allow the Strapi Cloud media domain (see [Cloud Fundamentals](/cloud/cloud-fundamentals) for more details).
:::
### 变量 {#variables}
🌐 Variables
环境变量(更多信息请参见 [CMS 文档](/cms/configurations/environment))用于配置你的 Strapi 应用的环境,例如数据库连接。
🌐 Environment variables (more information in the [CMS Documentation](/cms/configurations/environment)) are used to configure the environment of your Strapi application, such as the database connection.
在 *变量*标签中列出了你 Strapi Cloud 项目的默认和自定义环境变量。每个变量由一个*名称*和一个*值*组成。
#### 管理环境变量 {#managing-environment-variables}
🌐 Managing environment variables
将鼠标悬停在环境变量上,无论是默认的还是自定义的,都会显示以下可用选项:
🌐 Hovering on an environment variable, either default or custom, displays the following available options:
- **显示值**以使用变量的实际值替换`*`字符。
- **复制到剪贴板**以复制变量的值。
- **操作**以访问 编辑和 删除按钮。
- 编辑默认变量时,*名称*无法修改,*值*只能通过 生成值按钮自动生成。别忘了 **保存**,如果你希望更改立即生效,则选择 **保存并部署**。
- 在编辑自定义变量时,*名称*和*值*都可以通过输入新内容或使用 生成值按钮来修改。别忘了**保存**,如果希望更改立即生效,请选择**保存并部署**。
- 删除变量时,系统会要求你通过选择 **保存** 或 **保存并部署** 来确认,如果你希望更改立即生效请选择 **保存并部署**。
:::tip
使用搜索栏可以更快地在列表中找到环境变量!
🌐 Use the search bar to find more quickly an environment variable in the list!
:::
#### 创建自定义环境变量 {#creating-custom-environment-variables}
🌐 Creating custom environment variables
可以为 Strapi Cloud 项目创建自定义环境变量。创建或编辑环境变量后,请确保重新部署你的项目。
🌐 Custom environment variables can be created for the Strapi Cloud project. Make sure to redeploy your project after creating or editing an environment variable.
1. 在*自定义环境变量*部分,点击**添加变量**按钮。
2. 在同名字段中填写新环境变量的*名称*和*值*。或者,你可以点击 图标自动生成名称和值。
3. (可选)点击 **添加另一个** 来直接创建一个或多个其他自定义环境变量。
4. 点击 **保存** 按钮以确认创建自定义环境变量。要立即应用更改,请点击 **保存并部署**。
# 管理面板定制
Source: https://docs.strapi.io/cms/admin-panel-customization
# 管理面板定制 {#admin-panel-customization}
🌐 Admin panel customization
Strapi 的 **前端部分** 称为管理面板。管理面板提供图形用户界面,帮助你构建和管理通过内容 API 可访问的内容。要了解管理面板的概览,请参考 [入门 > 管理面板](/cms/features/admin-panel) 页面。
从开发者的角度来看,Strapi 的管理面板是一个基于 React 的单页应用,它封装了 Strapi 应用的所有功能和已安装的插件。
🌐 From a developer point of view, Strapi's admin panel is a React-based single-page application that encapsulates all the features and installed plugins of a Strapi application.
管理员面板的自定义通过调整 `src/admin/app` 文件或 `src/admin` 文件夹中包含的其他文件的代码来完成(参见 [项目结构](/cms/project-structure))。通过这样做,你可以:
🌐 Admin panel customization is done by tweaking the code of the `src/admin/app` file or other files included in the `src/admin` folder (see [project structure](/cms/project-structure)). By doing so, you can:
- 自定义管理面板的某些部分,以更好地体现你的品牌标识(徽标、网站图标)或语言。
- 替换管理面板的其他部分,例如富文本编辑器和打包器。
- 扩展主题或管理面板以添加新功能或自定义现有用户界面。
:::strapi Plugins and Admin Panel API
除了本节中详细说明的支持自定义功能外,你还可以更进一步,创建可以使用 [管理员面板 API](/cms/plugins-development/admin-panel-api) 的插件。
🌐 In addition to supported customizations detailed in this section, you can go further and create plugins that tap into the [Admin Panel API](/cms/plugins-development/admin-panel-api).
:::
## 一般考虑 {#general-considerations}
🌐 General considerations
:::prerequisites
在更新代码以自定义管理面板之前:
🌐 Before updating code to customize the admin panel:
- 将默认的 `app.example.tsx|js` 文件重命名为 `app.ts|js`。
- 在 `/src/admin/` 中创建一个新的 `extensions` 文件夹。
- 如果你想在开发时实时看到你的更改生效,请确保管理员面板服务器正在运行(通常如果你没有更改管理员面板的默认[主机、端口和路径](/cms/configurations/admin-panel#admin-panel-server),可以使用 `yarn develop` 或 `npm run develop` 命令来启动)。
:::
大多数基本的管理面板自定义将在 `/src/admin/app` 文件中完成,该文件包含一个 `config` 对象。
🌐 Most basic admin panel customizations will be done in the `/src/admin/app` file, which includes a `config` object.
任何 `config` 对象使用的文件(例如,自定义徽标)都应放置在 `/src/admin/extensions/` 文件夹中,并在 `/src/admin/app.js` 中导入。
🌐 Any file used by the `config` object (e.g., a custom logo) should be placed in a `/src/admin/extensions/` folder and imported inside `/src/admin/app.js`.
这将替换位于 `./build` 的文件夹内容。访问
## 基本示例 {#basic-example}
🌐 Basic example
以下是管理面板基本自定义的示例:
🌐 The following is an example of a basic customization of the admin panel:
:::strapi Detailed examples in the codebase
* 你可以查看完整的翻译键,例如要更改欢迎消息,请访问 [GitHub](https://github.com/strapi/strapi/blob/develop/packages/core/admin/admin/src/translations)。
* 明暗颜色也可以在 [GitHub](https://github.com/strapi/design-system/tree/main/packages/design-system/src/themes) 上找到。
:::
# 管理面板打包器
Source: https://docs.strapi.io/cms/admin-panel-customization/bundlers
# 管理面板打包器 {#admin-panel-bundlers}
🌐 Admin panel bundlers
Strapi 的 [管理面板](/cms/admin-panel-customization) 是一个基于 React 的单页应用,封装了 Strapi 应用的所有功能和已安装的插件。你的 Strapi 5 应用可以使用两种不同的打包工具,[Vite](#vite)(默认工具)和 [webpack](#webpack)。这两种打包工具都可以根据你的需求进行配置。
🌐 Strapi's [admin panel](/cms/admin-panel-customization) is a React-based single-page application that encapsulates all the features and installed plugins of a Strapi application. 2 different bundlers can be used with your Strapi 5 application, [Vite](#vite) (the default one) and [webpack](#webpack). Both bundlers can be configured to suit your needs.
:::info
为了简化,以下文档提到 `strapi develop` 命令,但实际上你可能会根据所选择的软件包管理器运行 `yarn develop` 或 `npm run develop` 来使用它的别名。
🌐 For simplification, the following documentation mentions the `strapi develop` command, but in practice you will probably use its alias by running either `yarn develop` or `npm run develop` depending on your package manager of choice.
:::
## 快 {#vite}
🌐 Vite
在 Strapi 5 中,
## Webpack
在 Strapi 5 中,默认的打包工具是 Vite。要使用
# 管理面板扩展
Source: https://docs.strapi.io/cms/admin-panel-customization/extension
# 管理面板扩展 {#admin-panel-extension}
🌐 Admin panel extension
Strapi的[管理面板](/cms/admin-panel-customization)是一个基于React的单页应用,封装了Strapi应用的所有功能和已安装的插件。如果Strapi提供的[自定义选项](/cms/admin-panel-customization#available-customizations)不足以满足你的使用需求,你将需要扩展Strapi的管理面板。
🌐 Strapi's [admin panel](/cms/admin-panel-customization) is a React-based single-page application that encapsulates all the features and installed plugins of a Strapi application. If the [customization options](/cms/admin-panel-customization#available-customizations) provided by Strapi are not enough for your use case, you will need to extend Strapi's admin panel.
扩展 Strapi 的管理面板意味着利用其 React 基础根据项目的特定需求调整和增强界面和功能,这可能意味着创建新组件或添加新类型的字段。
🌐 Extending Strapi's admin panel means leveraging its React foundation to adapt and enhance the interface and features according to the specific needs of your project, which might imply creating new components or adding new types of fields.
在 2 个用例中,你可能需要扩展管理面板:
🌐 There are 2 use cases where you might want to extend the admin panel:
| 方法 | 范围 | 入口点 | 文档 ||---|---|---|---|| 本地扩展 | 一个 Strapi 项目 | `/src/admin/app.(js\|ts)` 和 `/src/admin/extensions/` | [管理面板自定义](/cms/admin-panel-customization) || 插件扩展 | 安装了你的插件的任何项目 | `[plugin-name]/admin/src/index.(js\|ts)` | [管理面板 API 概览](/cms/plugins-development/admin-panel-api) |
- 作为 Strapi 插件开发者,你希望开发一个 Strapi 插件,使其在**每次安装到任何 Strapi 应用时**都能扩展管理面板。👉 这可以通过利用 [插件的管理面板 API](/cms/plugins-development/admin-panel-api) 来实现,该 API 允许你添加导航链接和设置部分,将 React 组件注入到预定义区域,使用 Redux 管理状态,扩展内容管理器的编辑和列表视图,等等。
- 作为一名 Strapi 开发者,你希望为一个只需要扩展 Strapi 应用特定实例的 Strapi 用户开发一个独特的解决方案。👉 这可以通过直接更新 `/src/admin/app` 文件来完成,该文件可以导入位于 `/src/admin/extensions` 中的任何文件。
## 何时考虑使用插件 {#when-to-consider-a-plugin-instead}
🌐 When to consider a plugin instead
从在 `/src/admin/app` 中进行直接自定义开始,是满足项目特定需求的正确默认方式。当出现以下一种或多种信号时,考虑转向基于插件的方法:
🌐 Starting with a direct customization in `/src/admin/app` is the right default for project-specific needs. Consider moving to a plugin-based approach when one or more of these signals appear:
- 你正在将相同的管理员自定义重复应用到多个 Strapi 项目中。
- 你想要对扩展进行版本控制和分发——无论是内部还是通过 。
- 你需要更强大的自动化测试,独立于单个项目代码库。
- 多个团队需要对同一个扩展进行共享所有权和版本管理。
有关插件开发的完整介绍,请参见 [开发 Strapi 插件](/cms/plugins-development/developing-plugins)。
🌐 For a full introduction to plugin development, see [Developing Strapi plugins](/cms/plugins-development/developing-plugins).
:::strapi Additional resources
* 如果你正在寻找替换默认富文本编辑器的方法,请参阅[相应页面](/cms/admin-panel-customization/wysiwyg-editor)。
* 要了解插件如何与 Strapi 管理面板集成,请从 [管理面板 API 概述](/cms/plugins-development/admin-panel-api) 开始。
:::
# 网站图标
Source: https://docs.strapi.io/cms/admin-panel-customization/favicon
# 网站图标 {#favicon}
🌐 Favicon
Strapi 的 [管理面板](/cms/admin-panel-customization) 会在多个地方显示其品牌标识,包括 [徽标](/cms/admin-panel-customization/logos) 和网站图标。替换这些图片可以让你将界面和应用与你的身份相匹配。
🌐 Strapi's [admin panel](/cms/admin-panel-customization) displays its branding on various places, including the [logo](/cms/admin-panel-customization/logos) and the favicon. Replacing these images allows you to match the interface and application to your identity.
更换网站图标有两种方法:
🌐 There are 2 approaches to replacing the favicon:
* 替换 Strapi 项目根目录下的 `favicon.png` 文件
* 用以下代码编辑 [`strapi::favicon` 中间件配置](/cms/configurations/middlewares#favicon):
```js title="/config/middlewares.js"
// …
{
name: 'strapi::favicon',
config: {
path: 'my-custom-favicon.png',
},
},
// …
```
完成后,通过在终端运行 `yarn build && yarn develop` 来重建、启动并重新访问你的 Strapi 应用。
🌐 Once done, rebuild, launch and revisit your Strapi app by running `yarn build && yarn develop` in the terminal.
:::caution
确保清除缓存的收藏夹图标。它可能缓存于你的网页浏览器中,也可能缓存于像 Cloudflare 的 CDN 这样的域名管理工具中。
🌐 Make sure that the cached favicon is cleared. It can be cached in your web browser and also with your domain management tool like Cloudflare's CDN.
:::
# 首页自定义
Source: https://docs.strapi.io/cms/admin-panel-customization/homepage
# 首页自定义
Strapi 管理面板的
:::note The API requires Strapi 5.13+
`app.widgets.register` API 仅适用于 Strapi 5.13 及以上版本。尝试在较旧版本的 Strapi 中调用该 API 会导致管理面板崩溃。
希望注册小部件的插件开发者应当选择以下一种方式:
🌐 The `app.widgets.register` API only works with Strapi 5.13 and above. Trying to call the API with older versions of Strapi will crash the admin panel.
Plugin developers who want to register widgets should either:
- 在他们的插件 `package.json` 中将 `^5.13.0` 设置为其 `@strapi/strapi` 的 peerDependency。这个 peerDependency 支撑了市场的兼容性检查。
- 或者,在调用 API 之前检查它是否存在:
```js
if ('widgets' in app) {
// proceed with the registration
}
```
如果插件的全部目的是注册小部件,建议使用 peerDependency 方法。如果插件想添加小部件,但其大部分功能在其他地方,第二种方法更合理。
🌐 The peerDependency approach is recommended if the whole purpose of the plugin is to register widgets. The second approach makes more sense if a plugin wants to add a widget but most of its functionality is elsewhere.
:::
#### 组件 API 参考 {#widget-api-reference}
🌐 Widget API reference
`app.widgets.register()` 方法可以接受单个小部件配置对象或一个配置对象数组。每个小部件配置对象可以接受以下属性:
🌐 The `app.widgets.register()` method can take either a single widget configuration object or an array of configuration objects. Each widget configuration object can accept the following properties:
| 属性 | 类型 | 描述 | 是否必填 ||-------------|------------------------|-------------------------------------------------------|----------|| `icon` | `React.ComponentType` | 显示在小部件标题旁的图标组件 | 是 || `title` | `MessageDescriptor` | 支持翻译的小部件标题 | 是 || `component` | `() => Promise
:::tip
为了简单起见,下面的示例在 useEffect 钩子内部直接使用数据获取。虽然这在演示中可行,但它可能不反映生产中的最佳实践。
🌐 For simplicity, the example below uses data fetching directly inside a useEffect hook. While this works for demonstration purposes, it may not reflect best practices in production.
对于更稳健的解决方案,请考虑在[React 文档](https://react.nodejs.cn/learn/build-a-react-app-from-scratch#data-fetching)中推荐的替代方法。如果你希望集成数据获取库,我们建议使用[TanStackQuery](https://tanstack.com/query/v3/)。
🌐 For more robust solutions, consider alternative approaches recommended in the [React documentation](https://react.nodejs.cn/learn/build-a-react-app-from-scratch#data-fetching). If you're looking to integrate a data fetching library, we recommend using [TanStackQuery](https://tanstack.com/query/v3/).
:::
**数据管理**:

上方的绿色框表示用户的 React 组件(来自 [API](#widget-api-reference) 中的 `widget.component`)被渲染的区域。你可以在这个框内渲染你想要的任何内容。然而,框外的所有内容都是由 Strapi 渲染的。这确保了管理员面板内整体设计的一致性。API 提供的 `icon`、`title` 和(可选的)`link` 属性用于显示小部件。
🌐 The green box above represents the area where the user’s React component (from `widget.component` in the [API](#widget-api-reference)) is rendered. You can render whatever you like inside of this box. Everything outside that box is, however, rendered by Strapi. This ensures overall design consistency within the admin panel. The `icon`, `title`, and `link` (optional) properties provided in the API are used to display the widget.
#### 小部件辅助组件参考 {#widget-helper-components-reference}
🌐 Widget helper components reference
Strapi 提供了几个辅助组件,以便在各个小部件之间保持一致的用户体验:
🌐 Strapi provides several helper components to maintain a consistent user experience across widgets:
| 组件 | 描述 | 用法 ||------------------|-----------------------------------------------------|--------------------------------------|| `Widget.Loading` | 显示加载旋转器和消息 | 当数据正在加载时 || `Widget.Error` | 显示错误状态 | 当发生错误时 || `Widget.NoData` | 当没有可用数据时显示 | 当小部件没有数据可显示时 || `Widget.NoPermissions` | 当用户缺少所需权限时显示 | 当用户无法访问该小部件时 |
这些组件有助于在不同的部件中保持一致的外观和感觉。
你可以在没有子组件的情况下渲染这些组件以获得默认文案:`
))}
);
};
```
以下文件定义了一个自定义控制器,用于统计所有内容类型:
🌐 The following file defines a custom controller that counts all content-types:
```js title="src/plugins/content-metrics/server/src/controllers/metrics.js"
'use strict';
module.exports = ({ strapi }) => ({
async getContentCounts(ctx) {
try {
// Get all content types
const contentTypes = Object.keys(strapi.contentTypes)
.filter(uid => uid.startsWith('api::'))
.reduce((acc, uid) => {
const contentType = strapi.contentTypes[uid];
acc[contentType.info.displayName || uid] = 0;
return acc;
}, {});
// Count entities for each content type
for (const [name, _] of Object.entries(contentTypes)) {
const uid = Object.keys(strapi.contentTypes)
.find(key =>
strapi.contentTypes[key].info.displayName === name || key === name
);
if (uid) {
// Using the count() method from the Document Service API
const count = await strapi.documents(uid).count();
contentTypes[name] = count;
}
}
ctx.body = contentTypes;
} catch (err) {
ctx.throw(500, err);
}
}
});
```
以下文件确保指标控制器可以通过自定义的 `/count` 路由访问:
🌐 The following file ensures that the metrics controller is reachable at a custom `/count` route:
```js title="src/plugins/content-metrics/server/src/routes/index.js"
'content-api': {
type: 'content-api',
routes: [
{
method: 'GET',
path: '/count',
handler: 'metrics.getContentCounts',
config: {
policies: [],
},
},
],
},
};
```
))}
);
};
```
以下文件定义了一个自定义控制器,用于统计所有内容类型:
🌐 The following file defines a custom controller that counts all content-types:
```js title="src/plugins/content-metrics/server/src/controllers/metrics.js"
'use strict';
module.exports = ({ strapi }) => ({
async getContentCounts(ctx) {
try {
// Get all content types
const contentTypes = Object.keys(strapi.contentTypes)
.filter(uid => uid.startsWith('api::'))
.reduce((acc, uid) => {
const contentType = strapi.contentTypes[uid];
acc[contentType.info.displayName || uid] = 0;
return acc;
}, {});
// Count entities for each content type using Document Service
for (const [name, _] of Object.entries(contentTypes)) {
const uid = Object.keys(strapi.contentTypes)
.find(key =>
strapi.contentTypes[key].info.displayName === name || key === name
);
if (uid) {
// Using the count() method from Document Service instead of strapi.db.query
const count = await strapi.documents(uid).count();
contentTypes[name] = count;
}
}
ctx.body = contentTypes;
} catch (err) {
ctx.throw(500, err);
}
}
});
```
以下文件确保指标控制器可以通过自定义的 `/count` 路由访问:
🌐 The following file ensures that the metrics controller is reachable at a custom `/count` route:
```js title="src/plugins/content-metrics/server/src/routes/index.js"
'content-api': {
type: 'content-api',
routes: [
{
method: 'GET',
path: '/count',
handler: 'metrics.getContentCounts',
config: {
policies: [],
},
},
],
},
};
```
# 本地化与翻译
Source: https://docs.strapi.io/cms/admin-panel-customization/locales-translations
# 本地化与翻译 {#locales--translations}
🌐 Locales & translations
Strapi [管理面板](/cms/admin-panel-customization) 默认提供英文字符串,并支持添加其他语言环境,以便你的编辑团队可以使用他们偏好的语言进行工作。语言环境决定界面中显示的语言,而翻译则提供在某个语言环境中每个键显示的文本。
🌐 The Strapi [admin panel](/cms/admin-panel-customization) ships with English strings and supports adding other locales so your editorial team can work in their preferred language. Locales determine which languages appear in the interface, while translations provide the text displayed for each key in a locale.
本指南面向从应用代码库自定义管理体验的项目维护者。所有示例都修改从 `/src/admin/app` 文件导出的配置,Strapi 在构建管理面板时会加载该配置。你将学习如何声明额外的语言环境,以及当语言环境缺少字符串时如何扩展 Strapi 或插件的翻译。
🌐 This guide targets project maintainers customizing the admin experience from the application codebase. All examples modify the configuration exported from `/src/admin/app` file, which Strapi loads when the admin panel builds. You'll learn how to declare additional locales and how to extend Strapi or plugin translations when a locale is missing strings.
## 定义区域设置 {#defining-locales}
🌐 Defining locales
要在管理面板中更新可用语言环境列表,请在 `src/admin/app` 文件中设置 `config.locales` 数组:
🌐 To update the list of available locales in the admin panel, set the `config.locales` array in `src/admin/app` file:
:::note Notes
- `en` 语言环境无法从构建中移除,因为它既是回退语言环境(即如果在某个语言环境中未找到翻译,将使用 `en`),也是默认语言环境(即当用户第一次打开管理面板时使用)。
- 可用区域设置的完整列表可在
插件的键/值对在插件的文件 `/admin/src/translations/[language-name].json` 中独立声明。这些键/值对可以通过在 `config.translations` 键中添加前缀(插件的名称,即 `[plugin name].[key]: 'value'`)来类似地扩展,如以下示例所示:
🌐 A plugin's key/value pairs are declared independently in the plugin's files at `/admin/src/translations/[language-name].json`. These key/value pairs can similarly be extended in the `config.translations` key by prefixing the key with the plugin's name (i.e. `[plugin name].[key]: 'value'`) as in the following example:
如果你需要发送额外的翻译 JSON 文件——例如为了组织大型覆盖或支持 Strapi 未打包的本地化——请将它们放在 `/src/admin/extensions/translations` 文件夹中,并确保本地化代码已列在 `config.locales` 中。
🌐 If you need to ship additional translation JSON files—for example to organize large overrides or to support a locale not bundled with Strapi—place them in the `/src/admin/extensions/translations` folder and ensure the locale code is listed in `config.locales`.
:::tip Rebuild the admin
当管理员重建时,翻译更改会生效。如果更新未显示,请重新运行开发服务器或重建管理员以刷新打包的翻译。
🌐 Translation changes apply when the admin rebuilds. If updates don’t show, re-run your dev server or rebuild the admin to refresh bundled translations.
:::
# 标志
Source: https://docs.strapi.io/cms/admin-panel-customization/logos
# 标志 {#logos}
🌐 Logos
Strapi 的 [管理面板](/cms/admin-panel-customization) 在登录屏幕和主导航中显示其品牌标识。更换这些图片可以让界面与你的身份保持一致。本页展示了如何通过管理面板配置覆盖这两个徽标文件。如果你更喜欢直接在 UI 中上传,请参见 [自定义徽标](/cms/features/admin-panel#customizing-the-logo)。
🌐 Strapi's [admin panel](/cms/admin-panel-customization) displays its branding on both the login screen and in the main navigation. Replacing these images allows you to match the interface to your identity. The present page shows how to override the two logo files via the admin panel configuration. If you prefer uploading them directly in the UI, see [Customizing the logo](/cms/features/admin-panel#customizing-the-logo).
Strapi 管理面板在 2 个不同位置显示徽标,由管理面板配置中的 2 个不同键表示:
🌐 The Strapi admin panel displays a logo in 2 different locations, represented by 2 different keys in the admin panel configuration:
| 在用户界面中的位置 | 要更新的配置键 || --- | --- || 在登录页面 | `config.auth.logo` || 在主导航中 | `config.menu.logo` |
:::note
通过管理面板上传的徽标将取代通过配置文件设置的任何徽标。
🌐 Logos uploaded via the admin panel supersede any logo set through the configuration files.
:::
### 管理面板中的标志位置 {#logos-location-in-the-admin-panel}
🌐 Logos location in the admin panel
`config.auth.logo` 处理的徽标只显示在登录屏幕上:
🌐 The logo handled by `config.auth.logo` logo is only shown on the login screen:

`config.menu.logo` 处理的徽标位于管理员面板左上角的主导航中:
🌐 The logo handled by `config.menu.logo` logo is located in the main navigation at the top left corner of the admin panel:

### 更新标志 {#updating-logos}
🌐 Updating logos
要更新徽标,请将图片文件放入 `/src/admin/extensions` 文件夹,在 `src/admin/app` 中导入这些文件,并按以下示例更新相应的键:
🌐 To update the logos, put image files in the `/src/admin/extensions` folder, import these files in `src/admin/app` and update the corresponding keys as in the following example:
:::note
通过配置文件设置的图片文件没有大小限制。
🌐 There is no size limit for image files set through the configuration files.
:::
# 主题扩展
Source: https://docs.strapi.io/cms/admin-panel-customization/theme-extension
# 主题扩展 {#theme-extension}
🌐 Theme extension
Strapi 的 [管理面板](/cms/admin-panel-customization) 可以显示为浅色或夜间模式(参见 [个人资料设置](/cms/getting-started/setting-up-admin-panel#setting-up-your-administrator-profile)),两者都可以通过自定义主题设置进行扩展。
🌐 Strapi's [admin panel](/cms/admin-panel-customization) can be displayed either in light or dark mode (see [profile setup](/cms/getting-started/setting-up-admin-panel#setting-up-your-administrator-profile)), and both can be extended through custom theme settings.
要扩展主题,请使用:
🌐 To extend the theme, use either:
- Light 模式的 `config.theme.light` 键
- `config.theme.dark` 键用于夜间模式
:::strapi Strapi Design System
默认的
# 自定义富文本编辑器
Source: https://docs.strapi.io/cms/admin-panel-customization/wysiwyg-editor
# 更改默认富文本编辑器 {#change-the-default-rich-text-editor}
🌐 Change the default rich text editor
Strapi 的 [管理面板](/cms/admin-panel-customization) 附带了一个内置的富文本编辑器。要更改默认编辑器,你有几种选择:
🌐 Strapi's [admin panel](/cms/admin-panel-customization) comes with a built-in rich text editor. To change the default editor, several options are at your disposal:
- 你可以通过访问 安装第三方插件,例如用于CKEditor的插件。
- 你可以创建自己的插件来创建和注册一个完全自定义的所见即所得字段(参见 [自定义字段文档](/cms/features/custom-fields))。
:::tip Next steps
评估编辑器时,建议先从 Marketplace 下载插件进行快速试用,如果需要更深入的集成(例如架构、验证或自定义工具栏行为),则可以考虑使用自定义字段。
🌐 When evaluating editors, start with a plugin from the Marketplace for a quick trial, then consider a custom field if you need deeper integration (schema, validation, or custom toolbar behavior).
:::
# Strapi 客户端
Source: https://docs.strapi.io/cms/api/client
# Strapi 客户端 {#strapi-client}
🌐 Strapi Client
Strapi 客户端库简化了与 Strapi 后端的交互,提供了一种获取、创建、更新和删除内容的方式。本指南将引导你完成 Strapi 客户端的设置、身份验证配置,以及有效使用其主要功能。
🌐 The Strapi Client library simplifies interactions with your Strapi back end, providing a way to fetch, create, update, and delete content. This guide walks you through setting up the Strapi Client, configuring authentication, and using its key features effectively.
## 入门 {#getting-started}
🌐 Getting Started
:::prerequisites
- Strapi 项目已创建并正在运行。如果你还没有设置,请按照[快速入门指南](/cms/quick-start)创建一个。
- 你知道你的 Strapi 实例的内容 API 的 URL(例如,`http://localhost:1337/api`)。
:::
### 安装 {#installation}
🌐 Installation
要在你的项目中使用 Strapi 客户端,请使用你首选的包管理器将其作为依赖安装:
🌐 To use the Strapi Client in your project, install it as a dependency using your preferred package manager:
### 基本配置 {#basic-configuration}
🌐 Basic configuration
要开始与 Strapi 后端交互,请初始化 Strapi 客户端并设置基本 API URL:
🌐 To start interacting with your Strapi back end, initialize the Strapi Client and set the base API URL:
`baseURL` 必须包含协议(`http` 或 `https`)。无效的 URL 将抛出错误 `StrapiInitializationError`。
🌐 The `baseURL` must include the protocol (`http` or `https`). An invalid URL will throw an error `StrapiInitializationError`.
### 身份验证 {#authentication}
🌐 Authentication
Strapi 客户端支持不同的身份验证策略来访问 Strapi 后端中受保护的资源。
🌐 The Strapi Client supports different authentication strategies to access protected resources in your Strapi back end.
如果你的 Strapi 实例使用 [API 令牌](/cms/features/api-tokens),请按如下方式配置 Strapi 客户端:
🌐 If your Strapi instance uses [API tokens](/cms/features/api-tokens), configure the Strapi Client as follows:
```js
const client = strapi({
baseURL: 'http://localhost:1337/api',
auth: 'your-api-token-here',
});
```
这允许你的请求自动包含必要的身份验证凭据。如果令牌无效或缺失,客户端在初始化时将抛出错误 `StrapiValidationError`。
🌐 This allows your requests to include the necessary authentication credentials automatically.
If the token is invalid or missing, the client will throw an error during initialization `StrapiValidationError`.
## API参考 {#api-reference}
🌐 API Reference
Strapi 客户端提供以下关键属性和方法用于与你的 Strapi 后端交互:
🌐 The Strapi Client provides the following key properties and methods for interacting with your Strapi back end:
| 参数 | 描述 || ---| --- || `baseURL` | 你的 Strapi 后端的基础 API URL。 || `fetch()` | 一个用于发起通用 API 请求的工具方法,类似于原生 fetch API。 || `collection()` | 管理集合类型资源(例如博客文章、产品)。 || `single()` | 管理单一类型资源(例如主页设置、全局配置)。 || `files()` | 直接向 Strapi 媒体库上传、检索和管理文件的功能。 |
### 通用抓取 {#general-purpose-fetch}
🌐 General purpose fetch
Strapi 客户端提供了对底层 JavaScript `fetch` 函数的访问,以便直接进行 API 请求。请求总是相对于客户端初始化时提供的基础 URL:
🌐 The Strapi Client provides access to the underlying JavaScript `fetch` function to make direct API requests. The request is always relative to the base URL provided during client initialization:
```js
const result = await client.fetch('articles', { method: 'GET' });
```
### 与集合类型一起工作 {#working-with-collection-types}
🌐 Working with collection types
Strapi 中的集合类型是具有多个条目的实体(例如,拥有多篇文章的博客)。Strapi 客户端提供了一个 `collection()` 方法来与这些资源进行交互,具有以下可用方法:
🌐 Collection types in Strapi are entities with multiple entries (e.g., a blog with many posts). The Strapi Client provides a `collection()` method to interact with these resources, with the following methods available:
| 参数 | 描述 || ---| --- || `find(queryParams?)` | 获取多个文档,可选择进行过滤、排序或分页。 || `findOne(documentID, queryParams?)` | 通过其唯一 ID 检索单个文档。 || `create(data, queryParams?)` | 在集合中创建一个新文档。 || `update(documentID, data, queryParams?)` | 更新现有文档。 || `delete(documentID, queryParams?)` | 更新现有文档。 |
**使用示例:**
### 处理单一类型 {#working-with-single-types}
🌐 Working with single types
Strapi 中的单一类型表示只存在一次的独特内容条目(例如首页设置或全站配置)。Strapi 客户端提供了 `single()` 方法来与这些资源进行交互,可用的方法如下:| 参数 | 描述 || ----------| -------------------------------------------------------------------------------------------- || `find(queryParams?)` | 获取文档。 || `update(documentID, data, queryParams?)` | 更新文档。 || `delete(queryParams?)` | 删除文档。 |
🌐 Single types in Strapi represent unique content entries that exist only once (e.g., the homepage settings or site-wide configurations). The Strapi Client provides a `single()` method to interact with these resources, with the following methods available:| Parameter | Description || ----------| -------------------------------------------------------------------------------------------- || `find(queryParams?)` | Fetch the document. || `update(documentID, data, queryParams?)` | Update the document. || `delete(queryParams?)` | Remove the document. |
**使用示例:**
```js
const homepage = client.single('homepage');
// Fetch the default homepage content
const defaultHomepage = await homepage.find();
// Fetch the Spanish version of the homepage
const spanishHomepage = await homepage.find({ locale: 'es' });
// Update the homepage draft content
const updatedHomepage = await homepage.update(
{ title: 'Updated Homepage Title' },
{ status: 'draft' }
);
// Delete the homepage content
await homepage.delete();
```
### 处理文件 {#working-with-files}
🌐 Working with files
Strapi 客户端通过 `files` 属性提供对 [媒体库](/cms/features/media-library) 的访问。这使你能够在不直接与 REST API 交互的情况下检索和管理文件元数据。
🌐 The Strapi Client provides access to the [Media Library](/cms/features/media-library) via the `files` property. This allows you to retrieve and manage file metadata without directly interacting with the REST API.
以下方法可用于处理文件。点击表格中的方法名称即可跳转到相应部分,查看更多详细信息和示例:
🌐 The following methods are available for working with files. Click on the method name in the table to jump to the corresponding section with more details and examples:
| 方法 | 描述 ||--------|-------------|| [`find(params?)`](#find) | 根据可选查询参数检索文件元数据列表 || [`findOne(fileId)`](#findone) | 根据文件 ID 检索单个文件的元数据 || [`update(fileId, fileInfo)`](#update) | 更新现有文件的元数据 || [`upload(file, options)`](#upload) | 上传文件(Blob 或 Buffer),可选提供用于元数据的 `options` 对象 || [`delete(fileId)`](#delete) | 根据文件 ID 删除文件 |
#### `find`
`strapi.client.files.find()` 方法根据可选查询参数检索文件元数据列表。
🌐 The `strapi.client.files.find()` method retrieves a list of file metadata based on optional query parameters.
该方法的使用方式如下:
🌐 The method can be used as follows:
```js
// Initialize the client
const client = strapi({
baseURL: 'http://localhost:1337/api',
auth: 'your-api-token',
});
// Find all file metadata
const allFiles = await client.files.find();
console.log(allFiles);
// Find file metadata with filtering and sorting
const imageFiles = await client.files.find({
filters: {
mime: { $contains: 'image' }, // Only get image files
name: { $contains: 'avatar' }, // Only get files with 'avatar' in the name
},
sort: ['name:asc'], // Sort by name in ascending order
});
```
#### `findOne` {#findone}
`strapi.client.files.findOne()` 方法通过其 ID 检索单个文件的元数据。
🌐 The `strapi.client.files.findOne()` method retrieves the metadata for a single file by its id.
该方法的使用方式如下:
🌐 The method can be used as follows:
```js
// Initialize the client
const client = strapi({
baseURL: 'http://localhost:1337/api',
auth: 'your-api-token',
});
// Find file metadata by ID
const file = await client.files.findOne(1);
console.log(file.name);
console.log(file.url);
console.log(file.mime); // The file MIME type
```
#### `update`
`strapi.client.files.update()` 方法更新现有文件的元数据,接受两个参数,`fileId`,以及包含选项的对象,例如媒体的名称、替代文本和标题。
🌐 The `strapi.client.files.update()` method updates metadata for an existing file, accepting 2 parameters, the `fileId`, and an object containing options such as the name, alternative text, and caption for the media.
这些方法的使用方式如下:
🌐 The methods can be used as follows:
```js
// Initialize the client
const client = strapi({
baseURL: 'http://localhost:1337/api',
auth: 'your-api-token',
});
// Update file metadata
const updatedFile = await client.files.update(1, {
name: 'New file name',
alternativeText: 'Descriptive alt text for accessibility',
caption: 'A caption for the file',
});
```
#### `upload`
##### 响应结构 {#response-structure}
🌐 Response Structure
`strapi.client.files.upload()` 方法返回一个文件对象数组,每个对象都有如下字段:
🌐 The `strapi.client.files.upload()` method returns an array of file objects, each with fields such as:
```json
{
"id": 1,
"name": "image.png",
"alternativeText": "Uploaded from Node.js Buffer",
"caption": "Example upload",
"mime": "image/png",
"url": "/uploads/image.png",
"size": 12345,
"createdAt": "2025-07-23T12:34:56.789Z",
"updatedAt": "2025-07-23T12:34:56.789Z"
}
```
:::note Additional response fields
上传响应包括上述显示内容之外的其他字段。有关所有可用字段,请参阅 中的完整 FileResponse 接口。
:::
#### `delete`
`strapi.client.files.delete()` 方法通过其 ID 删除文件。
🌐 The `strapi.client.files.delete()` method deletes a file by its ID.
该方法的使用方式如下:
🌐 The method can be used as follows:
```js
// Initialize the client
const client = strapi({
baseURL: 'http://localhost:1337/api',
auth: 'your-api-token',
});
// Delete a file by ID
const deletedFile = await client.files.delete(1);
console.log('File deleted successfully');
console.log('Deleted file ID:', deletedFile.id);
console.log('Deleted file name:', deletedFile.name);
```
## 处理常见错误 {#handling-common-errors}
🌐 Handling Common Errors
通过 Strapi 客户端发送查询时可能会出现以下错误:
🌐 The following errors might occur when sending queries through the Strapi Client:
| 错误 | 描述 ||-------|-------------|| 权限错误 | 如果经过身份验证的用户没有上传或管理文件的权限,将抛出 `FileForbiddenError`。 || HTTP 错误 | 如果服务器无法访问、身份验证失败或存在网络问题,将抛出 `HTTPError`。 || 缺少参数 | 当上传 `Buffer` 时,必须在选项对象中提供 `filename` 和 `mimetype`。如果缺少任何一个,将抛出错误。 |
:::strapi Additional information
有关 Strapi 客户端的更多详细信息可以在 中找到。
:::
# 内容 API
Source: https://docs.strapi.io/cms/api/content-api
# Strapi API 访问你的内容 {#strapi-apis-to-access-your-content}
🌐 Strapi APIs to access your content
一旦你创建并配置了一个 Strapi 项目,使用 [内容类型构建器](/cms/features/content-type-builder) 创建了内容结构,并通过 [内容管理器](/cms/features/content-manager) 开始添加数据,你可能希望访问你的内容。
🌐 Once you've created and configured a Strapi project, created a content structure with the [Content-Type Builder](/cms/features/content-type-builder) and started adding data through the [Content Manager](/cms/features/content-manager), you likely would like to access your content.
从前端应用,你的内容可以通过 Strapi 的 Content API 访问,该 API 公开:
🌐 From a front-end application, your content can be accessed through Strapi's Content API, which is exposed:
- 默认通过 [REST API](/cms/api/rest)
- 如果你安装了 Strapi 内置的 [GraphQL 插件](/cms/plugins/graphql),也可以通过 [GraphQL API](/cms/api/graphql) 访问。
你也可以使用 [Strapi Client](/cms/api/client) 库与 REST API 进行交互。
🌐 You can also use the [Strapi Client](/cms/api/client) library to interact with the REST API.
REST 和 GraphQL API 代表了面向外部应用暴露的内容 API 的顶层。Strapi 还提供了两个较低层次的 API:
🌐 REST and GraphQL APIs represent the top-level layers of the Content API exposed to external applications. Strapi also provides 2 lower-level APIs:
- [文档服务 API](/cms/api/document-service),可通过 `strapi.documents` 访问,是在 [后端服务器](/cms/customization) 内或通过 [插件](/cms/plugins-development/developing-plugins) 与你的应用数据库交互的推荐 API。文档服务是处理 **文档**
# 文件
Source: https://docs.strapi.io/cms/api/document
# 文件 {#documents}
🌐 Documents
在 Strapi 5 中,**文档**是一个仅限 API 的概念。文档代表了给定内容类型条目所有不同的内容变体。
🌐 A **document** in Strapi 5 is an API-only concept. A document represents all the different variations of content for a given entry of a content-type.
单一类型包含一个唯一文档,而集合类型可以包含多个文档。
🌐 A single type contains a unique document, and a collection type can contain several documents.
当你使用管理员面板时,从未提到文档的概念,并且对终端用户并不必要。用户在[内容管理器](/cms/features/content-manager)中创建和编辑**条目**。例如,作为用户,你要么列出给定语言环境下的条目,要么编辑给定语言环境中特定条目的草稿版本。
🌐 When you use the admin panel, the concept of a document is never mentioned and not necessary for the end user. Users create and edit **entries** in the [Content Manager](/cms/features/content-manager). For instance, as a user, you either list the entries for a given locale, or edit the draft version of a specific entry in a given locale.
但是,在 API 级别,条目字段的值实际上可以具有:
🌐 However, at the API level, the value of the fields of an entry can actually have:
- 英语和法语语言环境的内容不同,
- 甚至在每个语言环境中为草稿和已发布版本设置不同的内容。
包含所有语言环境的所有草稿和已发布版本内容的存储桶是一个文档。
🌐 The bucket that includes the content of all the draft and published versions for all the locales is a document.
使用 [文档服务 API](/cms/api/document-service) 操作文档将帮助你创建、检索、更新和删除文档或其中包含的特定数据子集。
🌐 Manipulating documents with the [Document Service API](/cms/api/document-service) will help you create, retrieve, update, and delete documents or a specific subset of the data they contain.
下列图表显示了内容的所有可能变体,这取决于内容类型启用了哪些功能,例如[国际化 (i18n)](/cms/features/internationalization)和[草稿与发布](/cms/features/draft-and-publish):
🌐 The following diagrams represent all the possible variations of content depending on which features, such as [Internationalization (i18n)](/cms/features/internationalization) and [Draft & Publish](/cms/features/draft-and-publish), are enabled for a content-type:
- 如果内容类型启用了国际化 (i18n) 功能,则一个文档可以拥有多个**文档语言环境**。
- 如果在内容类型上启用了“草稿与发布”功能,文档可以同时拥有**已发布**版本和**草稿**版本。
:::strapi APIs to query documents data
要与文档或它们所代表的数据进行交互:
🌐 To interact with documents or the data they represent:
- 从后端服务器(例如,从控制器、服务以及插件的后端部分)使用 [文档服务 API](/cms/api/document-service)。
- 从应用的前端部分,使用 [REST API](/cms/api/rest) 或 [GraphQL API](/cms/api/graphql) 查询你的数据。
有关 API 的更多信息,请参阅 [内容 API 介绍](/cms/api/content-api)。
🌐 For additional information about the APIs, please refer to the [Content API introduction](/cms/api/content-api).
:::
:::info Default version in returned results
后端和前端 API 之间的一个重要区别是关于未传递参数时返回的默认版本:
🌐 An important difference between the back-end and front-end APIs is about the default version returned when no parameter is passed:
- 文档服务 API 默认返回草稿版本,
- 而 REST 和 GraphQL API 默认返回已发布的版本。
:::
# 文档服务 API
Source: https://docs.strapi.io/cms/api/document-service
# 文档服务 API {#document-service-api}
🌐 Document Service API
文档服务 API 建立在 **查询引擎 API** 之上 并用于对 **文档** 执行 CRUD([创建](#create)、[检索](#findone)、[更新](#update) 和 [删除](#delete))操作
:::strapi Entity Service API is deprecated in Strapi 5
文档服务 API 取代了 Strapi v4 (
`findOne()` 方法在找到时返回匹配的文档,否则返回 `null`。
🌐 The `findOne()` method returns the matching document if found, otherwise returns `null`.
### `findFirst()`
查找与参数匹配的第一个文档。
🌐 Find the first document matching the parameters.
语法:`findFirst(parameters: Params) => Document`
🌐 Syntax: `findFirst(parameters: Params) => Document`
#### 参数 {#parameters-1}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 |
|-----------|-------------|---------|------|
| [`locale`](/cms/api/document-service/locale#find-first) | 要查找的文档的语言环境。 | 默认语言环境 | 字符串或 `undefined` |
| [`status`](/cms/api/document-service/status#find-first) | _如果内容类型启用了 [Draft & Publish](/cms/features/draft-and-publish)_: 发布状态,可以是:
`'published'` 仅查找已发布文档
`'draft'` 仅查找草稿文档
| `'draft'` | `'published'` 或 `'draft'` |
| [`filters`](/cms/api/document-service/filters) | 使用的[筛选器](/cms/api/document-service/filters) | `null` | 对象 |
| [`fields`](/cms/api/document-service/fields#findfirst) | [选择返回的字段](/cms/api/document-service/fields#findfirst) | 所有字段 (除默认未填充的字段外) | 对象 |
| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) 用额外的字段填充结果。 | `null` | 对象 |
#### 例子 {#examples}
🌐 Examples
##### 通用示例 {#generic-example}
🌐 Generic example
默认情况下,`findFirst()` 会返回传入唯一标识符(集合类型 ID 或单类型 ID)的第一个文档的草稿版本,使用默认语言环境:
🌐 By default, `findFirst()` returns the draft version, in the default locale, of the first document for the passed unique identifier (collection type id or single type id):
##### 查找符合参数的第一个文档 {#find-the-first-document-matching-parameters}
🌐 Find the first document matching parameters
向 `findFirst()` 传递一些参数以返回与之匹配的第一个文档。
🌐 Pass some parameters to `findFirst()` to return the first document matching them.
如果未传入 `locale` 或 `status` 参数,结果将返回默认语言环境的草稿版本:
🌐 If no `locale` or `status` parameters are passed, results return the draft version for the default locale:
### `findMany()`
查找与参数匹配的文档。
🌐 Find documents matching the parameters.
语法:`findMany(parameters: Params) => Document[]`
🌐 Syntax: `findMany(parameters: Params) => Document[]`
#### 参数 {#parameters-2}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 |
|-----------|-------------|---------|------|
| [`locale`](/cms/api/document-service/locale#find-many) | 要查找的文档的区域设置。 | 默认区域设置 | 字符串或 `undefined` |
| [`status`](/cms/api/document-service/status#find-many) | _如果内容类型启用了 [Draft & Publish](/cms/features/draft-and-publish)_: 发布状态,可以是:
`'published'` 仅查找已发布文档
`'draft'` 仅查找草稿文档
| `'draft'` | `'published'` 或 `'draft'` |
| [`filters`](/cms/api/document-service/filters) | 使用的[筛选器](/cms/api/document-service/filters) | `null` | 对象 |
| [`fields`](/cms/api/document-service/fields#findmany) | [选择返回的字段](/cms/api/document-service/fields#findmany) | 所有字段 (除默认未填充的字段外) | 对象 |
| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) 用额外的字段填充结果。 | `null` | 对象 |
| [`pagination`](/cms/api/document-service/sort-pagination#pagination) | [分页](/cms/api/document-service/sort-pagination#pagination) 结果 |
| [`sort`](/cms/api/document-service/sort-pagination#sort) | [排序](/cms/api/document-service/sort-pagination#sort) 结果 | | |
#### 例子 {#examples-1}
🌐 Examples
##### 通用示例 {#generic-example-1}
🌐 Generic example
当没有传入参数时,`findMany()` 会返回每个文档在默认语言环境下的草稿版本:
🌐 When no parameter is passed, `findMany()` returns the draft version in the default locale for each document:
##### 查找符合参数的文档 {#find-documents-matching-parameters}
🌐 Find documents matching parameters
可用的过滤器详细信息请参见文档服务 API 参考中的 [filters](/cms/api/document-service/filters) 页面。
🌐 Available filters are detailed in the [filters](/cms/api/document-service/filters) page of the Document Service API reference.
如果未传入 `locale` 或 `status` 参数,结果将返回默认语言环境的草稿版本:
🌐 If no `locale` or `status` parameters are passed, results return the draft version for the default locale:
### `create()`
创建草稿文档并返回它。
🌐 Creates a drafted document and returns it.
传递字段以在 `data` 对象中创建内容。
🌐 Pass fields for the content to create in a `data` object.
语法:`create(parameters: Params) => Document`
🌐 Syntax: `create(parameters: Params) => Document`
#### 参数 {#parameters-3}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 ||-----------|-------------|---------|------|| [`locale`](/cms/api/document-service/locale#create) | 要创建的文档的语言环境。 | 默认语言环境 | 字符串或 `undefined` || [`fields`](/cms/api/document-service/fields#create) | 要返回的 [选择字段](/cms/api/document-service/fields#create) | 所有字段 (默认未填充的字段除外) | 对象 || [`status`](/cms/api/document-service/status#create) | _如果内容类型启用了 [草稿与发布](/cms/features/draft-and-publish)_: 可以设置为 `'published'`,以在创建文档时自动发布草稿版本 | - | `'published'` || [`populate`](/cms/api/document-service/populate) | 使用附加字段 [填充](/cms/api/document-service/populate) 结果。 | `null` | 对象 |
#### 例子 {#example-1}
🌐 Example
如果没有传入 `locale` 参数,`create()` 会为默认语言创建文档的草稿版本:
🌐 If no `locale` parameter is passed, `create()` creates the draft version of the document for the default locale:
:::tip
如果在内容类型上启用了[草稿与发布](/cms/features/draft-and-publish)功能,你可以在创建文档的同时自动发布它(参见[`status` 文档`](/cms/api/document-service/status#create))。
🌐 If the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled on the content-type, you can automatically publish a document while creating it (see [`status` documentation](/cms/api/document-service/status#create)).
:::
### `update()`
更新文档版本并返回它们。
🌐 Updates document versions and returns them.
语法:`update(parameters: Params) => Promise
### `delete()`
删除一个文档或其特定语言环境。
🌐 Deletes one document, or a specific locale of it.
语法:`delete(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
🌐 Syntax: `delete(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
#### 参数 {#parameters-5}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 ||-----------|-------------|---------|------|| `documentId` | 文档 ID | | `ID` || [`locale`](/cms/api/document-service/locale#delete) | 要删除的文档的本地化版本。 | `null` (仅删除默认语言) | 字符串, `'*'`, 或 `null` || [`filters`](/cms/api/document-service/filters) | 要使用的[筛选器](/cms/api/document-service/filters) | `null` | 对象 || [`fields`](/cms/api/document-service/fields#delete) | 要返回的[选择字段](/cms/api/document-service/fields#delete) | 所有字段 (默认未填充的除外) | 对象 || [`populate`](/cms/api/document-service/populate) | 使用附加字段[填充](/cms/api/document-service/populate)结果。 | `null` | 对象 |
#### 例子 {#example-3}
🌐 Example
如果没有传递 `locale` 参数,`delete()` 只会删除文档的默认语言版本。这会删除草稿和已发布的版本:
🌐 If no `locale` parameter is passed, `delete()` only deletes the default locale version of a document. This deletes both the draft and published versions:
### `publish()`
已发布的版本是只读的,因此你无法从技术上更新文档的已发布版本。
🌐 Publishes one or multiple locales of a document.
只有在内容类型上启用了[草稿与发布](/cms/features/draft-and-publish)时,此方法才可用。
🌐 This method is only available if [Draft & Publish](/cms/features/draft-and-publish) is enabled on the content-type.
语法:`publish(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
🌐 Syntax: `publish(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
#### 参数 {#parameters-6}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 ||-----------|-------------|---------|------|| `documentId` | 文档 ID | | `ID` || [`locale`](/cms/api/document-service/locale#publish) | 要发布的文档的语言环境 | 仅默认语言环境 | 字符串, `'*'`, 或 `null` || [`filters`](/cms/api/document-service/filters) | 使用的 [过滤器](/cms/api/document-service/filters) | `null` | 对象 || [`fields`](/cms/api/document-service/fields#publish) | 返回的 [选择字段](/cms/api/document-service/fields#publish) | 所有字段 (默认未填充的字段除外) | 对象 || [`populate`](/cms/api/document-service/populate) | 使用额外字段 [填充](/cms/api/document-service/populate) 结果 | `null` | 对象 |
#### 例子 {#example-4}
🌐 Example
如果没有传递 `locale` 参数,`publish()` 只会发布文档的默认语言版本:
🌐 If no `locale` parameter is passed, `publish()` only publishes the default locale version of the document:
### `unpublish()`
取消发布文档的一个或所有语言环境版本,并返回未发布的语言环境版本数。
🌐 Unpublishes one or all locale versions of a document, and returns how many locale versions were unpublished.
只有在内容类型上启用了[草稿与发布](/cms/features/draft-and-publish)时,此方法才可用。
🌐 This method is only available if [Draft & Publish](/cms/features/draft-and-publish) is enabled on the content-type.
语法:`unpublish(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
🌐 Syntax: `unpublish(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
#### 参数 {#parameters-7}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 ||-----------|-------------|---------|------|| `documentId` | 文档 ID | | `ID` || [`locale`](/cms/api/document-service/locale#unpublish) | 要取消发布的文档的语言环境。 | 仅默认语言环境 | 字符串, `'*'` 或 `null` || [`filters`](/cms/api/document-service/filters) | 使用的 [过滤器](/cms/api/document-service/filters) | `null` | 对象 || [`fields`](/cms/api/document-service/fields#unpublish) | 要返回的 [选择字段](/cms/api/document-service/fields#unpublish) | 所有字段 (默认未填充的字段除外) | 对象 || [`populate`](/cms/api/document-service/populate) | 用额外字段 [填充](/cms/api/document-service/populate) 结果。 | `null` | 对象 |
#### 例子 {#example-5}
🌐 Example
如果没有传入 `locale` 参数,`unpublish()` 只会取消发布文档的默认语言版本:
🌐 If no `locale` parameter is passed, `unpublish()` only unpublishes the default locale version of the document:
### `discardDraft()`
丢弃草稿数据并用已发布的版本覆盖它。
🌐 Discards draft data and overrides it with the published version.
只有在内容类型上启用了[草稿与发布](/cms/features/draft-and-publish)时,此方法才可用。
🌐 This method is only available if [Draft & Publish](/cms/features/draft-and-publish) is enabled on the content-type.
语法:`discardDraft(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
🌐 Syntax: `discardDraft(parameters: Params): Promise<{ documentId: ID, entries: Number }>`
#### 参数 {#parameters-8}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 ||-----------|-------------|---------|------|| `documentId` | 文档ID | | `ID` || [`locale`](/cms/api/document-service/locale#discard-draft) | 要丢弃的文档的语言环境 | 仅默认语言 | 字符串,`'*'` 或 `null` || [`filters`](/cms/api/document-service/filters) | 使用的 [过滤器](/cms/api/document-service/filters) | `null` | 对象 || [`fields`](/cms/api/document-service/fields#discarddraft) | 要返回的 [选择字段](/cms/api/document-service/fields#discarddraft) | 所有字段 (默认未填充的字段除外) | 对象 || [`populate`](/cms/api/document-service/populate) | 使用附加字段 [填充](/cms/api/document-service/populate) 结果 | `null` | 对象 |
#### 例子 {#example-6}
🌐 Example
如果没有传递 `locale` 参数,`discardDraft()` 将丢弃草稿数据,并仅使用默认语言版本的已发布内容进行覆盖:
🌐 If no `locale` parameter is passed, `discardDraft()` discards draft data and overrides it with the published version only for the default locale:
### `count()`
计算与提供的参数匹配的文档数量。
🌐 Count the number of documents that match the provided parameters.
语法:`count(parameters: Params) => number`
🌐 Syntax: `count(parameters: Params) => number`
#### 参数 {#parameters-9}
🌐 Parameters
| 参数 | 描述 | 默认值 | 类型 ||-----------|-------------|---------|------|| [`locale`](/cms/api/document-service/locale#count) | 要计数的文档的区域设置 | 默认区域设置 | 字符串 或 `null` || [`status`](/cms/api/document-service/status#count) | _如果内容类型启用了 [草稿与发布](/cms/features/draft-and-publish)_: 发布状态,可为:
`'published'` 仅查找已发布文档
`'draft'` 查找草稿文档(将返回所有文档)
| `'draft'` | `'published'` 或 `'draft'` || [`filters`](/cms/api/document-service/filters) | 要使用的 [过滤器](/cms/api/document-service/filters) | `null` | 对象 |
:::note
由于已发布的文档必然也有草稿副本,因此已发布的文档仍算作具有草稿版本。
🌐 Since published documents necessarily also have a draft counterpart, a published document is still counted as having a draft version.
这意味着,即使某些文档已经发布并且在内容管理器中不再显示为“草稿”或“已修改”,使用 `status: 'draft'` 参数进行计数仍会返回符合其他参数的文档总数。目前没有方法可以阻止已发布的文档被计入统计。
🌐 This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. There currently is no way to prevent already published documents from being counted.
:::
#### 例子 {#examples-2}
🌐 Examples
##### 通用示例 {#generic-example-2}
🌐 Generic example
如果未传递参数,`count()` 方法将返回默认语言环境的文档总数:
##### 统计已发布的文件 {#count-published-documents}
🌐 Count published documents
要仅计算已发布的文档,请将 `status: 'published'` 与其他参数一起传递给 `count()` 方法。
🌐 To count only published documents, pass `status: 'published'` along with other parameters to the `count()` method.
如果没有传入 `locale` 参数,将会统计默认语言环境的文档。
🌐 If no `locale` parameter is passed, documents are counted for the default locale.
##### 使用筛选条件计数文档 {#count-documents-with-filters}
🌐 Count documents with filters
任何 [filters](/cms/api/document-service/filters) 都可以传递给 `count()` 方法。
🌐 Any [filters](/cms/api/document-service/filters) can be passed to the `count()` method.
如果没有传入 `locale` 和 `status` 参数,则草稿文档(即该语言环境的所有可用文档总数,因为即使已发布的文档也被视为有草稿版本)仅会计算默认语言环境:
🌐 If no `locale` and no `status` parameter is passed, draft documents (which is the total of available documents for the locale since even published documents are counted as having a draft version) are counted only for the default locale:
```js
/**
* Count number of draft documents (default if status is omitted)
* in English (default locale)
* whose name starts with 'Pizzeria'
*/
strapi.documents('api::restaurant.restaurant').count({ filters: { name: { $startsWith: "Pizzeria" }}})`
```
# 使用文档服务 API 的字段
Source: https://docs.strapi.io/cms/api/document-service/fields
# 文档服务 API:选择字段 {#document-service-api-selecting-fields}
🌐 Document Service API: Selecting fields
默认情况下,[文档服务 API](/cms/api/document-service) 会返回文档的所有字段,但不会填充任何字段。本页介绍如何使用 `fields` 参数仅返回查询结果中的特定字段。
🌐 By default the [Document Service API](/cms/api/document-service) returns all the fields of a document but does not populate any fields. This page describes how to use the `fields` parameter to return only specific fields with the query results.
:::tip
你也可以使用 `populate` 参数来填充关系、媒体字段、组件或动态区域(参见 [`populate` 参数](/cms/api/document-service/populate) 文档)。
🌐 You can also use the `populate` parameter to populate relations, media fields, components, or dynamic zones (see the [`populate` parameter](/cms/api/document-service/populate) documentation).
:::
## 使用 `findFirst()` 查询选择字段 {#findfirst}
🌐 Select fields with `findFirst()` queries
在使用文档服务 API [查找第一个匹配参数的文档](/cms/api/document-service#findfirst) 时选择要返回的字段:
🌐 To select fields to return while [finding the first document](/cms/api/document-service#findfirst) matching the parameters with the Document Service API:
## 使用 `findMany()` 查询选择字段 {#findmany}
🌐 Select fields with `findMany()` queries
在使用文档服务 API [查找文档](/cms/api/document-service#findmany) 时选择要返回的字段:
🌐 To select fields to return while [finding documents](/cms/api/document-service#findmany) with the Document Service API:
## 使用 `create()` 查询选择字段 {#create}
🌐 Select fields with `create()` queries
在使用文档服务 API [创建文档](/cms/api/document-service#create) 时选择要返回的字段:
🌐 To select fields to return while [creating documents](/cms/api/document-service#create) with the Document Service API:
## 使用 `update()` 查询选择字段 {#update}
🌐 Select fields with `update()` queries
在使用文档服务 API [更新文档](/cms/api/document-service#update) 时选择要返回的字段:
🌐 To select fields to return while [updating documents](/cms/api/document-service#update) with the Document Service API:
## 使用 `delete()` 查询选择字段 {#delete}
🌐 Select fields with `delete()` queries
在使用文档服务 API [删除文档](/cms/api/document-service#delete) 时选择要返回的字段:
🌐 To select fields to return while [deleting documents](/cms/api/document-service#delete) with the Document Service API:
## 使用 `publish()` 查询选择字段 {#publish}
🌐 Select fields with `publish()` queries
在使用文档服务 API [发布文档](/cms/api/document-service#publish) 时选择要返回的字段:
🌐 To select fields to return while [publishing documents](/cms/api/document-service#publish) with the Document Service API:
## 选择包含 `unpublish()` 查询的字段 {#unpublish}
🌐 Select fields with `unpublish()` queries
在使用文档服务 API[取消发布文档](/cms/api/document-service#unpublish)时选择要返回的字段:
🌐 To select fields to return while [unpublishing documents](/cms/api/document-service#unpublish) with the Document Service API:
## 选择包含 `discardDraft()` 查询的字段 {#discarddraft}
🌐 Select fields with `discardDraft()` queries
使用文档服务 API 时,[丢弃文档的草稿版本](/cms/api/document-service#discarddraft) 并选择返回的字段:
🌐 To select fields to return while [discarding draft versions of documents](/cms/api/document-service#discarddraft) with the Document Service API:
# 在文档服务 API 中使用过滤器
Source: https://docs.strapi.io/cms/api/document-service/filters
# 文档服务 API:筛选器 {#document-service-api-filters}
🌐 Document Service API: Filters
[文档服务 API](/cms/api/document-service) 提供筛选结果的功能。
🌐 The [Document Service API](/cms/api/document-service) offers the ability to filter results.
可以使用以下运算符:
🌐 The following operators are available:
| 运算符 | 描述 |
| --- | --- |
| [`$eq`](#eq) | 相等 |
| [`$eqi`](#eqi) | 相等(不区分大小写) |
| [`$ne`](#ne) | 不相等 |
| [`$nei`](#nei) | 不等于(不区分大小写) |
| [`$lt`](#lt) | 少于 |
| [`$lte`](#lte) | 小于或等于 |
| [`$gt`](#gt) | 大于 |
| [`$gte`](#gte) | 大于或等于 |
| [`$in`](#in) | 包含在数组中 |
| [`$notIn`](#notin) | 不包含在数组中 |
| [`$contains`](#contains) | 包含 |
| [`$notContains`](#notcontains) | 不包含 |
| [`$containsi`](#containsi) | 包含(不区分大小写) |
| [`$notContainsi`](#notcontainsi) | 不包含(不区分大小写) |
| [`$null`](#null) | 为空 |
| [`$notNull`](#notnull) | 不为空 |
| [`$between`](#between) | 介于 |
| [`$startsWith`](#startswith) | 以...开始 |
| [`$startsWithi`](#startswithi) | 以…开头(不区分大小写) |
| [`$endsWith`](#endswith) | 以...结尾 |
| [`$endsWithi`](#endswithi) | 以…结尾(不区分大小写) |
| [`$or`](#or) | 将过滤器组合成“或”表达式 |
| [`$and`](#and) | 将过滤器组合成“与”表达式 |
| [`$not`](#not) | 在“not”表达式中连接过滤器 |
## 属性运算符 {#attribute-operators}
🌐 Attribute operators
### `$not`
否定嵌套条件。
🌐 Negates the nested condition(s).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$not: {
$contains: 'Hello World',
},
},
},
});
```
### `$eq`
属性等于输入值。
🌐 Attribute equals input value.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$eq: 'Hello World',
},
},
});
```
`$eq`可以省略:
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: 'Hello World',
},
});
```
### `$eqi`
属性等于输入值(不区分大小写)。
🌐 Attribute equals input value (case-insensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$eqi: 'HELLO World',
},
},
});
```
### `$ne`
属性不等于输入值。
🌐 Attribute does not equal input value.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$ne: 'ABCD',
},
},
});
```
### `$nei`
属性不等于输入值(不区分大小写)。
🌐 Attribute does not equal input value (case-insensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$nei: 'abcd',
},
},
});
```
### `$in`
属性包含在输入列表中。
🌐 Attribute is contained in the input list.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$in: ['Hello', 'Hola', 'Bonjour'],
},
},
});
```
在传递一个值数组时可以省略 `$in`:
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: ['Hello', 'Hola', 'Bonjour'],
},
});
```
### `$notIn`
输入列表中不包含属性。
🌐 Attribute is not contained in the input list.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$notIn: ['Hello', 'Hola', 'Bonjour'],
},
},
});
```
### `$lt`
属性小于输入值。
🌐 Attribute is less than the input value.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
rating: {
$lt: 10,
},
},
});
```
### `$lte`
属性小于或等于输入值。
🌐 Attribute is less than or equal to the input value.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
rating: {
$lte: 10,
},
},
});
```
### `$gt`
属性大于输入值。
🌐 Attribute is greater than the input value.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
rating: {
$gt: 5,
},
},
});
```
### `$gte`
属性大于或等于输入值。
🌐 Attribute is greater than or equal to the input value.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
rating: {
$gte: 5,
},
},
});
```
### `$between`
属性介于两个输入值之间,包括边界(例如,`$between[1, 3]` 也会返回 `1` 和 `3`)。
🌐 Attribute is between the 2 input values, boundaries included (e.g., `$between[1, 3]` will also return `1` and `3`).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
rating: {
$between: [1, 20],
},
},
});
```
### `$contains`
属性包含输入值(区分大小写)。
🌐 Attribute contains the input value (case-sensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$contains: 'Hello',
},
},
});
```
### `$notContains`
属性不包含输入值(区分大小写)。
🌐 Attribute does not contain the input value (case-sensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$notContains: 'Hello',
},
},
});
```
### `$containsi`
属性包含输入值。`$containsi`不区分大小写,而[$contains](#contains)区分大小写。
🌐 Attribute contains the input value. `$containsi` is not case-sensitive, while [$contains](#contains) is.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$containsi: 'hello',
},
},
});
```
### `$notContainsi`
属性不包含输入值。`$notContainsi` 不区分大小写,而 [$notContains](#notcontains) 区分大小写。
🌐 Attribute does not contain the input value. `$notContainsi` is not case-sensitive, while [$notContains](#notcontains) is.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$notContainsi: 'hello',
},
},
});
```
### `$startsWith`
属性以输入值开头(区分大小写)。
🌐 Attribute starts with input value (case-sensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$startsWith: 'ABCD',
},
},
});
```
### `$startsWithi`
属性以输入值开头(不区分大小写)。
🌐 Attribute starts with input value (case-insensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$startsWithi: 'ABCD', // will return the same as filtering with 'abcd'
},
},
});
```
### `$endsWith`
属性以输入值结尾(区分大小写)。
🌐 Attribute ends with input value (case-sensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$endsWith: 'ABCD',
},
},
});
```
### `$endsWithi`
属性以输入值结尾(不区分大小写)。
🌐 Attribute ends with input value (case-insensitive).
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$endsWith: 'ABCD', // will return the same as filtering with 'abcd'
},
},
},
});
```
### `$null`
属性是 `null`。
🌐 Attribute is `null`.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$null: true,
},
},
});
```
### `$notNull`
属性不是 `null`。
🌐 Attribute is not `null`.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: {
$notNull: true,
},
},
});
```
## 逻辑运算符 {#logical-operators}
🌐 Logical operators
### `$and`
所有嵌套条件必须是 `true`。
🌐 All nested conditions must be `true`.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
$and: [
{
title: 'Hello World',
},
{
createdAt: { $gt: '2021-11-17T14:28:25.843Z' },
},
],
},
});
```
`$and` 在传递带有嵌套条件的对象时将被隐式使用:
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
title: 'Hello World',
createdAt: { $gt: '2021-11-17T14:28:25.843Z' },
},
});
```
### `$or`
一个或多个嵌套条件必须是 `true`。
🌐 One or many nested conditions must be `true`.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
$or: [
{
title: 'Hello World',
},
{
createdAt: { $gt: '2021-11-17T14:28:25.843Z' },
},
],
},
});
```
### `$not`
否定嵌套条件。
🌐 Negates the nested conditions.
**示例**
```js
const entries = await strapi.documents('api::article.article').findMany({
filters: {
$not: {
title: 'Hello World',
},
},
});
```
:::note
`$not` 可以用作:
- 一个逻辑运算符(例如在 `filters: { $not: { // conditions… }}` 中)
- [属性操作符](#not)(例如在 `filters: { attribute-name: $not: { … } }` 中)。
:::
:::tip
`$and`、`$or` 和 `$not` 操作符可以嵌套在另一个 `$and`、`$or` 或 `$not` 操作符中。
:::
# 在文档服务 API 中使用区域参数
Source: https://docs.strapi.io/cms/api/document-service/locale
# 文档服务 API:使用 `locale` 参数 {#document-service-api-using-the-locale-parameter}
🌐 Document Service API: Using the `locale` parameter
默认情况下,[Document Service API](/cms/api/document-service) 返回文档的默认语言版本(默认为'en',即英语版本,除非应用已设置了其他默认语言,详见[国际化(i18n)功能](/cms/features/internationalization))。本页面描述了如何使用 `locale` 参数仅获取或操作特定语言的数据。
🌐 By default the [Document Service API](/cms/api/document-service) returns the default locale version of documents (which is 'en', i.e. the English version, unless another default locale has been set for the application, see [Internationalization (i18n) feature](/cms/features/internationalization)). This page describes how to use the `locale` parameter to get or manipulate data only for specific locales.
## 获取带有 `findOne()` 的本地化版本 {#find-one}
🌐 Get a locale version with `findOne()`
如果传入 `locale`,文档服务 API 的 [`findOne()` 方法](/cms/api/document-service#findone) 将返回该语言环境的文档版本:
🌐 If a `locale` is passed, the [`findOne()` method](/cms/api/document-service#findone) of the Document Service API returns the version of the document for this locale:
如果没有传递 `status` 参数,则默认返回 `draft` 版本。
🌐 If no `status` parameter is passed, the `draft` version is returned by default.
## 获取带有 `findFirst()` 的本地化版本 {#find-first}
🌐 Get a locale version with `findFirst()`
要在使用文档服务 API [查找第一个](/cms/api/document-service#findfirst) 与参数匹配的文档时返回特定区域设置:
🌐 To return a specific locale while [finding the first document](/cms/api/document-service#findfirst) matching the parameters with the Document Service API:
如果没有传递 `status` 参数,则默认返回 `draft` 版本。
🌐 If no `status` parameter is passed, the `draft` version is returned by default.
## 使用 `findMany()` 获取本地化版本 {#find-many}
🌐 Get locale versions with `findMany()`
当将 `locale` 传递给文档服务 API 的 [`findMany()` 方法](/cms/api/document-service#findmany) 时,响应将返回所有具有此语言环境的文档。
🌐 When a `locale` is passed to the [`findMany()` method](/cms/api/document-service#findmany) of the Document Service API, the response will return all documents that have this locale available.
如果没有传递 `status` 参数,则默认返回 `draft` 版本。
🌐 If no `status` parameter is passed, the `draft` versions are returned by default.
解释:
给定以下 4 个具有不同语言环境的文档:
🌐 Given the following 4 documents that have various locales:
- 文件A:
- en
- `fr`
- it
- 文件 B:
- en
- it
- 文件 C:
- `fr`
- 文件 D:
- `fr`
- it
`findMany({ locale: 'fr' })` 只会返回那些有 `‘fr’` 语言版本的文档的草稿版本,即文档 A、C 和 D。
## `create()` 为一个区域创建文档 {#create}
🌐 `create()` a document for a locale
要为特定区域创建文档,请将 `locale` 作为参数传递给文档服务 API 的 [`create` 方法](/cms/api/document-service#create):
🌐 To create a document for specific locale, pass the `locale` as a parameter to the [`create` method](/cms/api/document-service#create) of the Document Service API:
## `update()` 本地化版本 {#update}
🌐 `update()` a locale version
要仅更新文档的特定语言版本,请将 `locale` 参数传递给文档服务 API 的 [`update()` 方法](/cms/api/document-service#update):
🌐 To update only a specific locale version of a document, pass the `locale` parameter to the [`update()` method](/cms/api/document-service#update) of the Document Service API:
## `delete()` 语言区域版本 {#delete}
🌐 `delete()` locale versions
使用 Document Service API 的 [`delete()` 方法](/cms/api/document-service#delete) 的 `locale` 参数仅删除某些语言版本。除非传入特定的 `status` 参数,否则这将删除草稿和已发布版本。
🌐 Use the `locale` parameter with the [`delete()` method](/cms/api/document-service#delete) of the Document Service API to delete only some locales. Unless a specific `status` parameter is passed, this deletes both the draft and published versions.
### 删除一个语言版本 {#delete-a-locale-version}
🌐 Delete a locale version
要删除文档的特定语言环境版本:
🌐 To delete a specific locale version of a document:
### 删除所有语言版本 {#delete-all-locale-versions}
🌐 Delete all locale versions
`*` 通配符由 `locale` 参数支持,可用于删除文档的所有语言版本:
🌐 The `*` wildcard is supported by the `locale` parameter and can be used to delete all locale versions of a document:
## `publish()` 语言版本 {#publish}
🌐 `publish()` locale versions
要使用文档服务 API 的 [`publish()` 方法](/cms/api/document-service#publish) 仅发布文档的特定语言版本,请将 `locale` 作为参数传递:
🌐 To publish only specific locale versions of a document with the [`publish()` method](/cms/api/document-service#publish) of the Document Service API, pass `locale` as a parameter:
### 发布本地化版本 {#publish-a-locale-version}
🌐 Publish a locale version
要发布文档的特定语言环境版本:
🌐 To publish a specific locale version of a document:
### 发布所有语言版本 {#publish-all-locale-versions}
🌐 Publish all locale versions
`*` 通配符由 `locale` 参数支持,用于发布文档的所有语言版本:
🌐 The `*` wildcard is supported by the `locale` parameter to publish all locale versions of a document:
## `unpublish()` 语言版本 {#unpublish}
🌐 `unpublish()` locale versions
要使用文档服务 API 的 [`unpublish()` 方法](/cms/api/document-service#unpublish) 仅发布文档的特定语言版本,请将 `locale` 作为参数传递:
🌐 To publish only specific locale versions of a document with the [`unpublish()` method](/cms/api/document-service#unpublish) of the Document Service API, pass `locale` as a parameter:
### 取消发布本地版本 {#unpublish-a-locale-version}
🌐 Unpublish a locale version
要取消发布文档的特定语言版本,请将 `locale` 作为参数传递给 `unpublish()`:
🌐 To unpublish a specific locale version of a document, pass the `locale` as a parameter to `unpublish()`:
### 取消发布所有语言版本 {#unpublish-all-locale-versions}
🌐 Unpublish all locale versions
`*` 通配符由 `locale` 参数支持,用于取消发布文档的所有语言版本:
🌐 The `*` wildcard is supported by the `locale` parameter, to unpublish all locale versions of a document:
## `discardDraft()` 用于本地化版本 {#discard-draft}
🌐 `discardDraft()` for locale versions
要仅丢弃某些语言版本文档的草稿数据,使用文档服务 API 的 [`discardDraft()` 方法](/cms/api/document-service#discarddraft),传递 `locale` 作为参数:
🌐 To discard draft data only for some locales versions of a document with the [`discardDraft()` method](/cms/api/document-service#discarddraft) of the Document Service API, pass `locale` as a parameter:
### 丢弃本地化版本的草稿 {#discard-draft-for-a-locale-version}
🌐 Discard draft for a locale version
要放弃文档特定语言版本的草稿数据,并用该语言版本的已发布数据覆盖它,请将 `locale` 作为参数传递给 `discardDraft()`:
🌐 To discard draft data for a specific locale version of a document and override it with data from the published version for this locale, pass the `locale` as a parameter to `discardDraft()`:
### 丢弃所有语言版本的草稿 {#discard-drafts-for-all-locale-versions}
🌐 Discard drafts for all locale versions
`*` 通配符由 `locale` 参数支持,用于丢弃文档的所有区域版本的草稿数据,并用已发布版本的数据替换它们:
🌐 The `*` wildcard is supported by the `locale` parameter, to discard draft data for all locale versions of a document and replace them with the data from the published versions:
## `count()` 个本地化文档 {#count}
🌐 `count()` documents for a locale
要统计特定语言环境的文档,请将 `locale` 与其他参数一起传递给文档服务 API 的 [`count()` 方法](/cms/api/document-service#count)。
🌐 To count documents for a specific locale, pass the `locale` along with other parameters to the [`count()` method](/cms/api/document-service#count) of the Document Service API.
如果没有传递 `status` 参数,则统计草稿文档(即该语言环境下可用文档的总数,因为即使已发布的文档也会被计为有草稿版本):
🌐 If no `status` parameter is passed, draft documents are counted (which is the total of available documents for the locale since even published documents are counted as having a draft version):
```js
// Count number of published documents in French
strapi.documents('api::restaurant.restaurant').count({ locale: 'fr' });
```
# 扩展文档服务行为
Source: https://docs.strapi.io/cms/api/document-service/middlewares
# 文档服务 API:中间件 {#document-service-api-middlewares}
🌐 Document Service API: Middlewares
[文档服务 API](/cms/api/document-service) 提供了通过中间件扩展其行为的能力。
🌐 The [Document Service API](/cms/api/document-service) offers the ability to extend its behavior thanks to middlewares.
文档服务中间件允许你在方法运行之前和/或之后执行操作。
🌐 Document Service middlewares allow you to perform actions before and/or after a method runs.
该图表示请求在 Strapi 后端传输的简化版本,并突出了文档服务。后端自定义介绍页面包括一个完整的、 交互式图表。
## 注册中间件 {#registering-a-middleware}
🌐 Registering a middleware
语法:`strapi.documents.use(middleware)`
🌐 Syntax: `strapi.documents.use(middleware)`
### 参数 {#parameters}
🌐 Parameters
中间件是一种接收上下文和下一个函数的函数。
🌐 A middleware is a function that receives a context and a next function.
语法:`(context, next) => ReturnType`
🌐 Syntax: `(context, next) => ReturnType`
| 参数 | 描述 | 类型 ||-----------|---------------------------------------|------------|| `context` | 中间件上下文 | `Context` || `next` | 调用堆栈中的下一个中间件 | `function` |
#### `context`
| 参数 | 描述 | 类型 ||---------------|--------------------------------------------------------------------------------------|---------------|| `action` | 正在运行的方法([查看可用方法](/cms/api/document-service)) | `string` || `params` | 方法参数([查看可用方法](/cms/api/document-service)) | `Object` || `uid` | 内容类型唯一标识 | `string` || `contentType` | 内容类型 | `ContentType` |
示例:
以下示例显示了根据调用的方法,`context` 可能包含的内容:
🌐 The following examples show what `context` might include depending on the method called:
#### `next`
`next` 是一个没有参数的函数,它调用堆栈中的下一个中间件并返回其响应。
**示例**
```js
strapi.documents.use((context, next) => {
return next();
});
```
### 在哪里注册 {#where-to-register}
🌐 Where to register
一般来说,你应该在 Strapi 注册阶段注册你的中间件。
🌐 Generaly speaking you should register your middlewares during the Strapi registration phase.
#### 用户 {#users}
🌐 Users
中间件必须在通用的 `register()` 生命周期方法中注册:
🌐 The middleware must be registered in the general `register()` lifecycle method:
```js title="/src/index.js|ts"
module.exports = {
register({ strapi }) {
strapi.documents.use((context, next) => {
// your logic
return next();
});
},
// bootstrap({ strapi }) {},
// destroy({ strapi }) {},
};
```
#### 插件开发者 {#plugin-developers}
🌐 Plugin developers
中间件必须在插件的 `register()` 生命周期方法中注册:
🌐 The middleware must be registered in the plugin's `register()` lifecycle method:
```js title="/(plugin-root-folder)/strapi-server.js|ts"
module.exports = {
register({ strapi }) {
strapi.documents.use((context, next) => {
// your logic
return next();
});
},
// bootstrap({ strapi }) {},
// destroy({ strapi }) {},
};
```
## 实现中间件 {#implementing-a-middleware}
🌐 Implementing a middleware
在实现中间件时,总是要返回来自 `next()` 的响应。
如果不这样做,将会导致 Strapi 应用出错。
🌐 When implementing a middleware, always return the response from `next()`.
Failing to do this will break the Strapi application.
### 例子 {#examples}
🌐 Examples
```js
const applyTo = ['api::article.article'];
strapi.documents.use((context, next) => {
// Only run for certain content types
if (!applyTo.includes(context.uid)) {
return next();
}
// Only run for certain actions
if (['create', 'update'].includes(context.action)) {
context.params.data.fullName = `${context.params.data.firstName} ${context.params.data.lastName}`;
}
const result = await next();
// do something with the result before returning it
return result
});
```
:::strapi Lifecycle hooks
文档服务 API 会根据调用的方法触发各种数据库生命周期钩子。完整参考请参见 [文档服务 API:生命周期钩子](/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service#table)。
🌐 The Document Service API triggers various database lifecycle hooks based on which method is called. For a complete reference, see [Document Service API: Lifecycle hooks](/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service#table).
:::
# 使用 Document Service API 的 Populate
Source: https://docs.strapi.io/cms/api/document-service/populate
# 文档服务 API:填充字段 {#document-service-api-populating-fields}
🌐 Document Service API: Populating fields
默认情况下,[文档服务 API](/cms/api/document-service) 不会填充任何关系、媒体字段、组件或动态区域。本页介绍如何使用 `populate` 参数来填充特定字段。
🌐 By default the [Document Service API](/cms/api/document-service) does not populate any relations, media fields, components, or dynamic zones. This page describes how to use the `populate` parameter to populate specific fields.
:::tip
你也可以使用 `select` 参数仅返回查询结果中的特定字段(参见 [`select` 参数](/cms/api/document-service/fields) 文档)。
🌐 You can also use the `select` parameter to return only specific fields with the query results (see the [`select` parameter](/cms/api/document-service/fields) documentation).
:::
:::caution
如果安装了“用户与权限”插件,则必须为正在填充的内容类型启用 `find` 权限。如果某个角色无法访问某个内容类型,则该内容类型将不会被填充。
🌐 If the Users & Permissions plugin is installed, the `find` permission must be enabled for the content-types that are being populated. If a role doesn't have access to a content-type it will not be populated.
:::
## 关系与媒体字段 {#relations-and-media-fields}
🌐 Relations and media fields
查询可以接受一个 `populate` 参数来明确指定要填充的字段,语法选项示例如下。
🌐 Queries can accept a `populate` parameter to explicitly define which fields to populate, with the following syntax option examples.
### 为所有关系填充 1 级 {#populate-1-level-for-all-relations}
🌐 Populate 1 level for all relations
要为所有关系填充一层深度,请将 `*` 通配符与 `populate` 参数结合使用:
🌐 To populate one-level deep for all relations, use the `*` wildcard in combination with the `populate` parameter:
### 为特定关系填充 1 级 {#populate-1-level-for-specific-relations}
🌐 Populate 1 level for specific relations
要填充特定的一层深度的关系,请在 `populate` 数组中传入关系名称:
🌐 To populate specific relations one-level deep, pass the relation names in a `populate` array:
### 为特定关系填充多层数据 {#populate-several-levels-deep-for-specific-relations}
🌐 Populate several levels deep for specific relations
要填充多层的特定关联,请使用带有 `populate` 的对象格式:
🌐 To populate specific relations several levels deep, use the object format with `populate`:
## 组件与动态区域 {#components--dynamic-zones}
🌐 Components & Dynamic Zones
组件的填充方式与关系相同:
🌐 Components are populated the same way as relations:
动态区域本质上是高度动态的内容结构。要填充动态区域,你必须使用 `on` 属性为每个组件定义填充查询。
🌐 Dynamic zones are highly dynamic content structures by essence. To populate a dynamic zone, you must define per-component populate queries using the `on` property.
## 正在用 `create()` 填充 {#populating-with-create}
🌐 Populating with `create()`
要在创建文档时填充:
🌐 To populate while creating documents:
## 正在用 `update()` 填充 {#populating-with-update}
🌐 Populating with `update()`
要在更新文档时填充:
🌐 To populate while updating documents:
## 正在用 `publish()` 填充 {#populating-with-publish}
🌐 Populating with `publish()`
在发布文档时进行填充(与 `unpublish()` 和 `discardDraft()` 的行为相同):
🌐 To populate while publishing documents (same behavior with `unpublish()` and `discardDraft()`):
# 在文档服务 API 中使用排序和分页
Source: https://docs.strapi.io/cms/api/document-service/sort-pagination
# 文档服务 API:结果的排序和分页 {#document-service-api-sorting-and-paginating-results}
🌐 Document Service API: Sorting and paginating results
[文档服务 API](/cms/api/document-service) 提供对查询结果进行排序和分页的功能。
🌐 The [Document Service API](/cms/api/document-service) offers the ability to sort and paginate query results.
## 排序 {#sort}
🌐 Sort
要对文档服务 API 返回的结果进行排序,请在查询中包含 `sort` 参数。
🌐 To sort results returned by the Document Service API, include the `sort` parameter with queries.
### 按单个字段排序 {#sort-on-a-single-field}
🌐 Sort on a single field
要根据单个字段对结果进行排序:
🌐 To sort results based on a single field:
### 按多个字段排序 {#sort-on-multiple-fields}
🌐 Sort on multiple fields
要对多个字段进行排序,请将它们全部传递到一个数组中:
🌐 To sort on multiple fields, pass them all in an array:
## 分页 {#pagination}
🌐 Pagination
要对结果进行分页,请传递 `limit` 和 `start` 参数:
🌐 To paginate results, pass the `limit` and `start` parameters:
# 在文档服务 API 中使用草稿与发布
Source: https://docs.strapi.io/cms/api/document-service/status
# 文档服务 API:草稿与发布的使用 {#document-service-api-usage-with-draft--publish}
🌐 Document Service API: Usage with Draft & Publish
默认情况下,当启用 [Draft & Publish](/cms/features/draft-and-publish) 功能时,[Document Service API](/cms/api/document-service) 会返回文档的草稿版本。此页面描述了如何使用 `status` 参数来:
🌐 By default the [Document Service API](/cms/api/document-service) returns the draft version of a document when the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled. This page describes how to use the `status` parameter to:
- 返回文档的已发布版本,
- 根据文档的状态计数文档,
- 并在创建或更新文档时直接发布文档。
:::note
将 `{ status: 'draft' }` 传递给文档服务 API 查询返回的结果与未传递任何 `status` 参数时相同。
🌐 Passing `{ status: 'draft' }` to a Document Service API query returns the same results as not passing any `status` parameter.
:::
## 获取已发布的版本与 `findOne()` {#find-one}
🌐 Get the published version with `findOne()`
`findOne()` 查询默认返回文档的草稿版本。
要在使用文档服务 API [查找特定文档](/cms/api/document-service#findone) 时返回已发布的版本,请传递 `status: 'published'`:
🌐 To return the published version while [finding a specific document](/cms/api/document-service#findone) with the Document Service API, pass `status: 'published'`:
## 获取带有 `findFirst()` {#find-first} 的已发布版本
🌐 Get the published version with `findFirst()`
`findFirst()` 查询默认返回文档的草稿版本。
要在使用文档服务 API[查找第一个文档](/cms/api/document-service#findfirst)时返回已发布的版本,请传递 `status: 'published'`:
🌐 To return the published version while [finding the first document](/cms/api/document-service#findfirst) with the Document Service API, pass `status: 'published'`:
## 获取已发布的版本与 `findMany()` {#find-many}
🌐 Get the published version with `findMany()`
`findMany()` 查询默认返回文档的草稿版本。
在使用文档服务 API [查找文档](/cms/api/document-service#findmany) 时,要返回已发布的版本,请传递 `status: 'published'`:
🌐 To return the published version while [finding documents](/cms/api/document-service#findmany) with the Document Service API, pass `status: 'published'`:
## `count()` 仅草稿或已发布版本 {#count}
🌐 `count()` only draft or published versions
在使用文档服务 API [计数文档](/cms/api/document-service#count) 时,如果只考虑文档的草稿或已发布版本,请传递相应的 `status` 参数:
🌐 To take into account only draft or published versions of documents while [counting documents](/cms/api/document-service#count) with the Document Service API, pass the corresponding `status` parameter:
```js
// Count draft documents (also actually includes published documents)
const draftsCount = await strapi.documents("api::restaurant.restaurant").count({
status: 'draft'
});
```
```js
// Count only published documents
const publishedCount = await strapi.documents("api::restaurant.restaurant").count({
status: 'published'
});
```
:::note
由于已发布的文档必然也有草稿副本,因此已发布的文档仍算作具有草稿版本。
🌐 Since published documents necessarily also have a draft counterpart, a published document is still counted as having a draft version.
这意味着,即使某些文档已经发布并且在内容管理器中不再显示为“草稿”或“已修改”,使用 `status: 'draft'` 参数进行计数仍会返回符合其他参数的文档总数。目前没有方法可以阻止已发布的文档被计入统计。
🌐 This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. There currently is no way to prevent already published documents from being counted.
:::
## 创建草稿并发布它 {#create}
🌐 Create a draft and publish it
要在创建文档时自动发布它,请将 `status: 'published'` 添加到传递给 `create()` 的参数中:
🌐 To automatically publish a document while creating it, add `status: 'published'` to parameters passed to `create()`:
## 更新草稿并发布它 {#update}
🌐 Update a draft and publish it
要在更新文档时自动发布它,请将 `status: 'published'` 添加到传递给 `update()` 的参数中:
🌐 To automatically publish a document while updating it, add `status: 'published'` to parameters passed to `update()`:
# GraphQL API
Source: https://docs.strapi.io/cms/api/graphql
# GraphQL API
GraphQL API 允许通过 Strapi 的 [GraphQL 插件](/cms/plugins/graphql) 对 [内容类型](/cms/backend-customization/models#content-types) 执行查询和变更。结果可以被 [过滤](#filters)、[排序](#sorting) 和 [分页](#pagination)。
🌐 The GraphQL API allows performing queries and mutations to interact with the [content-types](/cms/backend-customization/models#content-types) through Strapi's [GraphQL plugin](/cms/plugins/graphql). Results can be [filtered](#filters), [sorted](#sorting) and [paginated](#pagination).
:::prerequisites
要使用 GraphQL API,请安装 [GraphQL](/cms/plugins/graphql) 插件:
🌐 To use the GraphQL API, install the [GraphQL](/cms/plugins/graphql) plugin:
:::
安装完成后,GraphQL playground 可通过 `/graphql` URL 访问,并可用于交互式构建查询和变更操作,以及阅读针对你的内容类型定制的文档:
🌐 Once installed, the GraphQL playground is accessible at the `/graphql` URL and can be used to interactively build your queries and mutations and read documentation tailored to your content-types:
#### 获取关系 {#fetch-relations}
🌐 Fetch relations
你可以在你的扁平查询或你的
:::
### 获取媒体字段 {#fetch-media-fields}
🌐 Fetch media fields
媒体字段内容的获取方式与其他属性一样。
🌐 Media fields content is fetched just like other attributes.
以下示例获取“Restaurants”内容类型中附加到每个文档的每个 `cover` 媒体字段的 `url` 属性值:
🌐 The following example fetches the `url` attribute value for each `cover` media field attached to each document from the "Restaurants" content-type:
```graphql
{
restaurants {
images {
documentId
url
}
}
}
```
对于多个媒体字段,你可以使用扁平查询或
### 获取组件 {#fetch-components}
🌐 Fetch components
组件内容的获取方式与其他属性一样。
🌐 Components content is fetched just like other attributes.
以下示例获取每个文档中添加的每个 `closingPeriod` 组件的 `label`、`start_date` 和 `end_date` 属性值,这些文档来自“餐馆”内容类型:
🌐 The following example fetches the `label`, `start_date`, and `end_date` attributes values for each `closingPeriod` component added to each document from the "Restaurants" content-type:
```graphql
{
restaurants {
closingPeriod {
label
start_date
end_date
}
}
}
```
### 获取动态区域数据 {#fetch-dynamic-zone-data}
🌐 Fetch dynamic zone data
动态区域是在 GraphQL 中的联合类型,因此你需要使用
```graphql title="Simple examples for membership operators (in, notIn)"
# in - returns restaurants with category either "pizza" or "burger"
{
restaurants(filters: { category: { in: ["pizza", "burger"] } }) {
name
}
}
# notIn - returns restaurants whose category is neither "pizza" nor "burger"
{
restaurants(filters: { category: { notIn: ["pizza", "burger"] } }) {
name
}
}
```
```graphql title="Simple examples for null checks operators (null, notNull)"
# null - returns restaurants where description is null
{
restaurants(filters: { description: { null: true } }) {
name
}
}
# notNull - returns restaurants where description is not null
{
restaurants(filters: { description: { notNull: true } }) {
name
}
}
```
```graphql title="Simple examples for logical operators (and, or, not)"
# and - both category must be "pizza" AND averagePrice must be < 20
{
restaurants(filters: {
and: [
{ category: { eq: "pizza" } },
{ averagePrice: { lt: 20 } }
]
}) {
name
}
}
# or - category is "pizza" OR category is "burger"
{
restaurants(filters: {
or: [
{ category: { eq: "pizza" } },
{ category: { eq: "burger" } }
]
}) {
name
}
}
# not - category must NOT be "pizza"
{
restaurants(filters: {
not: { category: { eq: "pizza" } }
}) {
name
}
}
```
```graphql title="Example with nested logical operators: use and, or, and not to find pizzerias under 20 euros"
{
restaurants(
filters: {
and: [
{ not: { averagePrice: { gte: 20 } } }
{
or: [
{ name: { eq: "Pizzeria" } }
{ name: { startsWith: "Pizzeria" } }
]
}
]
}
) {
documentId
name
averagePrice
}
}
```
### 获取特定语言环境的文档 {#locale-fetch}
🌐 Fetch a document in a specific locale
要获取特定区域的文档
### 创建一个新的本地化文档 {#locale-create}
🌐 Create a new localized document
`locale` 字段可以传递以创建针对特定语言环境的本地化文档
# OpenAPI 规范
Source: https://docs.strapi.io/cms/api/openapi
# OpenAPI 规范生成 {#openapi-specification-generation}
🌐 OpenAPI specification generation
Strapi 提供了一个命令行工具来为你的应用生成
你还可以传递一个可选的 `--output` 参数来指定路径和文件名,如下面的示例所示:
🌐 You can also path an optional `--output` argument to specify the path and filename, as in the following example:
### 规范结构和内容 {#specification-structure-and-content}
🌐 Specification structure and content
生成的 OpenAPI 规范遵循
生成的 OpenAPI 规范包含 Strapi 应用中所有可用的 API 端点,以及有关这些端点的信息,例如:
🌐 The generated OpenAPI specification includes all available API endpoints in your Strapi application, and information about these endpoints, such as the following:
- 适用于所有内容类型的 CRUD 操作
- 应用中定义的自定义 API 路由
- 用于用户管理的身份验证端点
- 用于媒体处理的文件上传端点
- 已安装插件的插件端点
## 与 Swagger UI 集成 {#integrating-with-swagger-ui}
🌐 Integrating with Swagger UI
通过以下步骤,你可以快速生成一个与 [Swagger UI](https://swagger.io/) 兼容的页面:
🌐 With the following steps you can quickly generate a [Swagger UI](https://swagger.io/)-compatible page:
1. 生成规范:
2. 使用以下代码更新 [ `/config/middlewares.js` 配置文件](/cms/configurations/middlewares):
这将确保来自 的 Swagger UI 显示不会被由[安全中间件](/cms/configurations/middlewares#security)处理的 Strapi CSP 策略阻止。
3. 在你的 Strapi 项目中创建一个 `public/openapi.html` 文件来显示 Swagger UI,代码如下:
```html
API Documentation
```
4. 使用 `yarn develop` 或 `npm run develop` 重新启动 Strapi 服务器,然后访问 `/openapi.html` 页面。应该会显示 Swagger UI:

# REST API参考
Source: https://docs.strapi.io/cms/api/rest
# REST API参考 {#rest-api-reference}
🌐 REST API reference
REST API 允许通过 API 端点访问 [内容类型](/cms/backend-customization/models)。Strapi 在创建内容类型时会自动创建 [API 端点](#endpoints)。在查询 API 端点时可以使用 [API 参数](/cms/api/rest/parameters) 来优化结果。
🌐 The REST API allows accessing the [content-types](/cms/backend-customization/models) through API endpoints. Strapi automatically creates [API endpoints](#endpoints) when a content-type is created. [API parameters](/cms/api/rest/parameters) can be used when querying API endpoints to refine the results.
本节文档是针对内容类型的 REST API 参考。我们还提供了针对特定用例的[指南](/cms/api/rest/guides/intro)。
🌐 This section of the documentation is for the REST API reference for content-types. We also have [guides](/cms/api/rest/guides/intro) available for specific use cases.
:::prerequisites
所有内容类型默认都是私有的,需要将其设为公开,或者查询需要使用适当权限进行认证。有关更多详细信息,请参阅[快速入门指南](/cms/quick-start#step-4-set-roles--permissions)、[用户与权限功能](/cms/features/users-permissions#roles)用户指南,以及[API 令牌配置文档](/cms/features/api-tokens)。
🌐 All content types are private by default and need to be either made public or queries need to be authenticated with the proper permissions. See the [Quick Start Guide](/cms/quick-start#step-4-set-roles--permissions), the user guide for the [Users & Permissions feature](/cms/features/users-permissions#roles), and [API tokens configuration documentation](/cms/features/api-tokens) for more details.
:::
:::note
默认情况下,REST API 响应仅包含顶层字段,不会填充任何关系、媒体字段、组件或动态区域。使用 [`populate` 参数](/cms/api/rest/populate-select) 来填充特定字段。确保为要填充的关系的字段授予查找权限。
🌐 By default, the REST API responses only include top-level fields and does not populate any relations, media fields, components, or dynamic zones. Use the [`populate` parameter](/cms/api/rest/populate-select) to populate specific fields. Ensure that the find permission is given to the field(s) for the relation(s) you populate.
:::
:::strapi Strapi Client
[Strapi 客户端](/cms/api/client) 库简化了与你的 Strapi 后端的交互,提供了一种获取、创建、更新和删除内容的方式。
🌐 The [Strapi Client](/cms/api/client) library simplifies interactions with your Strapi back end, providing a way to fetch, create, update, and delete content.
:::
## 端点 {#endpoints}
🌐 Endpoints
对于每个 Content-Type,会自动生成以下端点:
🌐 For each Content-Type, the following endpoints are automatically generated:
复数 API ID 与 单数 API ID:
在下表中:
🌐 In the following tables:
- `:singularApiId` 指内容类型中“API ID(单数)”字段的值,
- 而 `:pluralApiId` 指的是内容类型的“API ID(复数)”字段的值。
这些值是在内容类型构建器中创建内容类型时定义的,并且可以在管理面板编辑内容类型时找到(参见 [用户指南](/cms/features/content-type-builder#creating-content-types))。例如,对于“文章”内容类型,默认情况下:
🌐 These values are defined when creating a content-type in the Content-Type Builder, and can be found while editing a content-type in the admin panel (see [User Guide](/cms/features/content-type-builder#creating-content-types)). For instance, by default, for an "Article" content-type:
- `:singularApiId` 将是 `article`
- `:pluralApiId` 将是 `articles`
端点的真实世界示例:
以下端点示例取自
:::strapi Upload API
上传包(为[媒体库功能](/cms/features/media-library)提供支持)有一个特定的 API,可通过其[`/api/upload`端点](/cms/api/rest/upload)访问。
🌐 The Upload package (which powers the [Media Library feature](/cms/features/media-library)) has a specific API accessible through its [`/api/upload` endpoints](/cms/api/rest/upload).
:::
:::note
[组件](/cms/backend-customization/models#components-json) 没有 API 端点。
:::
## 请求 {#requests}
🌐 Requests
:::strapi Strapi 5 vs. Strapi v4
Strapi 5 的内容 API 与 Strapi v4 有 2 个主要区别:
🌐 Strapi 5's Content API includes 2 major differences with Strapi v4:
- 响应格式已被扁平化,这意味着属性不再嵌套在 `data.attributes` 对象中,而是可以直接在 `data` 对象的第一层访问(例如,内容类型的“title”属性可以使用 `data.title` 访问)。
- Strapi 5 现在使用 **文档**
### 获取文档 {#get}
🌐 Get a document
通过 `documentId` 返回文档。
🌐 Returns a document by `documentId`.
:::strapi Strapi 5 vs. Strapi v4
在 Strapi 5 中,特定文档可以通过其 `documentId` 来访问。
🌐 In Strapi 5, a specific document is reached by its `documentId`.
:::
### 创建文档 {#create}
🌐 Create a document
创建一个文档并返回其值。
🌐 Creates a document and returns its value.
如果安装了[国际化 (i18n) 插件](/cms/features/internationalization),则可以使用 POST 请求向 REST API [创建本地化文档](/cms/api/rest/locale#rest-delete)。
🌐 If the [Internationalization (i18n) plugin](/cms/features/internationalization) is installed, it's possible to use POST requests to the REST API to [create localized documents](/cms/api/rest/locale#rest-delete).
:::note
在创建文档时,你可以定义其关系及其顺序(有关更多详细信息,请参见[通过 REST API 管理关系](/cms/api/rest/relations.md))。
🌐 While creating a document, you can define its relations and their order (see [Managing relations through the REST API](/cms/api/rest/relations.md) for more details).
:::
### 更新文档 {#update}
🌐 Update a document
通过 `id` 部分更新文档并返回其值。
🌐 Partially updates a document by `id` and returns its value.
发送一个 `null` 值以清除字段。
🌐 Send a `null` value to clear fields.
:::note NOTES
* 即使安装了[国际化 (i18n) 插件](/cms/features/internationalization),目前仍然无法[更新文档的语言环境](/cms/api/rest/locale#rest-update)。
* 在更新文档时,你可以定义其关系及其顺序(有关更多详细信息,请参见[通过 REST API 管理关系](/cms/api/rest/relations))。
:::
### 删除文档 {#delete}
🌐 Delete a document
删除文档。
🌐 Deletes a document.
`DELETE` 请求在成功时仅发送 204 HTTP 状态码,并且不会在响应体中返回任何数据。
# 过滤器
Source: https://docs.strapi.io/cms/api/rest/filters
# REST API:过滤器 {#rest-api-filters}
🌐 REST API: Filters
[REST API](/cms/api/rest) 提供了使用其 ["获取条目"](/cms/api/rest#get-all) 方法筛选结果的能力。
使用可选的 Strapi 功能可以提供更多筛选条件:
- 如果在某个内容类型上启用了[国际化 (i18n) 插件](/cms/features/internationalization),就可以按语言环境进行过滤。
- 如果启用了 [Draft & Publish](/cms/features/draft-and-publish),可以根据 `published`(默认)或 `draft` 状态进行筛选。
:::tip
JavaScript 查询(使用 qs 库构建):
## 示例:查找 ID 为 3、6、8 的多家餐厅 {#example-find-multiple-restaurants-with-ids-3-68}
🌐 Example: Find multiple restaurants with ids 3, 6,8
你可以使用 `$in` 过滤操作符配合一个值数组来查找多个精确值。
🌐 You can use the `$in` filter operator with an array of values to find multiple exact values.
JavaScript 查询(使用 qs 库构建):
## 复杂筛选 {#complex-filtering}
🌐 Complex filtering
复杂过滤是使用高级方法组合多个过滤器,例如结合 `$and` 和 `$or`。这允许更灵活地请求所需的精确数据。
🌐 Complex filtering is combining multiple filters using advanced methods such as combining `$and` & `$or`. This allows for more flexibility to request exactly the data needed.
JavaScript 查询(使用 qs 库构建):
## 深度过滤 {#deep-filtering}
🌐 Deep filtering
深度过滤是对关系的字段进行过滤。
🌐 Deep filtering is filtering on a relation's fields.
:::note
- 关系、媒体字段、组件和动态区域默认情况下未填充。使用 `populate` 参数来填充这些内容结构(参见 [`populate` 文档`](/cms/api/rest/populate-select#population))
- 你可以过滤填充的内容,也可以过滤嵌套关系,但不能对多态内容结构(例如媒体字段和动态区域)使用过滤器。
:::
:::caution
使用深层过滤器查询你的 API 可能会导致性能问题。如果其中一个深层过滤查询过慢,我们建议构建一个包含优化查询版本的自定义路由。
🌐 Querying your API with deep filters may cause performance issues. If one of your deep filtering queries is too slow, we recommend building a custom route with an optimized version of the query.
:::
JavaScript 查询(使用 qs 库构建):
# REST API 指南
Source: https://docs.strapi.io/cms/api/rest/guides/intro
# REST API 指南 {#rest-api-guides}
🌐 REST API Guides
[REST API 参考](/cms/api/rest) 文档旨在为所有可用的端点和参数提供快速参考。
🌐 The [REST API reference](/cms/api/rest) documentation is meant to provide a quick reference for all the endpoints and parameters available.
## 指南 {#guides}
🌐 Guides
以下指南由 Strapi 文档团队官方维护,涵盖专门主题并为某些用例提供详细说明(用 🧠 表示的指南)或分步说明(用 🛠️ 表示的指南):
🌐 The following guides, officially maintained by the Strapi Documentation team, cover dedicated topics and provide detailed explanations (guides indicated with 🧠) or step-by-step instructions (guides indicated with 🛠️) for some use cases:
## 附加资源 {#additional-resources}
🌐 Additional resources
:::strapi Want to help other users?
本节中列出的一些附加资源是为 Strapi v4 创建的,可能无法完全适用于 Strapi 5。如果你想将以下文章中的某一篇更新为适用于 Strapi 5,请随时 加入社区写作计划。
:::
其他教程和指南可以在以下博客文章中找到:
🌐 Additional tutorials and guides can be found in the following blog posts:
# 交互式查询构建器
Source: https://docs.strapi.io/cms/api/rest/interactive-query-builder
# 使用 Strapi 的交互式工具构建你的查询 URL {#build-your-query-url-with-strapis-interactive-tool}
🌐 Build your query URL with Strapi's interactive tool
可以使用并组合各种参数通过[REST API](/cms/api/rest)查询你的内容,这可能会导致长且复杂的查询URL。
🌐 A wide range of parameters can be used and combined to query your content with the [REST API](/cms/api/rest), which can result in long and complex query URLs.
Strapi 的代码库使用 来解析和序列化嵌套的 JavaScript 对象。建议直接使用 `qs` 来生成复杂的查询 URL,而不是手动创建它们。
🌐 Strapi's codebase uses to parse and stringify nested JavaScript objects. It's recommended to use `qs` directly to generate complex query URLs instead of creating them manually.
你可以使用以下交互式查询构建器工具自动生成查询 URL:
🌐 You can use the following interactive query builder tool to generate query URLs automatically:
1. 将 _Endpoint_ 和 _Endpoint Query Parameters_ 字段中的值替换为适合你需求的内容。
2. 点击 **复制到剪贴板** 按钮以复制自动生成的 _查询字符串 URL_,该 URL 会随着你输入而更新。
:::info Parameters usage
请参阅[REST API 参数表](/cms/api/rest/parameters)并阅读相应的参数文档页面,以更好地理解参数的使用。
🌐 Please refer to the [REST API parameters table](/cms/api/rest/parameters) and read the corresponding parameters documentation pages to better understand parameters usage.
:::
:::note
默认的端点路径以 `/api/` 为前缀,除非你使用 [ `rest.prefix` API 配置选项](/cms/configurations/api) 配置了不同的 API 前缀,否则应保持不变。 例如,要使用默认 API 前缀查询 `books` 集合类型,请在 _Endpoint_ 字段中输入 `/api/books`。
:::
:::caution Disclaimer
本页面提供的 `qs` 库和交互式查询构建器:
🌐 The `qs` library and the interactive query builder provided on this page:
- 可能无法检测到所有语法错误,
- 不知道 Strapi 项目中可用的参数和值,
- 并且不提供自动补齐功能。
目前,这些工具仅用于将 JavaScript 对象转换为内联查询字符串 URL。使用生成的查询 URL 并不保证你的 API 能返回正确的结果。
🌐 Currently, these tools are only provided to transform the JavaScript object in an inline query string URL. Using the generated query URL does not guarantee that proper results will get returned with your API.
:::
# 本地化
Source: https://docs.strapi.io/cms/api/rest/locale
# REST API:`locale` {#rest-api-locale}
🌐 REST API: `locale`
[国际化 (i18n) 功能](/cms/features/internationalization) 为 [REST API](/cms/api/rest) 添加了新功能。
🌐 The [Internationalization (i18n) feature](/cms/features/internationalization) adds new abilities to the [REST API](/cms/api/rest).
:::prerequisites
要使用某个区域设置的 API 内容,请确保该区域设置已在 Strapi 管理面板中 [添加](/cms/features/internationalization#settings)。
🌐 To work with API content for a locale, please ensure the locale has been already [added to Strapi in the admin panel](/cms/features/internationalization#settings).
:::
`locale` [API 参数](/cms/api/rest/parameters) 可用于仅处理特定语言环境的文档。`locale` 以语言环境代码作为值(见
### `GET` 获取特定语言环境中的所有文档 {#rest-get-all}
🌐 `GET` Get all documents in a specific locale
### `GET` 获取特定语言环境的文档 {#rest-get}
🌐 `GET` Get a document in a specific locale
要在指定的区域获取特定文档,请在查询中添加 `locale` 参数:
🌐 To get a specific document in a given locale, add the `locale` parameter to the query:
| 使用场景 | 语法格式及更多信息链接 || --- | --- || 在集合类型中 | [`GET /api/content-type-plural-name/document-id?locale=locale-code`](#get-one-collection-type) || 在单一类型中 | [`GET /api/content-type-singular-name?locale=locale-code`](#get-one-single-type) |
#### 集合类型 {#get-one-collection-type}
🌐 Collection types
要在给定语言环境中获取集合类型中的特定文档,请在 `documentId` 之后将 `locale` 参数添加到查询中:
🌐 To get a specific document in a collection type in a given locale, add the `locale` parameter to the query, after the `documentId`:
#### 单类型 {#get-one-single-type}
🌐 Single types
要在指定区域获取特定单一类型的文档,请在单一类型名称后将 `locale` 参数添加到查询中:
🌐 To get a specific single type document in a given locale, add the `locale` parameter to the query, after the single type name:
### `POST` 为集合类型创建新的本地化文档 {#rest-create}
🌐 `POST` Create a new localized document for a collection type
要从头创建本地化文档,请向内容 API 发送 POST 请求。根据你是要为默认语言创建文档还是为其他语言创建文档,你可能需要在查询中传递 `locale` 参数。
🌐 To create a localized document from scratch, send a POST request to the Content API. Depending on whether you want to create it for the default locale or for another locale, you might need to pass the `locale` parameter in the query.
| 使用案例 | 语法格式及更多信息链接 || --- | --- || 为默认语言创建 | [`POST /api/content-type-plural-name`](#rest-create-default-locale) || 为特定语言创建 | [`POST /api/content-type-plural-name?locale=fr`](#rest-create-specific-locale) |
#### 对于默认区域设置 {#rest-create-default-locale}
🌐 For the default locale
如果请求主体中未传递任何语言环境,则使用应用的默认语言环境创建文档:
🌐 If no locale has been passed in the request body, the document is created using the default locale for the application:
#### 针对特定区域 {#rest-create-specific-locale}
🌐 For a specific locale
要为与默认语言不同的语言环境创建本地化条目,请在 POST 请求的查询 URL 中添加 `locale` 参数:
🌐 To create a localized entry for a locale different from the default one, add the `locale` parameter to the query URL of the POST request:
### `PUT` 为现有文档创建新的本地化版本,或更新现有的本地化版本 {#rest-update}
🌐 `PUT` Create a new, or update an existing, locale version for an existing document
通过向现有文档发送 `PUT` 请求,你可以:
🌐 With `PUT` requests sent to an existing document, you can:
- 创建文档的另一个语言环境版本,
- 或更新文档的现有语言环境版本。
将 `PUT` 请求发送到相应的 URL,在查询 URL 中添加 `locale=your-locale-code` 参数,并在请求的主体中通过 `data` 对象传递属性:
🌐 Send the `PUT` request to the appropriate URL, adding the `locale=your-locale-code` parameter to the query URL and passing attributes in a `data` object in the request's body:
| 用例 | 语法格式及更多信息链接 || --- | --- || 在集合类型中 | [`PUT /api/content-type-plural-name/document-id?locale=locale-code`](#rest-put-collection-type) || 在单一类型中 | [`PUT /api/content-type-singular-name?locale=locale-code`](#rest-put-single-type) |
:::caution
为现有本地化条目创建本地化时,请求正文只能接受本地化字段。
🌐 When creating a localization for existing localized entries, the body of the request can only accept localized fields.
:::
:::tip
Content-Type 应启用 [`createLocalization` 权限](/cms/features/rbac#collection-and-single-types),否则请求将返回 `403: Forbidden` 状态。
🌐 The Content-Type should have the [`createLocalization` permission](/cms/features/rbac#collection-and-single-types) enabled, otherwise the request will return a `403: Forbidden` status.
:::
:::note
无法更改现有本地化条目的区域设置。更新本地化条目时,如果在请求正文中设置 `locale` 属性,该属性将被忽略。
🌐 It is not possible to change the locale of an existing localized entry. When updating a localized entry, if you set a `locale` attribute in the request body it will be ignored.
:::
#### 在集合类型 {#rest-put-collection-type} 中
🌐 In a collection type
要为集合类型中的现有文档创建新区域,本地化,请在 `documentId` 之后将 `locale` 参数添加到查询中,并将数据传递到请求的主体中:
🌐 To create a new locale for an existing document in a collection type, add the `locale` parameter to the query, after the `documentId`, and pass data to the request's body:
#### 在单一类型中 {#rest-put-single-type}
🌐 In a single type
要为现有的单类型文档创建新的本地化版本,请在单类型名称后将 `locale` 参数添加到查询中,并将数据传递到请求的主体中:
🌐 To create a new locale for an existing single type document, add the `locale` parameter to the query, after the single type name, and pass data to the request's body:
### `DELETE` 删除文档的某个语言版本 {#rest-delete}
🌐 `DELETE` Delete a locale version of a document
要删除文档的本地化版本,请发送带有适当 `locale` 参数的 `DELETE` 请求。
🌐 To delete a locale version of a document, send a `DELETE` request with the appropriate `locale` parameter.
`DELETE` 请求在成功时仅发送 204 HTTP 状态码,并且不会在响应体中返回任何数据。
#### 在集合类型 {#rest-delete-collection-type} 中
🌐 In a collection type
要仅删除集合类型中文档的特定语言版本,请在 `documentId` 之后将 `locale` 参数添加到查询中:
🌐 To delete only a specific locale version of a document in a collection type, add the `locale` parameter to the query after the `documentId`:
#### 在单一类型中 {#rest-delete-single-type}
🌐 In a single type
要仅删除单类型文档的特定语言版本,请在单类型名称后将 `locale` 参数添加到查询中:
🌐 To delete only a specific locale version of a single type document, add the `locale` parameter to the query after the single type name:
# 参数
Source: https://docs.strapi.io/cms/api/rest/parameters
# REST API 参数 {#rest-api-parameters}
🌐 REST API parameters
API 参数可以与 [REST API](/cms/api/rest) 一起使用,以筛选、排序和分页结果,并选择要填充的字段和关联。此外,还可以使用与可选 Strapi 功能相关的特定参数,例如内容类型的发布状态和语言环境。
🌐 API parameters can be used with the [REST API](/cms/api/rest) to filter, sort, and paginate results and to select fields and relations to populate. Additionally, specific parameters related to optional Strapi features can be used, like the publication state and locale of a content-type.
以下 API 参数可用:
🌐 The following API parameters are available:
| 运算符 | 类型 | 描述 || --- | --- | --- || `filters` | 对象 | [过滤响应](/cms/api/rest/filters) || `locale` | 字符串 | [选择一个区域设置](/cms/api/rest/locale) || `status` | 字符串 | [选择草稿和发布状态](/cms/api/rest/status) || `populate` | 字符串或对象 | [填充关联、组件或动态区域](/cms/api/rest/populate-select#population) || `fields` | 数组 | [仅选择要显示的特定字段](/cms/api/rest/populate-select#field-selection) || `sort` | 字符串或数组 | [对响应进行排序](/cms/api/rest/sort-pagination.md#sorting) || `pagination` | 对象 | [分页浏览条目](/cms/api/rest/sort-pagination.md#pagination) |
:::note
参数中的长括号编码列表(例如 `populate` 或 `fields`)受 [`arrayLimit` 在 `strapi::query`](/cms/configurations/middlewares#query) 的限制。参见 [Population](/cms/api/rest/populate-select#population)。
🌐 Long bracket-encoded lists in a parameter (for example `populate` or `fields`) are limited by [`arrayLimit` on `strapi::query`](/cms/configurations/middlewares#query). See [Population](/cms/api/rest/populate-select#population).
:::
查询参数使用 (即它们使用方括号 `[]` 编码)。
:::tip
可以使用和组合广泛的 REST API 参数来查询你的内容,这可能会导致长且复杂的查询 URL。 👉 你可以使用 Strapi 的[交互式查询构建器](/cms/api/rest/interactive-query-builder)工具更方便地构建查询 URL。🤗
:::
# 填充并选择
Source: https://docs.strapi.io/cms/api/rest/populate-select
# REST API:人口和字段选择 {#rest-api-population--field-selection}
🌐 REST API: Population & Field Selection
[REST API](/cms/api/rest) 默认不会填充任何关联、媒体字段、组件或动态区域。使用 [`populate` 参数](#population) 来填充特定字段。使用 [`fields` 参数](#field-selection) 仅返回查询结果中的特定字段。
🌐 The [REST API](/cms/api/rest) by default does not populate any relations, media fields, components, or dynamic zones. Use the [`populate` parameter](#population) to populate specific fields. Use the [`fields` parameter](#field-selection) to return only specific fields with the query results.
:::tip
## 人口 {#population}
🌐 Population
默认情况下,REST API 不会填充任何类型的字段,因此它不会填充关联、媒体字段、组件或动态区域,除非你传递一个 `populate` 参数来填充各种字段类型。已填充的关联总是返回完整对象;REST API 目前无法仅返回 ID 数组。
🌐 The REST API by default does not populate any type of fields, so it will not populate relations, media fields, components, or dynamic zones unless you pass a `populate` parameter to populate various field types. Populated relations always return full objects; the REST API currently cannot return just an array of IDs.
:::prerequisites
必须为正在填充的内容类型启用 `find` 权限。如果某个角色无法访问某个内容类型,则该内容类型将不会被填充(有关如何为内容类型启用 `find` 权限的更多信息,请参见 [用户与权限](/cms/features/users-permissions#editing-a-role))。
🌐 The `find` permission must be enabled for the content-types that are being populated. If a role does not have access to a content-type, the content-type will not be populated (see [Users & Permissions](/cms/features/users-permissions#editing-a-role) for additional information on how to enable `find` permissions for content-types).
:::
你可以单独使用 `populate` 参数,或[与多个操作符结合使用](#combining-population-with-other-operators)以更好地控制人口。
🌐 You can use the `populate` parameter alone or [in combination with multiple operators](#combining-population-with-other-operators) for more control over the population.
:::caution
`populate=deep` 插件在 Strapi 中 [不推荐使用](https://support.strapi.io/articles/8544110758-why-populate-deep-plugins-are-not-recommended-in-strapi)。
:::
:::note
查询字符串中的大型 `populate` 列表(许多 `populate[0]`、`populate[1]` 等条目)受到查询解析器 `arrayLimit` 的限制(默认值:`100`)。要允许更长的列表,请在 [`strapi::query` 中间件](/cms/configurations/middlewares#query) 上提高 `arrayLimit`。更高的值会增加每个请求的解析开销。
🌐 Large `populate` lists in the query string (many `populate[0]`, `populate[1]`, … entries) are bounded by the query parser `arrayLimit` (default: `100`). To allow a longer list, raise `arrayLimit` on the [`strapi::query` middleware](/cms/configurations/middlewares#query). Higher values increase parsing cost per request.
:::
下表列出了 populate 的用例及示例语法。每一行都链接到“理解 populate”指南以获取详细信息:
🌐 The following table lists populate use cases with example syntax. Each row links to the Understanding populate guide for details:
| 用例 | 参数示例语法 | 详细说明阅读 |
|-----------| ---|-----------------------|
| 填充所有内容,深度 1 级,包括媒体字段、关联、组件和动态区域 | `populate=*` | [填充所有关联和字段,深度 1 级](/cms/api/rest/guides/understanding-populate#populate-all-relations-and-fields-1-level-deep) |
| 填充一个关系, 深度为1 | `populate=a-relation-name`| [为特定关系填充1级深度](/cms/api/rest/guides/understanding-populate#populate-1-level-deep-for-specific-relations) |
| 填充多个关系, 1 级深 | `populate[0]=relation-name&populate[1]=another-relation-name&populate[2]=yet-another-relation-name`| [为特定关系填充 1 级深](/cms/api/rest/guides/understanding-populate#populate-1-level-deep-for-specific-relations) |
| 填充一些关系,几层深 | `populate[root-relation-name][populate][0]=nested-relation-name`| [为特定关系填充几层深](/cms/api/rest/guides/understanding-populate#populate-several-levels-deep-for-specific-relations) |
| 填充组件 | `populate[0]=component-name`| [填充组件](/cms/api/rest/guides/understanding-populate#populate-components) |
| 填充一个组件及其嵌套组件之一 | `populate[0]=component-name&populate[1]=component-name.nested-component-name`| [填充组件](/cms/api/rest/guides/understanding-populate#populate-components) |
| 填充动态区域(仅其第一级元素) | `populate[0]=dynamic-zone-name`| [填充动态区域](/cms/api/rest/guides/understanding-populate#populate-dynamic-zones) |
| 使用精确定义的详细填充策略填充动态区域及其嵌套元素和关系 | `populate[dynamic-zone-name][on][component-category.component-name][populate][relation-name][populate][0]=field-name` | [填充动态区域](/cms/api/rest/guides/understanding-populate#populate-dynamic-zones) |
:::tip
要构建具有多级填充的复杂查询,请使用 [交互式查询构建器](/cms/api/rest/interactive-query-builder) 工具。有关更详细的说明和示例,请参阅 [REST API 指南](/cms/api/rest/guides/intro)。
🌐 To build complex queries with multiple-level population, use the [interactive query builder](/cms/api/rest/interactive-query-builder) tool. For more detailed explanations and examples, see the [REST API guides](/cms/api/rest/guides/intro).
:::
### 将人口与其他操作符结合 {#combining-population-with-other-operators}
🌐 Combining population with other operators
你可以在填充查询中将 `populate` 操作符与其他操作符结合使用,例如 [字段选择](/cms/api/rest/populate-select#field-selection)、[过滤器](/cms/api/rest/filters) 和 [排序](/cms/api/rest/sort-pagination)。
🌐 You can combine the `populate` operator with other operators such as [field selection](/cms/api/rest/populate-select#field-selection), [filters](/cms/api/rest/filters), and [sort](/cms/api/rest/sort-pagination) in the population queries.
:::note
总体和分页运算符不能组合使用。
🌐 The population and pagination operators cannot be combined.
:::
#### 用字段选择填充 {#populate-with-field-selection}
🌐 Populate with field selection
`fields` 和 `populate` 可以结合。
#### 填充并筛选 {#populate-with-filtering}
🌐 Populate with filtering
`filters` 和 `populate` 可以结合。
# 关系
Source: https://docs.strapi.io/cms/api/rest/relations
# 管理与 API 请求的关系 {#managing-relations-with-api-requests}
🌐 Managing relations with API requests
定义内容类型(在数据库层中指定为实体)之间的关系是将实体相互连接起来。
🌐 Defining relations between content-types (that are designated as entities in the database layers) is connecting entities with each other.
内容类型之间的关系可以通过[管理面板](/cms/features/content-manager#relational-fields)或通过[REST API](/cms/api/rest)或[文档服务 API](/cms/api/document-service)请求进行管理。
🌐 Relations between content-types can be managed through the [admin panel](/cms/features/content-manager#relational-fields) or through [REST API](/cms/api/rest) or [Document Service API](/cms/api/document-service) requests.
关系可以通过内容 API 连接、断开或设置,只需在请求的主体中传递参数。这些有效负载适用于单条条目关系和多重关系(一对多、多对一、多对多及多向)。当关系字段允许多个链接时,API 需要关系 ID 的数组,并在响应中返回数组。
🌐 Relations can be connected, disconnected or set through the Content API by passing parameters in the body of the request. These payloads work for both single-entry relations and multi relations (one-to-many, many-to-one, many-to-many, and many-way). When a relational field allows multiple links, the API expects arrays of relation IDs and returns arrays in responses.
| 参数名称 | 描述 | 更新类型 ||-------------------------|-------------|----------------|| [`connect`](#connect) | 连接新实体。
不能与 `connect` 或 `disconnect` 一起使用。 | 完整 |
:::note
多重关系可以通过 REST API 和 [GraphQL API](/cms/api/graphql#fetch-relations) 管理:`connect`、`disconnect` 和 `set` 操作在两个 API 中均可用。然而,[文档服务 API](/cms/api/document-service) 不处理关系。
🌐 Multi relations can be managed from the REST API and the [GraphQL API](/cms/api/graphql#fetch-relations): the `connect`, `disconnect`, and `set` operations are available across both APIs. However, the [Document Service API](/cms/api/document-service) does not handle relations.
:::
:::note
当在内容类型上启用[国际化 (i18n)](/cms/features/internationalization)时,你还可以传递一个语言环境以为特定语言环境设置关系,如在此文档服务 API 示例中所示:
🌐 When [Internationalization (i18n)](/cms/features/internationalization) is enabled on the content-type, you can also pass a locale to set relations for a specific locale, as in this Document Service API example:
```js
await strapi.documents('api::restaurant.restaurant').update({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
locale: 'fr',
data: {
category: {
connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']
}
}
})
```
如果未传递任何语言环境,则将假定使用默认语言环境。
🌐 If no locale is passed, the default locale will be assumed.
:::
## `connect`
在请求体中使用 `connect` 会执行部分更新,连接指定的关系。
🌐 Using `connect` in the body of a request performs a partial update, connecting the specified relations.
`connect` 接受简写或长写语法:
| 语法类型 | 语法示例 || --- | ---------------- || 简写 | `connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']` || 全写 | ```connect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }]``` |
你也可以使用长格式语法来[重新排序关系](#relations-reordering)。
🌐 You can also use the longhand syntax to [reorder relations](#relations-reordering).
`connect` 可以与 [`disconnect`](#disconnect) 结合使用。
:::caution
`connect` 官方不支持媒体属性。高级用户在技术上可以通过定位上传的文件 ID 来连接媒体条目,但这种方法不被 Strapi 推荐或支持,并且很容易出错(例如,当草稿与发布使用不匹配的 ID 时)。请谨慎操作。
:::
### 关系重新排序 {#relations-reordering}
🌐 Relations reordering
省略 `position` 参数(如 `documentId: 'srkvrr77k96o44d9v6ef1vu9'`)默认为 `position: { end: true }`。所有其他关系都是相对于另一个已存在的 `id`(使用 `after` 或 `before`)或相对于关系列表(使用 `start` 或 `end`)定位的。操作按 `connect` 数组中定义的顺序依次处理,因此生成的数据库记录将如下所示:
🌐 Omitting the `position` argument (as in `documentId: 'srkvrr77k96o44d9v6ef1vu9'`) defaults to `position: { end: true }`. All other relations are positioned relative to another existing `id` (using `after` or `before`) or relative to the list of relations (using `start` or `end`). Operations are treated sequentially in the order defined in the `connect` array, so the resulting database record will be the following:
```js
categories: [
{ id: 'nyk7047azdgbtjqhl7btuxw' },
{ id: 'j9k8l7m6n5o4p3q2r1s0tuv' },
{ id: '6u86wkc6x3parjd4emikhmx6' },
{ id: '3r1wkvyjwv0b9b36s7hzpxl7' },
{ id: 'a1b2c3d4e5f6g7h8i9j0klm' },
{ id: 'rkyqa499i84197l29sbmwzl' },
{ id: 'srkvrr77k96o44d9v6ef1vu9' }
]
```
### 边缘情况:草稿与发布或国际化禁用 {#edge-cases-draft--publish-or-i18n-disabled}
🌐 Edge cases: Draft & Publish or i18n disabled
当 Strapi 5 的某些内置功能在内容类型中被禁用时,例如 [草稿与发布](/cms/features/draft-and-publish) 和 [国际化 (i18n)](/cms/features/internationalization),`connect` 参数可能会有不同的使用方式:
🌐 When some built-in features of Strapi 5 are disabled for a content-type, such as [Draft & Publish](/cms/features/draft-and-publish) and [Internationalization (i18)](/cms/features/internationalization), the `connect` parameter might be used differently:
**从 i18n _关闭_ 的 `Category` 到 i18n _开启_ 的 `Article` 的关系:**
在这种情况下,你可以选择要连接到哪个语言环境:
🌐 In this situation you can select which locale you are connecting to:
```js
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', locale: 'en' },
// Connect to the same document id but with a different locale 👇
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', locale: 'fr' },
]
}
}
```
**从 Draft & Publish _关闭_ 的 `Category` 到 Draft & Publish _开启_ 的 `Article` 的关系:**
```js
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', status: 'draft' },
// Connect to the same document id but with different publication states 👇
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', status: 'published' },
]
}
}
```
## `disconnect`
在请求的主体中使用 `disconnect` 会执行部分更新,断开指定的关联。
🌐 Using `disconnect` in the body of a request performs a partial update, disconnecting the specified relations.
`disconnect` 接受简写或长写语法:
| 语法类型 | 语法示例 || ---|----------------|| 简写 | `disconnect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']` || 全写 | ```disconnect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }]``` |
`disconnect` 可以与 [`connect`](#connect) 结合使用。
## `set`
使用 `set` 会执行完整更新,用指定的顺序用指定的关系替换所有现有关系。
🌐 Using `set` performs a full update, replacing all existing relations with the ones specified, in the order specified.
`set` 接受简写或长写语法:
| 语法类型 | 语法示例 || --- | --- || 简写 | `set: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']` || 全写 | ```set: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }]``` |
由于 `set` 会替换所有现有关系,因此不应与其他参数一起使用。要执行部分更新,请使用 [`connect`](#connect) 和 [`disconnect`](#disconnect)。
🌐 As `set` replaces all existing relations, it should not be used in combination with other parameters. To perform a partial update, use [`connect`](#connect) and [`disconnect`](#disconnect).
:::note Omitting set
省略任何参数等同于使用 `set`。 例如,以下三种语法都是等效的:
- `data: { categories: set: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] }}`
- `data: { categories: set: ['z0y2x4w6v8u1t3s5r7q9onm2', 'j9k8l7m6n5o4p3q2r1s0tuv'] }}`
- `data: { categories: ['z0y2x4w6v8u1t3s5r7q9onm2', 'j9k8l7m6n5o4p3q2r1s0tuv'] }`
:::
# 排序与分页
Source: https://docs.strapi.io/cms/api/rest/sort-pagination
# REST API:排序与分页 {#rest-api-sort--pagination}
🌐 REST API: Sort & Pagination
通过对 [REST API](/cms/api/rest) 的查询返回的条目可以进行排序和分页。
🌐 Entries that are returned by queries to the [REST API](/cms/api/rest) can be sorted and paginated.
:::tip
JavaScript 查询(使用 qs 库构建):
### 示例:使用两个字段排序并设置顺序 {#example-sort-using-2-fields-and-set-the-order}
🌐 Example: Sort using 2 fields and set the order
使用 `sort` 参数并在已排序的字段上定义 `:asc` 或 `:desc`,你可以获得按特定顺序排序的结果。
🌐 Using the `sort` parameter and defining `:asc` or `:desc` on sorted fields, you can get results sorted in a particular order.
JavaScript 查询(使用 qs 库构建):
## 分页 {#pagination}
🌐 Pagination
查询可以接受 `pagination` 参数。结果可以分页:
🌐 Queries can accept `pagination` parameters. Results can be paginated:
- 可以通过 [page](#pagination-by-page)(即,指定页码和每页条目数)
- 或者通过 [offset](#pagination-by-offset)(即指定要跳过多少条条目以及要返回多少条)
:::note
分页方法不能混合使用。始终要么使用 `page` 和 `pageSize`,**或者**使用 `start` 和 `limit`。
🌐 Pagination methods can not be mixed. Always use either `page` with `pageSize` **or** `start` with `limit`.
:::
### 按页分页 {#pagination-by-page}
🌐 Pagination by page
要按页对结果进行分页,请使用以下参数:
🌐 To paginate results by page, use the following parameters:
| 参数 | 类型 | 描述 | 默认值 || --- | --- | --- | --- || `pagination[page]` | 整数 | 页码 | 1 || `pagination[pageSize]` | 整数 | 每页数量 | 25 || `pagination[withCount]` | 布尔值 | 在响应中添加条目总数和页数 | True |
JavaScript 查询(使用 qs 库构建):
### 按偏移量分页 {#pagination-by-offset}
🌐 Pagination by offset
要按偏移量对结果进行分页,请使用以下参数:
🌐 To paginate results by offset, use the following parameters:
| 参数 | 类型 | 描述 | 默认值 || --- | --- | --- | --- || `pagination[start]` | 整数 | 起始值(即要返回的第一个条目) | 0 || `pagination[limit]` | 整数 | 要返回的条目数量 | 25 || `pagination[withCount]` | 布尔值 | 切换是否在响应中显示条目总数 | `true` |
:::tip
`pagination[limit]` 的默认值和最大值可以在 `/cms/configurations/api` 文件中的 `./config/api.js` 配置里通过 `api.rest.defaultLimit` 和 `api.rest.maxLimit` 键进行设置。
🌐 The default and maximum values for `pagination[limit]` can be [configured in the `./config/api.js`](/cms/configurations/api) file with the `api.rest.defaultLimit` and `api.rest.maxLimit` keys.
:::
JavaScript 查询(使用 qs 库构建):
# 状态
Source: https://docs.strapi.io/cms/api/rest/status
# REST API:`status` {#rest-api-status}
🌐 REST API: `status`
[REST API](/cms/api/rest) 提供根据状态(草稿或已发布)过滤结果的功能。
🌐 The [REST API](/cms/api/rest) offers the ability to filter results based on their status, draft or published.
:::prerequisites
应该启用 [Draft & Publish](/cms/features/draft-and-publish) 功能。
🌐 The [Draft & Publish](/cms/features/draft-and-publish) feature should be enabled.
:::
查询可以接受一个 `status` 参数以根据其状态获取文档:
🌐 Queries can accept a `status` parameter to fetch documents based on their status:
- `published`:仅返回文档的已发布版本(默认)
- `draft`:仅返回文档的草稿版本
:::tip
在响应数据中,`publishedAt` 字段对于草稿来说是 `null`。
🌐 In the response data, the `publishedAt` field is `null` for drafts.
:::
:::note
由于默认返回已发布版本,因此不传递状态参数等同于传递 `status=published`。
🌐 Since published versions are returned by default, passing no status parameter is equivalent to passing `status=published`.
:::
JavaScript 查询(使用 qs 库构建):
# 上传文件
Source: https://docs.strapi.io/cms/api/rest/upload
# REST API:上传文件 {#rest-api-upload-files}
🌐 REST API: Upload files
[媒体库功能](/cms/features/media-library) 在 Strapi 的后端服务器中由 `upload` 包提供支持。要向 Strapi 上传文件,你可以直接从管理面板使用媒体库,也可以使用 [REST API](/cms/api/rest),可用的端点如下:
🌐 The [Media Library feature](/cms/features/media-library) is powered in the back-end server of Strapi by the `upload` package. To upload files to Strapi, you can either use the Media Library directly from the admin panel, or use the [REST API](/cms/api/rest), with the following available endpoints :
| 方法 | 路径 | 描述 || :----- | :---------------------- | :------------------ || GET | `/api/upload/files` | 获取文件列表 || GET | `/api/upload/files/:id` | 获取特定文件 || POST | `/api/upload` | 上传文件 || POST | `/api/upload?id=x` | 更新文件信息 || DELETE | `/api/upload/files/:id` | 删除文件 |
:::note Notes
- [文件夹](/cms/features/media-library#organizing-assets-with-folders) 是仅限管理员面板的功能,不属于内容 API(REST 或 GraphQL)。通过 REST 上传的文件位于自动创建的“API 上传”文件夹中。
- GraphQL API 不支持上传媒体文件。要上传文件,请使用 REST API 或直接从管理面板的 [媒体库](/cms/features/media-library) 添加文件。一些用于更新或删除已上传媒体文件的 GraphQL 变更仍然可能(详情请参见 [GraphQL API 文档](/cms/api/graphql#mutations-on-media-files))。
:::
## 上传文件 {#upload-files}
🌐 Upload files
将一个或多个文件上传到你的应用。
🌐 Upload one or more files to your application.
`files` 是唯一接受的参数,用于描述要上传的文件。其值可以是 Buffer 或 Stream。
:::tip
上传图片时,包含一个 `fileInfo` 对象以设置文件名、替代文本和标题。
🌐 When uploading an image, include a `fileInfo` object to set the file name, alt text, and caption.
:::
:::caution
你必须在请求正文中发送 FormData。
🌐 You have to send FormData in your request body.
:::
## 上传入口文件 {#upload-entry-files}
🌐 Upload entry files
上传一个或多个将链接到特定条目的文件。
🌐 Upload one or more files that will be linked to a specific entry.
接受以下参数:
🌐 The following parameters are accepted:
| 参数 | 描述 || --- | --- ||`files` | 要上传的文件。值可以是 Buffer 或 Stream。 ||`path` (可选) | 文件将上传到的文件夹(仅在 strapi-provider-upload-aws-s3 上支持)。 || `refId` | 将与文件关联的条目 ID。 || `ref` | 文件将关联的模型的唯一 ID(uid)(详见下文)。 || `source` (可选) | 模型所在插件的名称。 || `field` | 文件将精确关联到的条目字段。 |
例如,给定 `Restaurant` 模型属性:
🌐 For example, given the `Restaurant` model attributes:
```json title="/src/api/restaurant/content-types/restaurant/schema.json"
{
// ...
"attributes": {
"name": {
"type": "string"
},
"cover": {
"type": "media",
"multiple": false,
}
}
// ...
}
```
以下是相应前端的示例代码:
🌐 The following is an example of a corresponding front-end code:
```html
```
:::caution
你必须在请求正文中发送 FormData。
🌐 You have to send FormData in your request body.
:::
## 更新文件信息 {#update-fileinfo}
🌐 Update fileInfo
更新应用中的文件。
🌐 Update a file in your application.
`fileInfo` 是唯一被接受的参数,用于描述要更新的文件信息:
```js
const fileId = 50;
const newFileData = {
alternativeText: 'My new alternative text for this image!',
};
const form = new FormData();
form.append('fileInfo', JSON.stringify(newFileData));
const response = await fetch(`http://localhost:1337/api/upload?id=${fileId}`, {
method: 'post',
body: form,
});
```
## 模型定义 {#models-definition}
🌐 Models definition
向[模型](/cms/backend-customization/models)(或另一个插件的模型)添加文件属性就像添加一个新的关联。
🌐 Adding a file attribute to a [model](/cms/backend-customization/models) (or the model of another plugin) is like adding a new association.
以下示例允许你上传并附加一个文件到 `avatar` 属性:
🌐 The following example lets you upload and attach one file to the `avatar` attribute:
```json title="/src/api/restaurant/content-types/restaurant/schema.json"
{
// ...
{
"attributes": {
"pseudo": {
"type": "string",
"required": true
},
"email": {
"type": "email",
"required": true,
"unique": true
},
"avatar": {
"type": "media",
"multiple": false,
}
}
}
// ...
}
```
以下示例允许你上传并附加多张图片到 `restaurant` 内容类型:
🌐 The following example lets you upload and attach multiple pictures to the `restaurant` content-type:
```json title="/src/api/restaurant/content-types/restaurant/schema.json"
{
// ...
{
"attributes": {
"name": {
"type": "string",
"required": true
},
"covers": {
"type": "media",
"multiple": true,
}
}
}
// ...
}
```
# 后端定制
Source: https://docs.strapi.io/cms/backend-customization
# 后端自定义
:::strapi Disambiguation: Strapi back end
作为一个无头 CMS,Strapi 软件整体上可以被视为你网站或应用的“后端”。
但 Strapi 软件本身包含两个不同的部分:
🌐 As a headless CMS, the Strapi software as a whole can be considered as the "back end" of your website or application.
But the Strapi software itself includes 2 different parts:
- Strapi 的 **后端** 部分是 Strapi 运行的一个 HTTP 服务器。像任何 HTTP 服务器一样,Strapi 后端接收请求并发送响应。你的内容存储在数据库中,Strapi 后端与数据库交互以创建、检索、更新和删除内容。
- Strapi 的 **前端** 部分称为管理面板。管理面板提供图形用户界面,帮助你组织和管理内容。
在整个开发者文档中,“后端”专指 Strapi 的后端部分。
🌐 Throughout this developer documentation, 'back end' refers _exclusively_ to the back-end part of Strapi.
[入门 > 管理员面板页面](/cms/features/admin-panel) 提供了管理员面板的概览,[管理员面板自定义部分](/cms/admin-panel-customization) 详细说明了管理员面板可用的各种自定义选项。
🌐 The [Getting Started > Admin panel page](/cms/features/admin-panel) gives an admin panel overview and the [admin panel customization section](/cms/admin-panel-customization) details the various customization options available for the admin panel.
:::
Strapi 后端运行一个基于 的 HTTP 服务器, 是一个后端 JavaScript 框架。
像任何 HTTP 服务器一样,Strapi 后端接收请求并发送响应。你可以通过 [REST](/cms/api/rest) 或 [GraphQL](/cms/api/graphql) API 向 Strapi 后端发送请求,以创建、检索、更新或删除数据。
🌐 Like any HTTP server, the Strapi back end receives requests and send responses. You can send requests to the Strapi back end to create, retrieve, update, or delete data through the [REST](/cms/api/rest) or [GraphQL](/cms/api/graphql) APIs.
请求可以通过 Strapi 后端传输,如下所示:
🌐 A request can travel through the Strapi back end as follows:
1. Strapi 服务器接收一个 [请求](/cms/backend-customization/requests-responses)。
2. 请求会触发按顺序运行的[全局中间件](/cms/backend-customization/middlewares)。
3. 该请求访问了一个[路由](/cms/backend-customization/routes)。 默认情况下,Strapi 会为你创建的所有内容类型生成路由文件(参见[REST API 文档](/cms/api/rest)),并且可以添加和配置更多路由。
4. [路由策略](/cms/backend-customization/policies) 充当只读的验证步骤,可以阻止访问某条路由。[路由中间件](/cms/backend-customization/routes#middlewares) 可以控制请求流程,并在继续之前修改请求本身。
5. [控制器](/cms/backend-customization/controllers) 在路由被访问后执行代码。[服务](/cms/backend-customization/services) 是可选的附加代码,可用于构建可被控制器重复使用的自定义逻辑。
6. 控制器和服务执行的代码与[模型](/cms/backend-customization/models)交互,这些模型是存储在数据库中的内容结构的表示形式。 通过模型表示的数据的交互由[文档服务](/cms/api/document-service)和[查询引擎](/cms/api/query-engine)处理。
7. 你可以实现 [文档服务中间件](/cms/api/document-service/middlewares) 来在数据发送到查询引擎之前进行控制。查询引擎也可以使用生命周期钩子,不过我们建议你使用文档服务中间件,除非你确实需要直接与数据库交互。
7. 服务器返回一个 [响应](/cms/backend-customization/requests-responses)。响应可以在发送之前通过路由中间件和全局中间件返回。
全局和路由中间件都包含一个异步回调函数 `await next()`。根据中间件返回的内容,请求将在后端走一条较短或较长的路径:
🌐 Both global and route middlewares include an asynchronous callback function, `await next()`. Depending on what is returned by the middleware, the request will either go through a shorter or longer path through the back end:
* 如果中间件不返回任何内容,则请求将继续穿过后端的各个核心元素(即控制器、服务以及与数据库交互的其他层)。
* 如果中间件在调用 `await next()` 之前返回,将会立即发送响应,跳过其余的核心元素。然后,它将沿着原路返回同一条链。
:::info
请注意,本节页面中描述的所有自定义仅适用于 REST API。[GraphQL 自定义](/cms/plugins/graphql#customization) 在 GraphQL 插件文档中描述。
🌐 Please note that all customizations described in the pages of this section are only for the REST API. [GraphQL customizations](/cms/plugins/graphql#customization) are described in the GraphQL plugin documentation.
:::
## 交互式图表 {#interactive-diagram}
🌐 Interactive diagram
下图展示了请求如何通过 Strapi 后端传输。你可以点击任意形状跳转到文档中的相关页面。
🌐 The following diagram represents how requests travel through the Strapi back end. You can click on any shape to jump to the relevant page in the documentation.
# 控制器
Source: https://docs.strapi.io/cms/backend-customization/controllers
# 控制器 {#controllers}
🌐 Controllers
控制器是包含一组方法(称为动作)的 JavaScript 文件,客户端可以根据请求的[路由](/cms/backend-customization/routes)访问这些方法。每当客户端请求该路由时,动作会执行业务逻辑代码并返回[响应](/cms/backend-customization/requests-responses)。控制器代表模型-视图-控制器(MVC)模式中的 C。
🌐 Controllers are JavaScript files that contain a set of methods, called actions, reached by the client according to the requested [route](/cms/backend-customization/routes). Whenever a client requests the route, the action performs the business logic code and sends back the [response](/cms/backend-customization/requests-responses). Controllers represent the C in the model-view-controller (MVC) pattern.
在大多数情况下,控制器将包含项目大部分的业务逻辑。但随着控制器的逻辑变得越来越复杂,使用[服务](/cms/backend-customization/services)将代码组织成可重用的部分是一种好习惯。
🌐 In most cases, the controllers will contain the bulk of a project's business logic. But as a controller's logic becomes more and more complicated, it's a good practice to use [services](/cms/backend-customization/services) to organize the code into re-usable parts.
该图表示请求在 Strapi 后端传递的简化版本,控制器被高亮。后端自定义介绍页面包含一个完整的, 交互式图表。
:::caution Sanitize inputs and outputs
在重写核心操作时,始终验证和清理查询和响应,以避免泄露私有字段或绕过访问规则。在从自定义操作返回数据之前,使用 `validateQuery`(可选)、`sanitizeQuery`(推荐)和 `sanitizeOutput`。请参见下面的示例,了解安全的 `find` 重写。
🌐 When overriding core actions, always validate and sanitize queries and responses to avoid leaking private fields or bypassing access rules. Use `validateQuery` (optional), `sanitizeQuery` (recommended), and `sanitizeOutput` before returning data from custom actions. See the example below for a safe `find` override.
:::
## 实现 {#implementation}
🌐 Implementation
控制器可以[生成或手动添加](#adding-a-new-controller)。Strapi 提供了一个 `createCoreController` 工厂函数,可以自动生成核心控制器,并允许构建自定义控制器或[扩展或替换生成的控制器](#extending-core-controllers)。
🌐 Controllers can be [generated or added manually](#adding-a-new-controller). Strapi provides a `createCoreController` factory function that automatically generates core controllers and allows building custom ones or [extend or replace the generated controllers](#extending-core-controllers).
### 添加新控制器 {#adding-a-new-controller}
🌐 Adding a new controller
可以实现一个新的控制器:
🌐 A new controller can be implemented:
- 使用 [交互式 CLI 命令 `strapi generate`](/cms/cli)
- 或通过创建 JavaScript 文件手动:
- 在 `./src/api/[api-name]/controllers/` 中用于 API 控制器(此位置很重要,因为 Strapi 会从这里自动加载控制器)
- 或者在像 `./src/plugins/[plugin-name]/server/controllers/` 这样的文件夹中用于插件控制器,尽管它们可以创建在其他地方,只要插件接口在 `strapi-server.js` 文件中正确导出(参见 [插件的服务器 API 文档](/cms/plugins-development/server-api))
每个控制器动作可以是 `async` 或 `sync` 函数。每个动作都接收一个上下文对象(`ctx`)作为参数。`ctx` 包含 [请求上下文](/cms/backend-customization/requests-responses#ctxrequest) 和 [响应上下文](/cms/backend-customization/requests-responses#ctxresponse)。
🌐 Each controller action can be an `async` or `sync` function.
Every action receives a context object (`ctx`) as a parameter. `ctx` contains the [request context](/cms/backend-customization/requests-responses#ctxrequest) and the [response context](/cms/backend-customization/requests-responses#ctxresponse).
示例:GET /hello 路由调用一个基本控制器
定义了一个特定的 `GET /hello` [路由](/cms/backend-customization/routes),路由文件的名称(即 `index`)用于调用控制器处理程序(即 `index`)。每次向服务器发送 `GET /hello` 请求时,Strapi 会在 `hello.js` 控制器中调用 `index` 操作,并返回 `Hello World!`:
🌐 A specific `GET /hello` [route](/cms/backend-customization/routes) is defined, the name of the router file (i.e. `index`) is used to call the controller handler (i.e. `index`). Every time a `GET /hello` request is sent to the server, Strapi calls the `index` action in the `hello.js` controller, which returns `Hello World!`:
:::note
当创建一个新的 [内容类型](/cms/backend-customization/models#content-types) 时,Strapi 会生成一个带有占位代码的通用控制器,准备进行自定义。
🌐 When a new [content-type](/cms/backend-customization/models#content-types) is created, Strapi builds a generic controller with placeholder code, ready to be customized.
:::
:::tip
要了解自定义控制器可能的高级用法,请阅读后端自定义示例手册的 [服务和控制器](/cms/backend-customization/examples/services-and-controllers) 页面。
🌐 To see a possible advanced usage for custom controllers, read the [services and controllers](/cms/backend-customization/examples/services-and-controllers) page of the backend customization examples cookbook.
:::
### 控制器与路由:路由如何到达控制器动作 {#controllers--routes-how-routes-reach-controller-actions}
🌐 Controllers & Routes: How routes reach controller actions
- 核心映射是自动补齐的:当你生成一个内容类型时,Strapi 会创建匹配的控制器和一个已经针对标准操作(`find`、`findOne`、`create`、`update` 和 `delete`)的路由文件。在生成的控制器中覆盖这些操作中的任何一个不需要修改路由——路由保持相同的处理程序字符串并执行你更新后的逻辑。
- 添加路由应仅针对新的操作或路径进行。如果引入一个全新的方法,例如 `exampleAction`,则创建或更新一个路由条目,其 `handler` 指向该操作,以便 HTTP 请求可以访问它。使用完整限定的处理程序语法 `::..`(例如 API 控制器的 `api::restaurant.restaurant.exampleAction` 或插件控制器的 `plugin::menus.menu.exampleAction`)。
- 关于控制器和路由文件名:默认的控制器名称来自 `./src/api/[api-name]/controllers/` 中的文件名。使用 `createCoreRouter` 创建的核心路由采用相同的名称,因此生成的处理程序字符串会自动匹配。自定义路由可以遵循任何文件命名方案,只要 `handler` 字符串引用一个导出的控制器操作。
以下示例添加了一个新的控制器操作,并通过自定义路由将其公开,而不会重复现有的 CRUD 路由定义:
🌐 The example below adds a new controller action and exposes it through a custom route without duplicating the existing CRUD route definitions:
```js title="./src/api/restaurant/controllers/restaurant.js"
const { createCoreController } = require('@strapi/strapi').factories;
module.exports = createCoreController('api::restaurant.restaurant', ({ strapi }) => ({
async exampleAction(ctx) {
const specials = await strapi.service('api::restaurant.restaurant').find({ filters: { isSpecial: true } });
return this.transformResponse(specials.results);
},
}));
```
```js title="./src/api/restaurant/routes/01-custom-restaurant.js"
module.exports = {
routes: [
{
method: 'GET',
path: '/restaurants/specials',
handler: 'api::restaurant.restaurant.exampleAction',
},
],
};
```
### 控制器中的清理和验证 {#sanitization-and-validation-in-controllers}
🌐 Sanitization and Validation in controllers
:::warning
强烈建议你使用新的 `sanitizeQuery` 和 `validateQuery` 函数对传入的请求查询进行消毒(v4.8.0+)和/或验证(v4.13.0+),以防止私有数据泄露。
🌐 It's strongly recommended you sanitize (v4.8.0+) and/or validate (v4.13.0+) your incoming request query utilizing the new `sanitizeQuery` and `validateQuery` functions to prevent the leaking of private data.
:::
清理意味着对象被“清理”并返回。
🌐 Sanitization means that the object is “cleaned” and returned.
验证意味着断言数据已经干净,如果发现不应该存在的内容,则会引发错误。
🌐 Validation means an assertion is made that the data is already clean and throws an error if something is found that shouldn't be there.
在 Strapi 5 中,查询参数和输入数据(即创建和更新的请求体数据)都会被验证。任何包含以下无效输入的创建和更新数据请求都会抛出 `400 Bad Request` 错误:
🌐 In Strapi 5, both query parameters and input data (i.e., create and update body data) are validated. Any create and update data requests with the following invalid input will throw a `400 Bad Request` error:
- 用户无权创建的关系
- 模式中不存在的无法识别的值
- 不可写字段和内部时间戳,如 `createdAt` 和 `createdBy` 字段
- 设置或更新 `id` 字段(连接关系除外)
#### 使用控制器工厂时的消毒 {#sanitization-when-utilizing-controller-factories}
🌐 Sanitization when utilizing controller factories
在 Strapi 工厂中,公开了以下可用于清理和验证的函数:
🌐 Within the Strapi factories the following functions are exposed that can be used for sanitization and validation:
| 函数名称 | 参数 | 描述 ||------------------|----------------------------|--------------------------------------------------------------------------------------|| `sanitizeQuery` | `ctx` | 清理请求查询 || `sanitizeOutput` | `entity`/`entities`, `ctx` | 清理输出数据,其中实体/实体集合应为对象或数据数组 || `sanitizeInput` | `data`, `ctx` | 清理输入数据 || `validateQuery` | `ctx` | 验证请求查询(在参数无效时抛出错误) || `validateInput` | `data`, `ctx` | (实验性)验证输入数据(在数据无效时抛出错误) |
这些函数自动从模型继承清理设置,并根据内容类型架构和任何内容 API 身份验证策略(例如用户和权限插件或 API 令牌)相应地清理数据。
🌐 These functions automatically inherit the sanitization settings from the model and sanitize the data accordingly based on the content-type schema and any of the content API authentication strategies, such as the Users & Permissions plugin or API tokens.
:::warning
因为这些方法使用的是与当前控制器关联的模型,如果你查询的数据来自另一个模型(例如,在“restaurant”控制器方法中查找“menus”),你必须改为使用 `strapi.contentAPI` 方法,例如在 [Sanitizing Custom Controllers](#sanitize-validate-custom-controllers) 中描述的 `strapi.contentAPI.sanitize.query`,否则你的查询结果将会被错误的模型进行清理。
🌐 Because these methods use the model associated with the current controller, if you query data that is from another model (i.e., doing a find for "menus" within a "restaurant" controller method), you must instead use the `strapi.contentAPI` methods, such as `strapi.contentAPI.sanitize.query` described in [Sanitizing Custom Controllers](#sanitize-validate-custom-controllers), or else the result of your query will be sanitized against the wrong model.
:::
#### 构建自定义控制器时的清理和验证 {#sanitize-validate-custom-controllers}
🌐 Sanitization and validation when building custom controllers
在自定义控制器中,Strapi 通过 `strapi.contentAPI` 提供以下用于清理和验证的函数。要向内容 API 路由(例如在 `register` 中)添加自定义查询或请求体参数,请参见 [自定义内容 API 参数](/cms/backend-customization/routes#custom-content-api-parameters)。
🌐 Within custom controllers, Strapi exposes the following functions via `strapi.contentAPI` for sanitization and validation. To add custom query or body parameters to Content API routes (e.g. in `register`), see [Custom Content API parameters](/cms/backend-customization/routes#custom-content-api-parameters).
| 函数名 | 参数 | 描述 |
|------------------------------|--------------------|---------------------------------------------------------|
| `strapi.contentAPI.sanitize.input` | `data`,`schema`,`auth` | 清理请求输入,包括不可写字段,移除受限制的关系,以及其他由插件添加的嵌套“访问者” |
| `strapi.contentAPI.sanitize.output` | `data`、`schema`、`auth` | 清理响应输出,包括受限制的关系、私有字段、密码以及插件添加的其他嵌套“访问者” |
| `strapi.contentAPI.sanitize.query` | `ctx.query`、`schema`、`auth` | 清理请求查询,包括过滤器、排序、字段和填充 |
| `strapi.contentAPI.validate.query` | `ctx.query`、`schema`、`auth` | 验证请求查询,包括过滤器、排序、字段(当前未填充) |
| `strapi.contentAPI.validate.input` | `data`、`schema`、`auth` |(实验性)验证请求输入,包括不可写字段、移除受限关系,以及插件添加的其他嵌套“访问器”|
:::note
根据自定义控制器的复杂性,你可能需要 Strapi 目前无法考虑的额外清理,尤其是在组合多个来源的数据时。
🌐 Depending on the complexity of your custom controllers, you may need additional sanitization that Strapi cannot currently account for, especially when combining the data from multiple sources.
:::
### 扩展核心控制器 {#extending-core-controllers}
🌐 Extending core controllers
每种内容类型都会创建默认的控制器和操作。这些默认控制器用于响应 API 请求(例如,当访问 `GET /api/articles/3` 时,会调用 “Article” 内容类型默认控制器的 `findOne` 操作)。默认控制器可以自定义以实现你自己的逻辑。以下代码示例应能帮助你入门。
🌐 Default controllers and actions are created for each content-type. These default controllers are used to return responses to API requests (e.g. when `GET /api/articles/3` is accessed, the `findOne` action of the default controller for the "Article" content-type is called). Default controllers can be customized to implement your own logic. The following code examples should help you get started.
:::tip
核心控制器的一个操作可以完全通过[创建自定义操作](#adding-a-new-controller)来替换,并将该操作命名为与原操作相同的名称(例如 `find`、`findOne`、`create`、`update` 或 `delete`)。
🌐 An action from a core controller can be replaced entirely by [creating a custom action](#adding-a-new-controller) and naming the action the same as the original action (e.g. `find`, `findOne`, `create`, `update`, or `delete`).
:::
:::tip
在扩展核心控制器时,你无需重新实现任何清理功能,因为这些功能已经由你扩展的核心控制器处理。尽可能强烈建议扩展核心控制器,而不是创建自定义控制器。
🌐 When extending a core controller, you do not need to re-implement any sanitization as it will already be handled by the core controller you are extending. Where possible it's strongly recommended to extend the core controller instead of creating a custom controller.
:::
集合类型示例
:::tip
[后端自定义示例手册](/cms/backend-customization/examples)展示了如何覆盖默认的控制器操作,例如针对[`create`操作](/cms/backend-customization/examples/services-and-controllers#custom-controller)。
🌐 The [backend customization examples cookbook](/cms/backend-customization/examples) shows how you can overwrite a default controller action, for instance for the [`create` action](/cms/backend-customization/examples/services-and-controllers#custom-controller).
:::
单类型示例
## 使用 {#usage}
🌐 Usage
控制器被声明并附加到一个路由上。当路由被调用时,控制器会自动被调用,因此通常不需要显式调用控制器。但是,[服务](/cms/backend-customization/services) 可以调用控制器,在这种情况下应使用以下语法:
🌐 Controllers are declared and attached to a route. Controllers are automatically called when the route is called, so controllers usually do not need to be called explicitly. However, [services](/cms/backend-customization/services) can call controllers, and in this case the following syntax should be used:
```js
// access an API controller
strapi.controller('api::api-name.controller-name');
// access a plugin controller
strapi.controller('plugin::plugin-name.controller-name');
```
:::tip
要列出所有可用的控制器,请运行 `yarn strapi controllers:list`。
🌐 To list all the available controllers, run `yarn strapi controllers:list`.
:::
# 中间件
Source: https://docs.strapi.io/cms/backend-customization/middlewares
# 中间件定制 {#middlewares-customization}
🌐 Middlewares customization
全局作用域的自定义中间件应该添加到 [中间件配置文件](/cms/configurations/middlewares#loading-order),否则 Strapi 将无法加载它们。
🌐 Globally scoped custom middlewares should be added to the [middlewares configuration file](/cms/configurations/middlewares#loading-order) or Strapi won't load them.
API 级别和插件中间件可以添加到与其相关的特定路由中,如下所示:
🌐 API level and plugin middlewares can be added into the specific router that they are relevant to like the following:
```js title="./src/api/[api-name]/routes/[collection-name].js or ./src/plugins/[plugin-name]/server/routes/index.js"
module.exports = {
routes: [
{
method: "GET",
path: "/[collection-name]",
handler: "[controller].find",
config: {
middlewares: ["[middleware-name]"],
// See the usage section below for middleware naming conventions
},
},
],
};
```
自定义计时器中间件示例
GraphQL 插件还允许[实现自定义中间件](/cms/plugins/graphql#middlewares),语法有所不同。
🌐 The GraphQL plugin also allows [implementing custom middlewares](/cms/plugins/graphql#middlewares), with a different syntax.
:::tip Discover loaded middlewares
运行 `yarn strapi middlewares:list` 列出所有已注册的中间件,并在将它们连接到路由时仔细检查名称。
🌐 Run `yarn strapi middlewares:list` to list all registered middlewares and double‑check naming when wiring them in routers.
:::
## 使用 {#usage}
🌐 Usage
中间件根据其范围有不同的调用方式:
🌐 Middlewares are called different ways depending on their scope:
- 在应用级中间件中使用 `global::middleware-name`
- 使用 `api::api-name.middleware-name` 进行 API 级中间件
- 使用 `plugin::plugin-name.middleware-name` 作为插件中间件
:::tip
要列出所有已注册的中间件,运行 `yarn strapi middlewares:list`。
🌐 To list all the registered middlewares, run `yarn strapi middlewares:list`.
:::
### 使用“是所有者策略”限制内容访问 {#restricting-content-access-with-an-is-owner-policy}
🌐 Restricting content access with an "is-owner policy"
通常要求条目的作者是唯一被允许编辑或删除该条目的用户。在 Strapi 的早期版本中,这被称为“is-owner 策略”。在 Strapi v4 中,实现此行为的推荐方式是使用中间件。
🌐 It is often required that the author of an entry is the only user allowed to edit or delete the entry. In previous versions of Strapi, this was known as an "is-owner policy". With Strapi v4, the recommended way to achieve this behavior is to use a middleware.
正确的实现很大程度上取决于你的项目的需求和自定义代码,但最基本的实现可以通过以下过程来实现:
🌐 Proper implementation largely depends on your project's needs and custom code, but the most basic implementation could be achieved with the following procedure:
1. 在你的项目文件夹中,通过在终端运行 `yarn strapi generate`(或 `npm run strapi generate`)命令,使用 Strapi CLI 生成器创建一个中间件。
2. 使用键盘箭头从列表中选择 `middleware`,然后按回车键。
3. 给中间件起一个名字,例如 `isOwner`。
4. 从列表中选择 `Add middleware to an existing API`。
5. 选择你希望中间件应用哪个 API。
6. 将 `/src/api/[your-api-name]/middlewares/isOwner.js` 文件中的代码替换为以下内容,并在第 22 行将 `api::restaurant.restaurant` 替换为你在第 5 步选择的 API 对应的标识符(例如,如果你的 API 名称是 `blog-post`,则替换为 `api::blog-post.blog-post`):
```js showLineNumbers title="src/api/blog-post/middlewares/isOwner.js"
"use strict";
/**
* `isOwner` middleware
*/
module.exports = (config, { strapi }) => {
// Add your own logic here.
return async (ctx, next) => {
const user = ctx.state.user;
const entryId = ctx.params.id ? ctx.params.id : undefined;
let entry = {};
/**
* Gets all information about a given entry,
* populating every relations to ensure
* the response includes author-related information
*/
if (entryId) {
entry = await strapi.documents('api::restaurant.restaurant').findOne(
entryId,
{ populate: "*" }
);
}
/**
* Compares user id and entry author id
* to decide whether the request can be fulfilled
* by going forward in the Strapi backend server
*/
if (user.id !== entry.author.id) {
return ctx.unauthorized("This action is unauthorized.");
} else {
return next();
}
};
};
```
7. 确保中间件配置应用于某些路由。在 `src/api/[your-api–name]/routes/[your-content-type-name].js` 文件中找到的 `config` 对象中,定义你希望中间件应用的动作键(`find`、`findOne`、`create`、`update`、`delete` 等),并为这些路由声明 `isOwner` 中间件。
例如,如果你希望允许 GET 请求(对应 `find` 和 `findOne` 动作)和 POST 请求(即 `create` 动作)对任何用户在 `restaurant` API 中的 `restaurant` 内容类型生效,但希望将 PUT(即 `update` 动作)和 DELETE 请求限制为仅对创建该条目的用户生效,你可以在 `src/api/restaurant/routes/restaurant.js` 文件中使用以下代码:
```js title="src/api/restaurant/routes/restaurant.js"
/**
* restaurant router
*/
const { createCoreRouter } = require("@strapi/strapi").factories;
module.exports = createCoreRouter("api::restaurant.restaurant", {
config: {
update: {
middlewares: ["api::restaurant.is-owner"],
},
delete: {
middlewares: ["api::restaurant.is-owner"],
},
},
});
```
:::info
你可以在 [路由文档](/cms/backend-customization/routes) 中找到有关路由中间件的更多信息。
🌐 You can find more information about route middlewares in the [routes documentation](/cms/backend-customization/routes).
:::
# 模型
Source: https://docs.strapi.io/cms/backend-customization/models
# 模型 {#models}
🌐 Models
由于 Strapi 是一个无头内容管理系统(CMS),为内容创建内容结构是使用该软件时最重要的方面之一。模型定义了内容结构的表示。
🌐 As Strapi is a headless Content Management System (CMS), creating a content structure for the content is one of the most important aspects of using the software. Models define a representation of the content structure.
Strapi 有 2 种不同类型的模型:
🌐 There are 2 different types of models in Strapi:
- 内容类型,可以是集合类型或单一类型,具体取决于它们管理的条目数量,
- 以及可在多种内容类型中重复使用的内容结构组件。
如果你刚刚开始,可以直接在管理面板中使用 [Content-type Builder](/cms/features/content-type-builder) 生成一些模型。这种用户界面承担了许多验证任务,并展示了创建内容结构的所有可用选项。然后可以使用此文档在代码层面上查看生成的模型映射。
🌐 If you are just starting out, it is convenient to generate some models with the [Content-type Builder](/cms/features/content-type-builder) directly in the admin panel. The user interface takes over a lot of validation tasks and showcases all the options available to create the content's content structure. The generated model mappings can then be reviewed at the code level using this documentation.
## 模型创建 {#model-creation}
🌐 Model creation
内容类型和组件模型的创建和存储方式不同。
🌐 Content-types and components models are created and stored differently.
### 内容类型 {#content-types}
🌐 Content-types
可以在 Strapi 中创建内容类型:
🌐 Content-types in Strapi can be created:
- 在管理面板的[内容类型构建器](/cms/features/content-type-builder)中,
- 或者使用 [Strapi 的交互式 CLI `strapi generate`](/cms/cli#strapi-generate) 命令。
内容类型使用以下文件:
🌐 The content-types use the following files:
- `schema.json` 用于模型的 [schema](#model-schema) 定义。(自动生成,在使用任一方法创建内容类型时)
- `lifecycles.js` 用于 [生命周期钩子](#lifecycle-hooks)。此文件必须手动创建。
这些模型文件存储在 `./src/api/[api-name]/content-types/[content-type-name]/` 中,任何在这些文件夹中找到的 JavaScript 或 JSON 文件都将被加载为内容类型的模型(参见 [项目结构](/cms/project-structure))。
🌐 These models files are stored in `./src/api/[api-name]/content-types/[content-type-name]/`, and any JavaScript or JSON file found in these folders will be loaded as a content-type's model (see [project structure](/cms/project-structure)).
:::note
在启用了 [TypeScript](/cms/typescript.md) 的项目中,可以使用 `ts:generate-types` 命令生成模式类型定义。
🌐 In [TypeScript](/cms/typescript.md)-enabled projects, schema typings can be generated using the `ts:generate-types` command.
:::
### 组件 {#components-creation}
🌐 Components
组件模型无法使用 CLI 工具创建。请使用 [内容类型构建器](/cms/features/content-type-builder) 或手动创建它们。
🌐 Component models can't be created with CLI tools. Use the [Content-type Builder](/cms/features/content-type-builder) or create them manually.
组件模型存储在 `./src/components` 文件夹中。每个组件必须位于一个子文件夹内,该子文件夹的名称应与组件所属的类别相同(参见 [项目结构](/cms/project-structure))。
🌐 Components models are stored in the `./src/components` folder. Every component has to be inside a subfolder, named after the category the component belongs to (see [project structure](/cms/project-structure)).
## 模型架构 {#model-schema}
🌐 Model schema
一个模型的 `schema.json` 文件包含:
🌐 The `schema.json` file of a model consists of:
- [设置](#model-settings),例如模型表示的内容类型或应存储数据的表名,
- [信息](#model-information),主要用于在管理面板中显示模型并通过 REST 和 GraphQL API 访问它,
- [属性](#model-attributes),描述模型的内容结构,
- 以及 [options](#model-options) 用于定义模型上的特定行为。
### 模型设置 {#model-settings}
🌐 Model settings
模型的常规设置可以使用以下参数进行配置:
🌐 General settings for the model can be configured with the following parameters:
| 参数 | 类型 | 描述 || --- | --- | --- || `collectionName` | 字符串 | 数据应存储的数据库表名称 || `kind`
_可选, 仅用于内容类型_ | 字符串 | 定义内容类型是否为:
集合类型(`collectionType`)
或单一类型(`singleType`)
|
```json
// ./src/api/[api-name]/content-types/restaurant/schema.json
{
"kind": "collectionType",
"collectionName": "Restaurants_v1",
}
```
### 模型信息 {#model-information}
🌐 Model information
模型模式中的 `info` 键描述了用于在管理面板中显示模型以及通过内容 API 访问模型的信息。它包括以下参数:
🌐 The `info` key in the model's schema describes information used to display the model in the admin panel and access it through the Content API. It includes the following parameters:
| 参数 | 类型 | 描述 || --- | --- | --- || `displayName` | 字符串 | 在管理面板中使用的默认名称 || `singularName` | 字符串 | 内容类型名称的单数形式。 用于生成 API 路由和数据库/表集合。
应使用 kebab-case 格式。 || `description` | 字符串 | 模型的描述 |
```json title="./src/api/[api-name]/content-types/restaurant/schema.json"
"info": {
"displayName": "Restaurant",
"singularName": "restaurant",
"pluralName": "restaurants",
"description": ""
},
```
### 模型属性 {#model-attributes}
🌐 Model attributes
模型的内容结构由一系列属性组成。每个属性都有一个 `type` 参数,用于描述其性质,并将该属性定义为简单的数据片段或 Strapi 使用的更复杂结构。
🌐 The content structure of a model consists of a list of attributes. Each attribute has a `type` parameter, which describes its nature and defines the attribute as a simple piece of data or a more complex structure used by Strapi.
有多种类型的属性可用:
🌐 Many types of attributes are available:
- 标量类型(例如字符串、日期、数字、布尔值等),
- Strapi 特有的类型,例如:
- `media` 用于通过 [媒体库](/cms/features/content-type-builder#media) 上传的文件
- `relation` 用于描述内容类型之间的 [关系](#relations)
- `customField` 用于描述 [自定义字段](#custom-fields) 及其特定键
- `component` 用于定义一个 [组件](#components-json)(即可在多种内容类型中使用的内容结构)
- `dynamiczone` 用于定义一个 [动态区域](#dynamic-zones)(即基于组件列表的灵活空间)
- 以及 `locale` 和 `localizations` 类型,仅由 [国际化 (i18n) 插件](/cms/features/internationalization) 使用
属性的 `type` 参数应为以下值之一:
🌐 The `type` parameter of an attribute should be one of the following values:
| 类型类别 | 可用类型 ||------|-------|| 字符串类型 |
💡 这对于隐藏敏感数据很有用。 | `false` || `configurable` | 布尔值 | 如果 `false`,该属性无法通过内容类型构建器插件进行配置。 | `true` |
```json title="./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"
}
// ...
}
}
```
#### 数据库验证和设置 {#database-validations-and-settings}
🌐 Database validations and settings
:::caution 🚧 This API is considered experimental.
这些设置应该保留给高级使用,因为它们可能会导致某些功能失效。目前没有计划让这些设置稳定。
🌐 These settings should be reserved to an advanced usage, as they might break some features. There are no plans to make these settings stable.
:::
数据库验证和设置是直接传递给 `tableBuilder` Knex.js 函数的自定义选项,用于架构迁移期间。数据库验证允许对设置自定义列设置进行高级控制。以下选项在每个属性的 `column: {}` 对象中设置:
🌐 Database validations and settings are custom options passed directly onto the `tableBuilder` Knex.js function during schema migrations. Database validations allow for an advanced degree of control for setting custom column settings. The following options are set in a `column: {}` object per attribute:
| 参数 | 类型 | 描述 | 默认值 || --- | --- | --- | --- || `name` | 字符串 | 更改数据库中列的名称 | - || `defaultTo` | 字符串 | 设置数据库的 `defaultTo`,通常与 `notNullable` 一起使用 | - || `notNullable` | 布尔值 | 设置数据库的 `notNullable`,确保列不能为空 | `false` || `unsigned` | 布尔值 | 仅适用于数字列,移除允许负数的功能,但将最大长度加倍 | `false` || `unique` | 布尔值 | 强制对已发布条目执行数据库级唯一性检查。当启用“草稿与发布”功能时,草稿保存会跳过检查,因此仅在发布时重复才会失败 | `false` || `type` | 字符串 | 更改数据库类型,如果 `type` 有参数,应在 `args` 中传入 | - || `args` | 数组 | 传递给 Knex.js 函数的参数,可更改如 `type` 的内容 | `[]` |
:::caution Draft & Publish and `unique`
当启用 [Draft & Publish](/cms/features/draft-and-publish) 时,Strapi 会在条目被保存为草稿时故意跳过 `unique` 验证。因此,重复内容在发布之前不会被检测到,此时数据库约束会触发错误,即使 UI 之前对于草稿显示了“已保存文档”。
🌐 When [Draft & Publish](/cms/features/draft-and-publish) is enabled, Strapi intentionally skips `unique` validations while an entry is saved as a draft. Duplicates therefore remain undetected until publication, at which point the database constraint triggers an error even though the UI previously displayed “Saved document” for the drafts.
为避免意外发布失败:
🌐 To avoid unexpected publication failures:
- 禁用必须保持全局唯一的内容类型的“草稿和发布”功能,
- 或添加自定义验证(例如生命周期钩子或中间件),在保存前检查草稿是否重复,
- 或者依赖自动生成的唯一标识符,例如 `uid` 字段和文档编辑规范。
:::
```json title="./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-type}
🌐 `uid` type
`uid` 类型用于在管理面板中自动预填字段值,使用唯一标识符(UID)(例如文章的 slug),基于两个可选参数:
🌐 The `uid` type is used to automatically prefill the field value in the admin panel with a unique identifier (UID) (e.g. slugs for articles) based on 2 optional parameters:
- `targetField`(字符串):如果使用,定义为目标的字段的值将用于自动生成 UID。
- `options`(字符串):如果使用,UID 将基于传递给
#### 自定义字段 {#custom-fields}
🌐 Custom fields
[自定义字段](/cms/features/custom-fields) 通过向内容类型添加新类型的字段来扩展 Strapi 的功能。自定义字段在模型的 [属性](#model-attributes) 中使用 `type: customField` 明确定义。
自定义字段的属性还显示以下特性:
🌐 Custom fields' attributes also show the following specificities:
- 一个 `customField` 属性,其值作为唯一标识符,用于指示应使用哪个已注册的自定义字段。其值如下:
- 如果插件创建了自定义字段,则使用 `plugin::plugin-name.field-name` 格式
- 或者用于当前 Strapi 应用特定自定义字段的 `global::field-name` 格式
- 以及额外的参数,这取决于在注册自定义字段时定义的内容(参见[自定义字段文档](/cms/features/custom-fields))。
```json title="./src/api/[apiName]/[content-type-name]/content-types/schema.json"
{
// …
"attributes": {
"attributeName": { // attributeName would be replaced by the actual attribute name
"type": "customField",
"customField": "plugin::color-picker.color",
"options": {
"format": "hex"
}
}
}
// …
}
```
#### 组件 {#components-json}
🌐 Components
组件字段在内容类型和组件结构之间创建关系。组件在模型的 [attributes](#model-attributes) 中通过 `type: 'component'` 明确定义,并接受以下附加参数:
🌐 Component fields create a relation between a content-type and a component structure. Components are explicitly defined in the [attributes](#model-attributes) of a model with `type: 'component'` and accept the following additional parameters:
| 参数 | 类型 | 描述 || --- | --- | --- || `repeatable` | 布尔值 | 根据组件是否可重复,可能是 `true` 或 `false` || `component` | 字符串 | 定义相应的组件,遵循此格式: `.` |
```json title="./src/api/[apiName]/restaurant/content-types/schema.json"
{
"attributes": {
"openinghours": {
"type": "component",
"repeatable": true,
"component": "restaurant.openinghours"
}
}
}
```
#### 动态区域 {#dynamic-zones}
🌐 Dynamic zones
动态区域创建了一个灵活的空间,用于根据混合的[组件](#components-json)列表来编排内容。
🌐 Dynamic zones create a flexible space in which to compose content, based on a mixed list of [components](#components-json).
动态区域在模型的 [attributes](#model-attributes) 中用 `type: 'dynamiczone'` 明确定义。它们还接受一个 `components` 数组,其中每个组件的名称应遵循以下格式:`.`。
🌐 Dynamic zones are explicitly defined in the [attributes](#model-attributes) of a model with `type: 'dynamiczone'`. They also accept a `components` array, where each component should be named following this format: `.`.
```json title="./src/api/[api-name]/content-types/article/schema.json"
{
"attributes": {
"body": {
"type": "dynamiczone",
"components": ["article.slider", "article.content"]
}
}
}
```
### 模型选项 {#model-options}
🌐 Model options
`options` 键用于定义特定行为,并接受以下参数:
🌐 The `options` key is used to define specific behaviors and accepts the following parameter:
| 参数 | 类型 | 描述 |
|---------------------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `privateAttributes` | 字符串数组 | 允许将一组属性视为私有,即使它们实际上并未在模型中定义为属性。它可以用于从 API 响应中移除它们的时间戳。
默认值:`false`。 |
```json title="./src/api/[api-name]/content-types/restaurant/schema.json"
{
"options": {
"privateAttributes": ["id", "createdAt"],
"draftAndPublish": true
}
}
```
### 插件选项 {#plugin-options}
🌐 Plugin options
`pluginOptions` 是一个可选对象,允许插件为模型或特定属性存储配置。
| 键 | 值 | 描述 ||---------------------------|-------------------------------|--------------------------------------------------------|| `i18n` | `localized: true` | 启用本地化。 || `content-manager` | `visible: false` | 在管理员面板中从内容管理器隐藏。 || `content-type-builder` | `visible: false` | 在管理员面板中从内容类型构建器隐藏。 |
```json title="./src/api/[api-name]/content-types/[content-type-name]/schema.json"
{
"attributes": {
"name": {
"pluginOptions": {
"i18n": {
"localized": true
}
},
"type": "string",
"required": true
},
"slug": {
"pluginOptions": {
"i18n": {
"localized": true
}
},
"type": "uid",
"targetField": "name",
"required": true
}
// …additional attributes
}
}
```
## 生命周期钩子 {#lifecycle-hooks}
🌐 Lifecycle hooks
生命周期钩子是当 Strapi 查询被调用时触发的函数。当通过管理面板管理内容或使用 `queries` 开发自定义代码时,它们会自动触发。
🌐 Lifecycle hooks are functions that get triggered when Strapi queries are called. They are triggered automatically when managing content through the administration panel or when developing custom code using `queries`·
生命周期钩子可以通过声明或编程方式自定义。
🌐 Lifecycle hooks can be customized declaratively or programmatically.
:::caution
当直接使用
使用数据库层 API,还可以注册订阅者并以编程方式监听事件:
🌐 Using the database layer API, it's also possible to register a subscriber and listen to events programmatically:
```js title="./src/index.js"
module.exports = {
async bootstrap({ strapi }) {
// 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
}
});
}
}
```
# 政策
Source: https://docs.strapi.io/cms/backend-customization/policies
# 政策 {#policies}
🌐 Policies
策略是在每个请求到达[控制器](/cms/backend-customization/controllers)之前执行特定逻辑的函数。它们主要用于保护业务逻辑。
🌐 Policies are functions that execute specific logic on each request before it reaches the [controller](/cms/backend-customization/controllers). They are mostly used for securing business logic.
Strapi 项目的每个[路由](/cms/backend-customization/routes)都可以关联到一组策略。例如,一个名为 `is-admin` 的策略可以检查请求是否由管理员用户发送,并限制对关键路由的访问。
🌐 Each [route](/cms/backend-customization/routes) of a Strapi project can be associated to an array of policies. For example, a policy named `is-admin` could check that the request is sent by an admin user, and restrict access to critical routes.
策略可以是全局的或有范围的。[全局策略](#global-policies)可以关联到项目中的任何路由。有范围的策略只适用于特定的[API](#api-policies)或[插件](#plugin-policies),并应存放在相应的`./src/api//policies/`或`./src/plugins//policies/`文件夹下。
该图表示请求在 Strapi 后端传输的简化版本,并突出了策略和路由。后端自定义介绍页面包括一个完整的, 交互式图表。
## 实现 {#implementation}
🌐 Implementation
可以实现一项新政策:
🌐 A new policy can be implemented:
- 使用 [交互式 CLI 命令 `strapi generate`](/cms/cli#strapi-generate)
- 或者通过在相应的文件夹中创建一个 JavaScript 文件手动完成(参见 [项目结构](/cms/project-structure)):
- `./src/policies/` 用于全球政策
- `./src/api/[api-name]/policies/` 用于 API 策略
- `./src/plugins/[plugin-name]/policies/` 用于插件策略
全球政策实现示例:
🌐 Global policy implementation example:
`policyContext` 是 [controller](/cms/backend-customization/controllers) 上下文的一个封装。它增加了一些逻辑,这些逻辑对于在 REST 和 GraphQL 中实现策略可能很有用。
可以使用 `config` 对象配置策略:
🌐 Policies can be configured using a `config` object:
## 使用 {#usage}
🌐 Usage
要将策略应用到路由,请将它们添加到路由的配置对象中(参见 [路由文档](/cms/backend-customization/routes#policies))。
🌐 To apply policies to a route, add them to its configuration object (see [routes documentation](/cms/backend-customization/routes#policies)).
策略根据其范围有不同的调用方式:
🌐 Policies are called different ways depending on their scope:
- 使用 `global::policy-name` 用于 [全局策略](#global-policies)
- 使用 `api::api-name.policy-name` 用于 [API 政策](#api-policies)
- 使用 `plugin::plugin-name.policy-name` 用于 [插件政策](#plugin-policies)
:::tip
要列出所有可用的策略,请运行 `yarn strapi policies:list`。
🌐 To list all the available policies, run `yarn strapi policies:list`.
:::
### 全球政策 {#global-policies}
🌐 Global policies
全局策略可以与项目中的任何路由关联。
🌐 Global policies can be associated to any route in a project.
### 插件政策 {#plugin-policies}
🌐 Plugin policies
插件可以向应用添加并公开策略。例如,[用户与权限功能](/cms/features/users-permissions) 配备了策略,以确保用户已通过身份验证或拥有执行某个操作的权限:
🌐 Plugins can add and expose policies to an application. For example, the [Users & Permissions feature](/cms/features/users-permissions) comes with policies to ensure that the user is authenticated or has the rights to perform an action:
### API 政策 {#api-policies}
🌐 API policies
API 策略与声明它们的 API 中定义的路由相关联。
🌐 API policies are associated to the routes defined in the API where they have been declared.
要在另一个 API 中使用策略,请使用以下语法引用它:`api::[apiName].[policyName]`:
🌐 To use a policy in another API, reference it with the following syntax: `api::[apiName].[policyName]`:
# 请求与响应
Source: https://docs.strapi.io/cms/backend-customization/requests-responses
# 请求与响应 {#requests-and-responses}
🌐 Requests and Responses
Strapi 后端服务器基于 。当你通过 [REST API](/cms/api/rest) 发送请求时,一个上下文对象(`ctx`)会传递给 Strapi 后端的每个元素(例如,[policies](/cms/backend-customization/policies)、[controllers](/cms/backend-customization/controllers)、[services](/cms/backend-customization/services))。
`ctx` 包含 3 个主要对象:
- [`ctx.request`](#ctxrequest) 了解关于发起 API 请求的客户端发送的请求的信息,
- [`ctx.state`](#ctxstate) 了解有关请求在 Strapi 后端状态的信息,
- 以及 [`ctx.response`](#ctxresponse) 获取有关服务器将返回的响应的信息。
:::tip
请求的上下文也可以通过代码中的任何位置使用 [`strapi.requestContext` 函数](#accessing-the-request-context-anywhere) 访问。
🌐 The request's context can also be accessed from anywhere in the code with the [`strapi.requestContext` function](#accessing-the-request-context-anywhere).
:::
:::info
除了以下文档中描述的概念和参数外,你可能还会在 、 和 中找到额外的信息。
:::
该图表示请求在 Strapi 后端传输的简化版本,并突出了请求和响应。后端自定义介绍页面包括一个完整的、 交互式图表。
## `ctx.request`
`ctx.request` 对象包含以下参数:
🌐 The `ctx.request` object contains the following parameters:
| 参数 | 描述 | 类型 |
| --- | --- | --- |
| `ctx.request.body` | 正文的解析版本。 | `Object` |
| `ctx.request.files` | 随请求发送的文件。 | `Array` |
| `ctx.request.headers` | 随请求发送的头信息。 | `Object` |
| `ctx.request.host` | URL 的主机部分,包括端口。 | `String` |
| `ctx.request.hostname`| URL 的主机部分,不包括端口。 | `String` |
| `ctx.request.href` | 请求资源的完整 URL,包括协议、域名、端口(如果指定)、路径和查询参数。 | `String` |
| `ctx.request.ip` | 发送请求的人的IP。| `String` |
| `ctx.request.ips` | 当 `X-Forwarded-For` 存在并且 `app.proxy` 启用时,将返回一个 IP 数组,按从上游到下游的顺序排列。
`ctx.response.attachment([filename], [options])` | 将 头设置为 "attachment",以提示客户端进行下载。可选地指定下载文件名和一些 。 | `Function` |
| `ctx.response.type`| 头,不包含诸如 "charset" 之类的参数。 | `String` |
| `ctx.response.lastModified`| 将 `` 头作为日期,如果它存在的话。 | `DateTime` |
| `ctx.response.etag`| 设置响应的 ,包括封装的 s. 没有对应的 `response.etag` 获取器。 | `String` |
## 在任何地方访问请求上下文 {#accessing-the-request-context-anywhere}
🌐 Accessing the request context anywhere
Strapi 公开了一种从代码中的任何位置访问当前请求上下文的方法(例如生命周期函数)。
🌐 Strapi exposes a way to access the current request context from anywhere in the code (e.g. lifecycle functions).
你可以按如下方式访问该请求:
🌐 You can access the request as follows:
```js
const ctx = strapi.requestContext.get();
```
你应该只在 HTTP 请求上下文中调用的函数内部使用它。
🌐 You should only use this inside of functions that will be called in the context of an HTTP request.
```js
// correct
const service = {
myFunction() {
const ctx = strapi.requestContext.get();
console.log(ctx.state.user);
},
};
// incorrect
const ctx = strapi.requestContext.get();
const service = {
myFunction() {
console.log(ctx.state.user);
},
};
```
**示例:**
```js title="./api/test/content-types/article/lifecycles.js"
module.exports = {
beforeUpdate() {
const ctx = strapi.requestContext.get();
console.log('User info in service: ', ctx.state.user);
},
};
```
:::note
Strapi 使用 Node.js 的一个名为 的功能来使上下文在任何地方都可用。
:::
# 路线
Source: https://docs.strapi.io/cms/backend-customization/routes
# 路线 {#routes}
🌐 Routes
发送到 Strapi 上任何 URL 的请求都由路由处理。默认情况下,Strapi 会为所有内容类型生成路由(请参阅 [REST API 文档](/cms/api/rest))。路由可以被 [添加](#implementation) 和配置:
🌐 Requests sent to Strapi on any URL are handled by routes. By default, Strapi generates routes for all the content-types (see [REST API documentation](/cms/api/rest)). Routes can be [added](#implementation) and configured:
- 使用 [策略](#policies),这是一种阻止访问某个路线的方法,
- 以及使用 [中间件](#middlewares),中间件是一种控制和改变请求流程及请求本身的方式。
一旦路由存在,访问它会执行由控制器处理的一些代码(参见 [控制器文档](/cms/backend-customization/controllers))。要查看所有现有路由及其层级顺序,你可以运行 `yarn strapi routes:list`(参见 [CLI 参考](/cms/cli))。
🌐 Once a route exists, reaching it executes some code handled by a controller (see [controllers documentation](/cms/backend-customization/controllers)). To view all existing routes and their hierarchal order, you can run `yarn strapi routes:list` (see [CLI reference](/cms/cli)).
:::tip
如果你只是自定义 Strapi 为某个内容类型生成的默认控制器操作(`find`、`findOne`、`create`、`update` 或 `delete`),你可以保持路由不变。这些核心路由已经指向相同的处理程序名称,并会运行你新的控制器逻辑。只有在你需要一个全新的 HTTP 路径/方法或想要暴露自定义控制器操作时,才需要添加或编辑路由。
🌐 If you only customize the default controller actions (`find`, `findOne`, `create`, `update`, or `delete`) that Strapi generates for a content-type, you can leave the router as-is. Those core routes already target the same handler names and will run your new controller logic. Add or edit a route only when you need a brand-new HTTP path/method or want to expose a custom controller action.
:::
该图表示请求在 Strapi 后端传输的简化版本,并标出了路由。后端自定义介绍页面包括完整的、 交互式图表。
## 实现 {#implementation}
🌐 Implementation
实现一个新路由包括在 `./src/api/[apiName]/routes` 文件夹中的路由文件中定义它(参见 [项目结构](/cms/project-structure))。
🌐 Implementing a new route consists in defining it in a router file within the `./src/api/[apiName]/routes` folder (see [project structure](/cms/project-structure)).
根据用例,有 2 种不同的路由文件结构:
🌐 There are 2 different router file structures, depending on the use case:
- 配置[核心路由](#configuring-core-routers)
- 或创建[自定义路由](#creating-custom-routers)。
### 配置核心路由 {#configuring-core-routers}
🌐 Configuring core routers
核心路由(即 `find`、`findOne`、`create`、`update` 和 `delete`)对应于当创建新的 [内容类型](/cms/backend-customization/models#model-creation) 时 Strapi 自动创建的 [默认路由](/cms/api/rest#endpoints)。
🌐 Core routers (i.e. `find`, `findOne`, `create`, `update`, and `delete`) correspond to [default routes](/cms/api/rest#endpoints) automatically created by Strapi when a new [content-type](/cms/backend-customization/models#model-creation) is created.
Strapi 提供了一个 `createCoreRouter` 工厂函数,它会自动生成核心路由并允许:
🌐 Strapi provides a `createCoreRouter` factory function that automatically generates the core routers and allows:
- 将配置选项传递给每个路由
- 并禁用一些核心路由以[创建自定义路由](#creating-custom-routers)。
核心路由文件是一个 JavaScript 文件,导出对 `createCoreRouter` 调用的结果,该调用具有以下参数:
🌐 A core router file is a JavaScript file exporting the result of a call to `createCoreRouter` with the following parameters:
| 参数 | 描述 | 类型 || --- | --- | --- || `prefix` | 允许传入自定义前缀,添加到该模型的所有路由(例如 `/test`) | `String` || `only` | 仅会加载的核心路由
| `Object` |
可以使用参数和正则表达式创建动态路由。这些参数将会在 `ctx.params` 对象中暴露。更多详情,请参阅
## 配置 {#configuration}
🌐 Configuration
核心路由和自定义路由都有相同的配置选项。路由配置在一个 `config` 对象中定义,该对象可以用来处理策略和中间件,或将路由设为公开。
🌐 Both [core routers](#configuring-core-routers) and [custom routers](#creating-custom-routers) have the same configuration options. The routes configuration is defined in a `config` object that can be used to handle [policies](#policies) and [middlewares](#middlewares) or to [make the route public](#public-routes).
### 政策 {#policies}
🌐 Policies
可以将[策略](/cms/backend-customization/policies)添加到路由配置中:
- 通过指向在 `./src/policies` 中注册的策略,无论是否传递自定义配置
- 或者通过直接声明策略实现,将其作为一个函数,该函数以 `policyContext` 扩展
### 中间件 {#middlewares}
🌐 Middlewares
可以将[中间件](/cms/backend-customization/middlewares)添加到路由配置中:
- 通过指向在 `./src/middlewares` 中注册的中间件,无论是否传递自定义配置
- 或者直接通过声明中间件实现,作为一个函数,该函数以
### 公共路线 {#public-routes}
🌐 Public routes
默认情况下,路由受 Strapi 的身份验证系统保护,该系统基于[API 令牌](/cms/features/api-tokens)或使用[用户与权限插件](/cms/features/users-permissions)。
🌐 By default, routes are protected by Strapi's authentication system, which is based on [API tokens](/cms/features/api-tokens) or on the use of the [Users & Permissions plugin](/cms/features/users-permissions).
在某些情况下,将某条路由公开并在正常的 Strapi 身份验证系统之外控制访问可能是有用的。这可以通过将路由的 `auth` 配置参数设置为 `false` 来实现:
🌐 In some scenarios, it can be useful to have a route publicly available and control the access outside of the normal Strapi authentication system. This can be achieved by setting the `auth` configuration parameter of a route to `false`:
## 自定义内容 API 参数 {#custom-content-api-parameters}
🌐 Custom Content API parameters
你可以通过在 [register](/cms/configurations/functions#register) 生命周期中注册,将允许在内容 API 路由上的 `query` 和 body 参数扩展。注册的参数随后会像核心参数一样被验证和清理。客户端可以发送额外的查询键(例如 `?search=...`)或根级 body 键(例如 `clientMutationId`),而无需自定义路由或控制器。
🌐 You can extend the `query` and body parameters allowed on Content API routes by registering them in the [register](/cms/configurations/functions#register) lifecycle. Registered parameters are then validated and sanitized like core parameters. Clients can send extra query keys (e.g. `?search=...`) or root-level body keys (e.g. `clientMutationId`) without requiring custom routes or controllers.
| 什么 | 哪里 ||------|--------|| 启用严格参数(拒绝未知的查询/主体键) | [API 配置](/cms/configurations/api):在 `./config/api.js`(或 `./config/api.ts`)中设置 `rest.strictParams: true`。 || 添加允许的参数(应用) | 在 `./src/index.js` 或 `./src/index.ts` 的 [注册](/cms/configurations/functions#register) 中调用 `addQueryParams` / `addInputParams`。 || 添加允许的参数(插件) | 在插件的 [注册](/cms/plugins-development/server-lifecycle#register) 生命周期中调用 `addQueryParams` / `addInputParams`。 |
当启用 `rest.strictParams` 时,仅接受核心参数和每个路由请求模式上的参数;你注册的参数会合并到该模式中。模式请使用来自 `@strapi/utils`(或 `zod/v4`)的 `z` 实例。
🌐 When `rest.strictParams` is enabled, only core parameters and parameters on each route's request schema are accepted; the parameters you register are merged into that schema. Use the `z` instance from `@strapi/utils` (or `zod/v4`) for schemas.
### `addQueryParams`
`strapi.contentAPI.addQueryParams(options)` 注册额外的 `query` 参数。模式必须是标量或标量数组(字符串、数字、布尔值、枚举)。对于嵌套结构,请改用 `addInputParams`。每个条目可以有一个可选的 `matchRoute: (route) => boolean` 回调,仅将参数添加到回调返回 true 的路由。你不能将核心查询参数名称(例如 `filters`、`sort`、`fields`)注册为额外参数;它们是保留的。
### `addInputParams`
`strapi.contentAPI.addInputParams(options)` 注册额外的输入参数:请求体中的根级键(例如与 `data` 并列),可以使用任何 Zod 类型。可选的 `matchRoute` 回调的作用与 `addQueryParams` 相同。你不能将保留名称如 `id` 或 `documentId` 注册为输入参数。
### `matchRoute`
`matchRoute` 回调接收一个具有以下属性的 `route` 对象:
🌐 The `matchRoute` callback receives a `route` object with the following properties:
- `route.method`:HTTP 方法(`'GET'`、`'POST'` 等)
- `route.path`:路线路径
- `route.handler`:控制器操作字符串
- `route.info`:关于路线的元数据
例如,要仅针对 GET 路由,请使用 `matchRoute: (route) => route.method === 'GET'`。要仅针对路径包含 `articles` 的路由,请使用 `matchRoute: (route) => route.path.includes('articles')`。
🌐 For example, to target only GET routes, use `matchRoute: (route) => route.method === 'GET'`. To target only routes whose path includes `articles`, use `matchRoute: (route) => route.path.includes('articles')`.
# 服务
Source: https://docs.strapi.io/cms/backend-customization/services
# 服务 {#services}
🌐 Services
服务是一组可重用的功能。它们对于遵循“不要重复自己”(DRY)编程理念以及简化[控制器](/cms/backend-customization/controllers.md)的逻辑特别有用。
🌐 Services are a set of reusable functions. They are particularly useful to respect the "don’t repeat yourself" (DRY) programming concept and to simplify [controllers](/cms/backend-customization/controllers.md) logic.
该图表示请求在 Strapi 后端传递的简化版本,并高亮了服务。后端自定义介绍页面包括完整的、 交互式图表。
## 实现 {#implementation}
🌐 Implementation
服务可以[手动生成或添加](#adding-a-new-service)。Strapi 提供了一个 `createCoreService` 工厂函数,能够自动生成核心服务,并允许构建自定义服务或[扩展或替换生成的服务](#extending-core-services)。
🌐 Services can be [generated or added manually](#adding-a-new-service). Strapi provides a `createCoreService` factory function that automatically generates core services and allows building custom ones or [extend or replace the generated services](#extending-core-services).
### 添加新服务 {#adding-a-new-service}
🌐 Adding a new service
可以实现一个新的服务:
🌐 A new service can be implemented:
- 使用 [交互式 CLI 命令 `strapi generate`](/cms/cli#strapi-generate)
- 或者通过在相应的文件夹中创建一个 JavaScript 文件手动完成(参见 [项目结构](/cms/project-structure.md)):
- `./src/api/[api-name]/services/` 用于 API 服务
- 或用于[插件服务](/cms/plugins-development/server-controllers-services)的 `./src/plugins/[plugin-name]/services/`。
要手动创建一个服务,请导出一个工厂函数,该函数返回服务实现(即包含方法的对象)。该工厂函数接收 `strapi` 实例:
🌐 To manually create a service, export a factory function that returns the service implementation (i.e. an object with methods). This factory function receives the `strapi` instance:
:::strapi Document Service API
要开始创建你自己的服务,请参阅 Strapi 的内置函数,详见 [文档服务 API](/cms/api/document-service) 文档。
🌐 To get started creating your own services, see Strapi's built-in functions in the [Document Service API](/cms/api/document-service) documentation.
:::
自定义电子邮件服务示例(使用 Nodemailer)
服务的目标是存储可重复使用的函数。一个 `sendNewsletter` 服务可能在我们的代码库中从不同函数发送电子邮件时非常有用,这些函数有特定的用途:
🌐 The goal of a service is to store reusable functions. A `sendNewsletter` service could be useful to send emails from different functions in our codebase that have a specific purpose:
该服务现在可以通过 `strapi.service('api::restaurant.restaurant').sendNewsletter(...args)` 全局变量使用。它可以在代码库的其他部分使用,例如在以下控制器中:
🌐 The service is now available through the `strapi.service('api::restaurant.restaurant').sendNewsletter(...args)` global variable. It can be used in another part of the codebase, like in the following controller:
:::note
当创建新的 [内容类型](/cms/backend-customization/models.md#content-types) 时,Strapi 会生成一个带有占位符代码的通用服务,准备进行自定义。
🌐 When a new [content-type](/cms/backend-customization/models.md#content-types) is created, Strapi builds a generic service with placeholder code, ready to be customized.
:::
### 扩展核心服务 {#extending-core-services}
🌐 Extending core services
核心服务是为每种内容类型创建的,可以被[控制器](/cms/backend-customization/controllers.md)使用,以在 Strapi 项目中执行可重用的逻辑。核心服务可以自定义以实现你自己的逻辑。以下代码示例应能帮助你入门。
🌐 Core services are created for each content-type and could be used by [controllers](/cms/backend-customization/controllers.md) to execute reusable logic through a Strapi project. Core services can be customized to implement your own logic. The following code examples should help you get started.
:::tip
核心服务可以完全通过[创建自定义服务](#adding-a-new-service)来替代,并将其命名为与核心服务相同(例如 `find`、`findOne`、`create`、`update` 或 `delete`)。
🌐 A core service can be replaced entirely by [creating a custom service](#adding-a-new-service) and naming it the same as the core service (e.g. `find`, `findOne`, `create`, `update`, or `delete`).
:::
集合类型示例单类型示例
## 使用 {#usage}
🌐 Usage
一旦服务被创建,就可以从[控制器](/cms/backend-customization/controllers.md)或其他服务访问它:
🌐 Once a service is created, it's accessible from [controllers](/cms/backend-customization/controllers.md) or from other services:
```js
// access an API service
strapi.service('api::apiName.serviceName').FunctionName();
// access a plugin service
strapi.service('plugin::pluginName.serviceName').FunctionName();
```
在上面的语法示例中,`serviceName` 是 API 服务的服务文件名称,或者用于将服务文件导出到 `services/index.js` 的插件服务使用的名称。
🌐 In the syntax examples above, `serviceName` is the name of the service file for API services or the name used to export the service file to `services/index.js` for plugin services.
:::tip
要列出所有可用的服务,请运行 `yarn strapi services:list`。
🌐 To list all the available services, run `yarn strapi services:list`.
:::
### 核心服务方法 {#core-service-methods}
🌐 Core service methods
使用 `createCoreService` 生成的服务继承了封装 [文档服务 API](/cms/api/document-service) 的方法。可用的方法取决于内容类型:
🌐 Services generated with `createCoreService` inherit methods that wrap the [Document Service API](/cms/api/document-service). The available methods depend on the content-type:
#### 集合类型 {#collection-types}
🌐 Collection types
| 方法 | 描述 |
| --- | --- |
| `find(params)` | [`findMany`](/cms/api/document-service#findmany) 的封装;返回文档的分页列表。 |
| `findOne(documentId, params)` | [`findOne`](/cms/api/document-service#findone) 的封装器;通过其 `documentId` 返回单个文档。 |
| `create(params)` | [`create`](/cms/api/document-service#create) 的封装器;创建一个新文档。 |
| `update(documentId, params)` | [`update`](/cms/api/document-service#update) 的封装器;更新现有文档。 |
| `delete(documentId, params)` | [`delete`](/cms/api/document-service#delete) 的封装器;删除一个文档。 |
| `count(params)` | [`count`](/cms/api/document-service#count) 的封装器;返回匹配文档的数量。 |
| `publish(documentId, params)` | [`publish`](/cms/api/document-service#publish) 的封装器;发布草稿文档。 |
| `unpublish(documentId, params)` | [`unpublish`](/cms/api/document-service#unpublish) 的封装;取消发布文档。 |
| `discardDraft(documentId, params)` | [`discardDraft`](/cms/api/document-service#discarddraft) 的封装器;删除草稿副本。 |
#### 单一类型 {#single-types}
🌐 Single types
| 方法 | 描述 || --- | --- || `find(params)` | 返回单个文档(内部使用 [`findFirst`](/cms/api/document-service#findfirst))。 || `createOrUpdate({ data, ...params })` | 如果文档不存在则创建,或更新文档(使用 [`update`](/cms/api/document-service#update))。 || `delete(params)` | 删除文档(使用 [`delete`](/cms/api/document-service#delete))。 || `count(params)` | 计算匹配过滤条件的文档数量(使用 [`count`](/cms/api/document-service#count))。 || `publish(params)` | 发布草稿文档(使用 [`publish`](/cms/api/document-service#publish))。 || `unpublish(params)` | 取消发布文档(使用 [`unpublish`](/cms/api/document-service#unpublish))。 || `discardDraft(params)` | 删除草稿副本(使用 [`discardDraft`](/cms/api/document-service#discarddraft))。 |
#### 参数和默认行为 {#parameters-and-default-behavior}
🌐 Parameters and default behavior
核心服务方法接受与其底层的 [Document Service API](/cms/api/document-service) 调用相同的参数,例如 `fields`、`filters`、`sort`、`pagination`、`populate`、`locale` 和 `status`。当未提供 `status` 时,Strapi 会自动设置 `status: 'published'`,因此只返回已发布的内容。要查询草稿文档,请明确传递 `status: 'draft'` 或 Document Service 支持的其他值。
🌐 Core service methods accept the same parameters as their underlying [Document Service API](/cms/api/document-service) calls, such as `fields`, `filters`, `sort`, `pagination`, `populate`, `locale`, and `status`. When no `status` is provided, Strapi automatically sets `status: 'published'` so only published content is returned. To query draft documents, explicitly pass `status: 'draft'` or another value supported by the Document Service.
`createCoreService` 工厂还提供了一个 `getFetchParams(params)` 辅助工具,它可以将控制器的查询对象转换为这些方法期望的参数格式。在重写核心方法以将清理后的参数传递给 `strapi.documents()` 时,可以重复使用此辅助工具。
🌐 The `createCoreService` factory also exposes a `getFetchParams(params)` helper that converts a controller's query object into the parameter format expected by these methods. This helper can be reused when overriding core methods to forward sanitized parameters to `strapi.documents()`.
# 网络钩子
Source: https://docs.strapi.io/cms/backend-customization/webhooks
# 网络钩子 {#webhooks}
🌐 Webhooks
Webhook 是一种由应用使用的结构,用于通知其他应用某个事件已经发生。更准确地说,webhook 是用户定义的 HTTP 回调。使用 webhook 是告知第三方提供商开始某些处理(持续集成、构建、部署……)的好方法。
🌐 Webhook is a construct used by an application to notify other applications that an event occurred. More precisely, webhook is a user-defined HTTP callback. Using a webhook is a good way to tell third-party providers to start some processing (CI, build, deployment ...).
Webhook 的工作方式是通过 HTTP 请求(通常是 POST 请求)向接收应用传递信息。
🌐 The way a webhook works is by delivering information to a receiving application through HTTP requests (typically POST requests).
## 用户内容类型的网页钩子 {#user-content-type-webhooks}
🌐 User content-type webhooks
为了防止无意中将任何用户的信息发送到其他应用,Webhooks 将不会对用户内容类型起作用。如果你需要向其他应用通知用户集合的更改,可以通过使用 `./src/index.js` 示例创建 [生命周期钩子](/cms/backend-customization/models#lifecycle-hooks) 来实现。
🌐 To prevent from unintentionally sending any user's information to other applications, Webhooks will not work for the User content-type.
If you need to notify other applications about changes in the Users collection, you can do so by creating [Lifecycle hooks](/cms/backend-customization/models#lifecycle-hooks) using the `./src/index.js` example.
## 可用配置 {#available-configurations}
🌐 Available configurations
你可以在文件 `./config/server` 中设置 webhook 配置。
🌐 You can set webhook configurations inside the file `./config/server`.
- `webhooks`
- `defaultHeaders`:你可以为你的 webhook 请求设置默认头部。此选项会被 webhook 本身设置的头部覆盖。
**示例配置**
## Webhooks 安全 {#webhooks-security}
🌐 Webhooks security
大多数时候,Webhook 会向公共 URL 发出请求,因此有人可能会找到该 URL 并向其发送错误信息。
🌐 Most of the time, webhooks make requests to public URLs, therefore it is possible that someone may find that URL and send it wrong information.
为了防止这种情况发生,你可以发送带有身份验证令牌的头信息。使用管理面板时,你必须对每个 webhook 都这样做。
🌐 To prevent this from happening you can send a header with an authentication token. Using the Admin panel you would have to do it for every webhook.
另一种方法是定义 `defaultHeaders` 以添加到每个 webhook 请求中。
🌐 Another way is to define `defaultHeaders` to add to every webhook request.
你可以通过更新 `./config/server` 文件来配置这些全局头信息:
🌐 You can configure these global headers by updating the file at `./config/server`:
如果你自己开发 Webhook 处理程序,你现在可以通过读取标头来验证令牌。
🌐 If you are developing the webhook handler yourself you can now verify the token by reading the headers.
### 验证签名 {#verifying-signatures}
🌐 Verifying signatures
除了认证头之外,建议对 webhook 负载进行签名并在服务器端验证签名,以防止篡改和重放攻击。为此,你可以使用以下指南:
🌐 In addition to auth headers, it's recommended to sign webhook payloads and verify signatures server‑side to prevent tampering and replay attacks. To do so, you can use the following guidelines:
- 生成共享密钥并将其存储在环境变量中。
- 让发送方对原始请求正文加上时间戳计算 HMAC(例如,SHA-256)。
- 在头信息中发送签名(和时间戳)(例如,`X‑Webhook‑Signature`,`X‑Webhook‑Timestamp`)
- 收到请求后,重新计算 HMAC 并使用恒定时间检查进行比较。
- 如果签名无效或时间戳过旧,无法避免重放攻击,则拒绝请求。
示例:验证 HMAC 签名(Node.js)
这是一个最小的 Node.js 中间件示例(伪代码),显示
以下是一些额外的外部示例:
🌐 Here are a few additional external examples:
-
-
## 可用活动 {#available-events}
🌐 Available events
默认情况下,Strapi webhook 可以由以下事件触发:
🌐 By default Strapi webhooks can be triggered by the following events:
| 名称 | 描述 |
| --- | --- |
| [`entry.create`](#entrycreate) | 当创建内容类型条目时触发。 |
| [`entry.update`](#entryupdate) | 当内容类型条目被更新时触发。 |
| [`entry.delete`](#entrydelete) | 当内容类型条目被删除时触发。 |
|['entry.publish'](#entrypublish) |当发布内容类型条目时触发。\* |
| [`entry.unpublish`](#entryunpublish) | 当内容类型条目被取消发布时触发。* |
| [`media.create`](#mediacreate) | 当媒体被创建时触发。 |
| [`media.update`](#mediaupdate) | 当媒体被更新时触发。 |
| [`media.delete`](#mediadelete) | 当媒体被删除时触发。 |
| [`review-workflows.updateEntryStage`](#review-workflowsupdateentrystage) | 当内容在审核阶段之间移动时触发(参见 [审核工作流程](/cms/features/review-workflows#configuration))。 此事件仅适用于 Strapi 的 版本。 |
| [`releases.publish`](#releases-publish) | 当发布 Release 时触发(参见 [Releases](/cms/features/releases))。 此事件仅在 Strapi CMS 的 或 计划中可用。 |
*仅当此内容类型上的 `draftAndPublish` 已启用时。
## 有效载荷 {#payloads}
🌐 Payloads
:::info
私有字段不会在有效负载中发送。
🌐 Private fields are not sent in the payload.
:::
### 标题 {#headers}
🌐 Headers
当有效负载传递到你的 webhook 的 URL 时,它将包含特定标头:
🌐 When a payload is delivered to your webhook's URL, it will contain specific headers:
| 标题 | 描述 || --- | --- || `X-Strapi-Event` | 被触发的事件类型的名称。 |
### `entry.create`
创建新条目时会触发此事件。
🌐 This event is triggered when a new entry is created.
**示例有效负载**
```json
{
"event": "entry.create",
"createdAt": "2020-01-10T08:47:36.649Z",
"model": "address",
"entry": {
"id": 1,
"geolocation": {},
"city": "Paris",
"postal_code": null,
"category": null,
"full_name": "Paris",
"createdAt": "2020-01-10T08:47:36.264Z",
"updatedAt": "2020-01-10T08:47:36.264Z",
"cover": null,
"images": []
}
}
```
### `entry.update`
当条目更新时会触发此事件。
🌐 This event is triggered when an entry is updated.
**示例有效负载**
```json
{
"event": "entry.update",
"createdAt": "2020-01-10T08:58:26.563Z",
"model": "address",
"entry": {
"id": 1,
"geolocation": {},
"city": "Paris",
"postal_code": null,
"category": null,
"full_name": "Paris",
"createdAt": "2020-01-10T08:47:36.264Z",
"updatedAt": "2020-01-10T08:58:26.210Z",
"cover": null,
"images": []
}
}
```
### `entry.delete`
当删除条目时会触发此事件。
🌐 This event is triggered when an entry is deleted.
**示例有效负载**
```json
{
"event": "entry.delete",
"createdAt": "2020-01-10T08:59:35.796Z",
"model": "address",
"entry": {
"id": 1,
"geolocation": {},
"city": "Paris",
"postal_code": null,
"category": null,
"full_name": "Paris",
"createdAt": "2020-01-10T08:47:36.264Z",
"updatedAt": "2020-01-10T08:58:26.210Z",
"cover": null,
"images": []
}
}
```
### `entry.publish`
发布条目时会触发此事件。
🌐 This event is triggered when an entry is published.
**示例有效负载**
```json
{
"event": "entry.publish",
"createdAt": "2020-01-10T08:59:35.796Z",
"model": "address",
"entry": {
"id": 1,
"geolocation": {},
"city": "Paris",
"postal_code": null,
"category": null,
"full_name": "Paris",
"createdAt": "2020-01-10T08:47:36.264Z",
"updatedAt": "2020-01-10T08:58:26.210Z",
"publishedAt": "2020-08-29T14:20:12.134Z",
"cover": null,
"images": []
}
}
```
### `entry.unpublish`
当条目未发布时会触发此事件。
🌐 This event is triggered when an entry is unpublished.
**示例有效负载**
```json
{
"event": "entry.unpublish",
"createdAt": "2020-01-10T08:59:35.796Z",
"model": "address",
"entry": {
"id": 1,
"geolocation": {},
"city": "Paris",
"postal_code": null,
"category": null,
"full_name": "Paris",
"createdAt": "2020-01-10T08:47:36.264Z",
"updatedAt": "2020-01-10T08:58:26.210Z",
"publishedAt": null,
"cover": null,
"images": []
}
}
```
### `media.create`
当你在条目创建时或通过媒体界面上传文件时,会触发此事件。
🌐 This event is triggered when you upload a file on entry creation or through the media interface.
**示例有效负载**
```json
{
"event": "media.create",
"createdAt": "2020-01-10T10:58:41.115Z",
"media": {
"id": 1,
"name": "image.png",
"hash": "353fc98a19e44da9acf61d71b11895f9",
"sha256": "huGUaFJhmcZRHLcxeQNKblh53vtSUXYaB16WSOe0Bdc",
"ext": ".png",
"mime": "image/png",
"size": 228.19,
"url": "/uploads/353fc98a19e44da9acf61d71b11895f9.png",
"provider": "local",
"provider_metadata": null,
"createdAt": "2020-01-10T10:58:41.095Z",
"updatedAt": "2020-01-10T10:58:41.095Z",
"related": []
}
}
```
### `media.update`
当你通过媒体接口更换媒体或更新媒体元数据时,会触发该事件。
🌐 This event is triggered when you replace a media or update the metadata of a media through the media interface.
**示例有效负载**
```json
{
"event": "media.update",
"createdAt": "2020-01-10T10:58:41.115Z",
"media": {
"id": 1,
"name": "image.png",
"hash": "353fc98a19e44da9acf61d71b11895f9",
"sha256": "huGUaFJhmcZRHLcxeQNKblh53vtSUXYaB16WSOe0Bdc",
"ext": ".png",
"mime": "image/png",
"size": 228.19,
"url": "/uploads/353fc98a19e44da9acf61d71b11895f9.png",
"provider": "local",
"provider_metadata": null,
"createdAt": "2020-01-10T10:58:41.095Z",
"updatedAt": "2020-01-10T10:58:41.095Z",
"related": []
}
}
```
### `media.delete`
仅当你通过媒体接口删除媒体时才会触发该事件。
🌐 This event is triggered only when you delete a media through the media interface.
**示例有效负载**
```json
{
"event": "media.delete",
"createdAt": "2020-01-10T11:02:46.232Z",
"media": {
"id": 11,
"name": "photo.png",
"hash": "43761478513a4c47a5fd4a03178cfccb",
"sha256": "HrpDOKLFoSocilA6B0_icA9XXTSPR9heekt2SsHTZZE",
"ext": ".png",
"mime": "image/png",
"size": 4947.76,
"url": "/uploads/43761478513a4c47a5fd4a03178cfccb.png",
"provider": "local",
"provider_metadata": null,
"createdAt": "2020-01-07T19:34:32.168Z",
"updatedAt": "2020-01-07T19:34:32.168Z",
"related": []
}
}
```
### `review-workflows.updateEntryStage`
此事件仅适用于 Strapi 的 计划。 当内容被移动到新的审核阶段时,此事件将被触发(参见 [审核工作流](/cms/features/review-workflows#configuration))。
**示例有效负载**
```json
{
"event": "review-workflows.updateEntryStage",
"createdAt": "2023-06-26T15:46:35.664Z",
"model": "model",
"uid": "uid",
"entity": {
"id": 2
},
"workflow": {
"id": 1,
"stages": {
"from": {
"id": 1,
"name": "Stage 1"
},
"to": {
"id": 2,
"name": "Stage 2"
}
}
}
}
```
### `releases.publish` {#releases-publish}
当发布[release](/cms/features/releases)时,将触发该事件。
🌐 The event is triggered when a [release](/cms/features/releases) is published.
**示例有效负载**
```json
{
"event": "releases.publish",
"createdAt": "2024-02-21T16:45:36.877Z",
"isPublished": true,
"release": {
"id": 2,
"name": "Fall Winter highlights",
"releasedAt": "2024-02-21T16:45:36.873Z",
"scheduledAt": null,
"timezone": null,
"createdAt": "2024-02-21T15:16:22.555Z",
"updatedAt": "2024-02-21T16:45:36.875Z",
"actions": {
"count": 1
}
}
}
```
## Webhook 处理的最佳实践 {#best-practices-for-webhook-handling}
🌐 Best practices for webhook handling
- 通过检查标头和有效负载签名来验证传入请求。
- 对失败的 webhook 请求实现重试以处理瞬态错误。
- 记录 webhook 事件以进行调试和监控。
- 使用安全的 HTTPS 端点接收 webhook。
- 设置速率限制以避免被多个 webhook 请求淹没。
:::tip
如果你想了解更多关于如何在 Next.js 中使用 webhooks 的信息,请查看[专门的博客文章](https://strapi.io/blog/how-to-create-an-ssg-static-site-generation-application-with-strapi-webhooks-and-nextjs)。
🌐 If you want to learn more about how to use webhooks with Next.js, please have a look at the [dedicated blog article](https://strapi.io/blog/how-to-create-an-ssg-static-site-generation-application-with-strapi-webhooks-and-nextjs).
:::
# 命令行接口
Source: https://docs.strapi.io/cms/cli
# 命令行接口 (CLI) {#command-line-interface-cli}
🌐 Command Line Interface (CLI)
Strapi 带有功能齐全的命令行接口(CLI),使你可以在几秒钟内搭建和管理项目。CLI 可与 `yarn` 和 `npm` 包管理器一起使用。
🌐 Strapi comes with a full featured Command Line Interface (CLI) which lets you scaffold and manage your project in seconds. The CLI works with both the `yarn` and `npm` package managers.
:::caution
像 `strapi admin:create-user` 这样的交互命令在使用 `npm` 时不会显示提示。请考虑使用 `yarn` 包管理器。
🌐 Interactive commands such as `strapi admin:create-user` don't display prompts with `npm`. Please consider using the `yarn` package manager.
:::
:::note
建议仅在本地安装 Strapi,这需要在所有以下 `strapi` 命令前加上用于项目设置的包管理器(例如 `npm run strapi help` 或 `yarn strapi help`)或专用的 node 包执行器(例如 `npx strapi help`)。
🌐 It is recommended to install Strapi locally only, which requires prefixing all of the following `strapi` commands with the package manager used for the project setup (e.g `npm run strapi help` or `yarn strapi help`) or a dedicated node package executor (e.g. `npx strapi help`).
要使用 `npm` 传递选项,请使用以下语法:`npm run strapi -- --