# Account billing details Source: https://docs.strapi.io/cloud/account/account-billing # Account billing & invoices Through the *Profile* page, accessible by clicking on your profile picture on the top right hand corner of the interface then clicking on **Profile**, you can access the [ *Billing*](#account-billing) and [ *Invoices*](#account-invoices) tabs. ## Account billing The *Billing* tab displays and enables you to modify the billing details and payment method set for the account. The *Payment method* section of the *Billing* tab allows you to manage the credit cards that can be used for the Strapi Cloud projects. The *Billing details* section requires to be filled in, at least for the mandatory fields, as this information will be the default billing details for all Strapi Cloud projects related to your account. ### Adding a new credit card 1. In the *Payment method* section of the *Billing* tab, click on the **Add card** button. 2. Fill in the following fields: | Field name | Description | | --- | --- | | Card Number | Write the number of the credit card to add as payment method. | | Expires | Write the expiration date of the credit card. | | CVC | Write the 3-numbers code displayed at the back of the credit card. | 3. Click on the **Save** button. :::tip The first credit card to be added as payment method for the account will by default be the primary one. It is however possible to define another credit card as primary by clicking on the icon, then **Switch as primary**. ::: ### Deleting a credit card To remove a credit card from the list of payment methods for the account: 1. Click on the icon of the credit card you wish to delete. 2. Click **Remove card**. The card is immediately deleted. :::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 The *Invoices* tab displays the complete list of invoices for all your Strapi Cloud projects. :::strapi Invoices are also available per project. 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). ::: # Profile settings Source: https://docs.strapi.io/cloud/account/account-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**. There are 3 tabs available in the *Profile* interface: [*General*](#general), *Billing* and Invoices (the last 2 are documented in the [Account billing details](/cloud/account/account-billing) section of this documentation). ## General The *General* tab enables you to edit the following details for your account profile: - Details: to see the name associated with your account. - Connected accounts: to manage Google, GitHub, GitLab and email accounts connected with your Strapi Cloud account (see [Managing connected accounts](#managing-connected-accounts)). - Delete account: to permanently delete your Strapi Cloud account (see [Deleting Strapi Cloud account](#deleting-strapi-cloud-account)). ### Managing connected accounts 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. 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. 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. ### Deleting Strapi Cloud account 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. In the *Delete account* section of the *General* tab, click on the **Delete account** button. 2. In the dialog, type `DELETE` in the textbox. 3. Confirm the deletion of your account by clicking on the **Delete** button. # Database Source: https://docs.strapi.io/cloud/advanced/database # Database 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 - A local Strapi project running on `v4.8.2+`. - Credentials for an external database. - If using an existing database, the schema must match the Strapi project schema. ::: :::caution 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 already provides a managed database that is optimized for Strapi. - Using an external database may result in unexpected behavior and/or performance issues (e.g., network latency may impact performance). For performance reasons, it's recommended to host your external database close to the region where your Strapi Cloud project is hosted. You can find where your Strapi Cloud project is hosted in your Project Settings (see [Project Settings > General > Selected Region](/cloud/projects/settings#general)). - Strapi can't provide security or support with external databases used with Strapi Cloud. ::: :::warning 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 The project `./config/database.js` or `./config/database.ts` file must match the configuration found in the [environment variables in database configurations](https://docs.strapi.io/cms/configurations/database#environment-variables-in-database-configurations) section. Before pushing changes, add environment variables to the Strapi Cloud project: 1. Log into Strapi Cloud and click on the corresponding project on the Projects page. 2. Click on the **Settings** tab and choose **Variables** in the left menu. 3. Add the following environment variables: | Variable | Value | Details | | ---------------------------------- | ---------------- |----------| | `DATABASE_CLIENT` | your_db | Should be one of `mysql`, `postgres`, or `sqlite`. | | `DATABASE_HOST` | your_db_host | The URL or IP address of your database host | | `DATABASE_PORT` | your_db_port | The port to access your database | | `DATABASE_NAME` | your_db_name | The name of your database | | `DATABASE_USERNAME` | your_db_username | The username to access your database | | `DATABASE_PASSWORD` | your_db_password | The password associated to this username | | `DATABASE_SSL_REJECT_UNAUTHORIZED` | false | Whether unauthorized connections should be rejected | | `DATABASE_SCHEMA` | public | - | 4. Click **Save**. :::caution To ensure a smooth deployment, it is recommended to not change the names of the environment variables. ::: ## Deployment 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 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. # Email Provider Source: https://docs.strapi.io/cloud/advanced/email # Email Provider 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 Please be advised that Strapi is unable to provide support for third-party email providers. ::: :::prerequisites - A local Strapi project running on `v4.8.2+`. - Credentials for another email provider (see :::caution The file structure must match the above path exactly, or the configuration will not be applied to Strapi Cloud. ::: Each provider will have different configuration settings available. Review the respective entry for that provider in the :::tip 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 Cloud Configuration 1. Log into Strapi Cloud and click on the corresponding project on the Projects page. 2. Click on the **Settings** tab and choose **Variables** in the left menu. 3. Add the required environment variables specific to the email provider. 4. Click **Save**. **Example:** ## Deployment 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 If you want to create a custom email provider, please refer to the [Email providers](/cms/features/email#providers) documentation in the CMS Documentation. ::: # Upload Provider Source: https://docs.strapi.io/cloud/advanced/upload # Upload Provider 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 Please be advised that Strapi is unable to provide support for third-party upload providers. ::: :::prerequisites - A local Strapi project running on `v4.8.2+`. - Credentials for a third-party upload provider (see :::caution The file structure must match the above path exactly, or the configuration will not be applied to Strapi Cloud. ::: Each provider will have different configuration settings available. Review the respective entry for that provider in the ### Configure the Security Middleware 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. To do this in your Strapi project: 1. Navigate to `./config/middleware.js` or `./config/middleware.ts` in your Strapi project. 2. Replace the default `strapi::security` string with the object provided by the upload provider. **Example:** :::tip 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 Cloud Configuration 1. Log into Strapi Cloud and click on the corresponding project on the Projects page. 2. Click on the **Settings** tab and choose **Variables** in the left menu. 3. Add the required environment variables specific to the upload provider. 4. Click **Save**. **Example:** ## Deployment 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 If you want to create a custom upload provider, please refer to the [Providers](/cms/features/media-library#providers) documentation in the CMS Documentation. ::: # Command Line Interface (CLI) Source: https://docs.strapi.io/cloud/cli/cloud-cli # Command Line Interface (CLI) 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 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 login **Alias:** `strapi cloud:login` Log in Strapi Cloud. ```bash strapi login ``` 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 deploy **Alias:** `strapi cloud:deploy` Deploy a new local project (< 100MB) in Strapi Cloud. ```bash strapi deploy ``` 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. Deploying a Strapi project through the CLI creates a project on the Free plan. 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 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. - Some areas in the dashboard that are usually reserved to display information about the git provider will be blank. - Some buttons, such as the **Trigger deploy** button, will be greyed out and unclickable since, unless you have [connected a git repository to your Strapi Cloud project](/cloud/getting-started/deployment-cli#automatically-deploying-subsequent-changes). ::: ## strapi link **Alias:** `strapi cloud:link` Links project in the current folder to an existing project in Strapi Cloud. ```bash strapi link ``` 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 projects **Alias:** `strapi cloud:projects` Lists all Strapi Cloud projects associated with your account. ```bash strapi projects ``` This command retrieves and displays a list of all projects hosted on your Strapi Cloud account. ## strapi logout **Alias:** `strapi cloud:logout` Log out of Strapi Cloud. ```bash strapi logout ``` 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 For Strapi Cloud applications with large amounts of cacheable content, such as images, videos, and other static assets, enabling CDN (Content Delivery Network) caching via the # Strapi Cloud fundamentals Source: https://docs.strapi.io/cloud/getting-started/cloud-fundamentals # Strapi Cloud fundamentals 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. - **Hosting Platform**
Strapi Cloud is a hosting platform that allows to deploy already existing Strapi projects created with Strapi CMS (Content Management System). Strapi Cloud is *not* the SaaS () version of Strapi CMS and should rather be considered as a PaaS (). Feel free to refer to the [CMS documentation](https://docs.strapi.io/cms/intro) to learn more about Strapi CMS. - **Strapi Cloud Pricing Plans**
As a Strapi Cloud user you have the choice between 4 plans: Free, Essential, Pro and Scale. Depending on the plan, you have access to different functionalities, support and customization options (see [Pricing page](https://strapi.io/pricing-cloud) for more details). In this Strapi Cloud documentation, the , , and badges can be displayed below a section's title to indicate that the feature is only available starting from the corresponding paid plan. If no badge is shown, the feature is available on the Free plan. - **Types of Strapi Cloud users**
There can be 2 types of users on a Strapi Cloud project: owners and maintainers. The owner is the one who has created the project and has therefore access to all features and options for the project. Maintainers are users who have been invited to contribute to an already created project by its owner. Maintainers, as documented in the [Collaboration](/cloud/projects/collaboration) page, cannot view and access all features and options from the Strapi Cloud dashboard. - **Support**
The level of support provided by the Strapi Support team depends on the Strapi Cloud plan you subscribed for. The Free plan does not include access to support. The Essential and Pro plans include Basic support while the Scale plan includes Standard support. Please refer to the [dedicated support article](https://support.strapi.io/support/solutions/articles/67000680833-what-is-supported-by-the-strapi-team#Not-Supported) for all details regarding support levels. - **API access in Strapi Cloud vs self-hosted**
The REST and GraphQL APIs behave the same on Strapi Cloud and on self-hosted servers. The only differences are the URLs: - Base API domain: On Strapi Cloud, your API uses the domain of the environment (e.g. `https://.strapiapp.com/api/...`), or your custom domain if you set one (see [Domains documentation](/cloud/projects/settings#domains)). A self-hosted project would use whatever domain you expose. - Media Library URLs: Media fields in REST and GraphQL responses from Strapi Cloud always use the project media domain (e.g. `.media.strapiapp.com`), even when you access the API through a custom domain. Self-hosted projects return URLs from the configured upload provider, so the domain can match your own site or CDN. When you move a project from self-hosted to Strapi Cloud, make sure your frontend reads the absolute URLs returned by the API or accepts the Strapi Cloud media domain. # Strapi Cloud - Dashboard deployment Source: https://docs.strapi.io/cloud/getting-started/deployment # Project deployment with the Cloud dashboard This is a step-by-step guide for deploying your project on Strapi Cloud for the first time, using the Cloud dashboard. :::prerequisites Before you can deploy your Strapi application on Strapi Cloud using the Cloud dashboard, you need to have the following prerequisites: * Strapi version `4.8.2` or higher * Project database must be compatible with PostgreSQL. Strapi does not support and does not recommend using any external databases, though it's possible to configure one (see [advanced database configuration](/cloud/advanced/database)). * Project source code hosted on 5. Set up your Strapi Cloud project. 5.a. Fill in the following information: | Setting name | Instructions | |--------------|---------------------------------------------------------------------------------------------------------| | Display name | Write the name of your Strapi app, this is fetched from the repository name but can be edited. It is automatically converted to slug format (`my-strapi-app`). | | Git branch | Choose from the drop-down the branch you want to deploy. | | Deploy on push | Tick this box to automatically trigger a deployment when changes are pushed to your selected branch. When disabled, you will need to manually deploy the latest changes. | | Region | Choose the geographic location of the servers where your Strapi application is hosted. Selected region can either be US (East), Europe (West), Asia (Southeast) or Oceania. | :::note The Git branch and "Deploy on push" settings can be modified afterwards through the project's settings, however the hosting region can only be chosen during the creation of the project (see [Project Settings](/cloud/projects/settings)). ::: 5.b. (optional) Click on **Show advanced settings** to fill in the following options: | 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 You can use environment variable to connect your project to an external database rather than the default one used by Strapi Cloud (see [database configuration](/cms/configurations/database#environment-variables-in-database-configurations) for more details). If you would like to revert and use Strapi's default database again, you have to remove your `DATABASE_` environment variables (no automatic migration implied). You can also set up here a custom email provider. Sendgrid is set as the default one for the Strapi applications hosted on Strapi Cloud (see [providers configuration](/cms/features/email#providers) for more 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. To upgrade your project to a paid plan, you will need to fill in your billing information in the **Billing** section of your Profile. Skip to step 5 of the section below to finalize the creation of your project. ::: 1. Click on the **Continue to billing** button. You will directly be redirected to the second and final project deployment interface. There you can review all your new project setup information, enter payment & billing details and receive your invoice. 2. Review your project: make sure the plan and setup information are correct. If needed, click the **Edit** button to navigate back to the first step of the project creation and fix any mistake. 3. In the Payment section, fill in at least all mandatory elements for *Payment method* and *Billing information*. 4. Check your invoice which informs you of what should be paid now and the following month. Optionally, you can enter a *Discount code* if you have one. 5. Click on the **Create project** button to finalize the creation of your new Strapi Cloud 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. 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. ::: Once you 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. ## What to do next? 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: - Invite other users to [collaborate on your project](/cloud/projects/collaboration). - Check out the [deployments management documentation](/cloud/projects/deploys) to learn how to trigger new deployments for your project. # Strapi Cloud - CLI deployment Source: https://docs.strapi.io/cloud/getting-started/deployment-cli # Project deployment with the Command Line Interface (CLI) This is a step-by-step guide for deploying your project on Strapi Cloud for the first time, using the Command Line Interface. :::prerequisites Before you can deploy your Strapi application on Strapi Cloud using the Command Line Interface, you need to have the following prerequisites: - Have a Google, GitHub or GitLab account. - Have an already created Strapi project (see [Installing from CLI in the CMS Documentation](/cms/installation/cli)), stored locally. The project must be less than 100MB. - Have available storage in your hard drive where the temporary folder of your operating system is stored. ::: ## Logging in to Strapi Cloud 1. Open your terminal. 2. Navigate to the folder of your Strapi project, stored locally on your computer. 3. Enter the following command to log into Strapi Cloud: 4. In the browser window that opens automatically, confirm that the code displayed is the same as the one written in the terminal message. 5. Still in the browser window, choose whether to login via Google, GitHub or GitLab. The window should confirm the successful login soon after. ## Deploying your project 1. From your terminal, still from the folder of your Strapi project, enter the following command to deploy the project: 2. Follow the progression bar in the terminal until confirmation that the project was successfully deployed with Strapi Cloud. Deploying the project will create a new Strapi Cloud project on the Free plan. ### Automatically deploying subsequent changes 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. Another option is to enable automatic deployment through a git repository. To do so: 1. Host your code on a git repository, such as or . 2. Connect your Strapi Cloud project to the repository (see the _Connected repository_ setting in [Projects Settings > General](/cloud/projects/settings#general)). 3. Still in _Projects Settings > General_ tab, tick the box for the "Deploy the project on every commit pushed to this branch" setting. From now on, a new deployment to Strapi Cloud will be triggered any time a commit is pushed to the connected git repository. :::note 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? 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: - Visit the Cloud dashboard to follow [insightful metrics and information](/cloud/projects/overview) on your Strapi project. - Check out the full [Command Line Interface documentation](/cloud/cli/cloud-cli) to learn about the other commands available. # Project deployment Source: https://docs.strapi.io/cloud/getting-started/deployment-options # Project deployment with Strapi Cloud You have 2 options to deploy your project with Strapi Cloud: - either with the user interface (UI), meaning that you will perform all the actions directly on the Strapi Cloud dashboard, - or using the Cloud Comment Line Interface (CLI), meaning that you will only interact with a terminal. The guides below will guide you through all the steps for each of the deployment options. # Welcome to the Strapi Cloud Documentation! Source: https://docs.strapi.io/cloud/getting-started/intro # Welcome to the Strapi Cloud Documentation! 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? built on top of Strapi, the open-source headless CMS. ::: :::prerequisites The typical workflow, which is recommended by the Strapi team, is: 1. Create your Strapi application locally (v4.8.2 or later). 2. Optionally, extend the application with plugins or custom code. 3. Version the application's codebase through your git provider (GitHub or GitLab). 4. Deploy the application with 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 is built on top of Strapi, an open-source, community-oriented project. The Strapi team has at heart to share their vision and build the future of Strapi with the Strapi community. This is why the is open: as all insights are very important and will help steer the project in the right direction. Any community member is most welcome to share ideas and opinions there. You can also join , the , and the and benefit from the years of experience, knowledge, and contributions by the Strapi community as a whole. ::: # Information on billing & usage Source: https://docs.strapi.io/cloud/getting-started/usage-billing # Information on billing & usage This page contains general information related to the usage and billing of your Strapi Cloud account and projects. 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: | Feature | Free | Essential | Pro | Scale | | -------------------------------- | ----- | --------- | --- | ----- | | **Database Entries** | 500 | Unlimited* | Unlimited* | Unlimited* | | **Asset Storage** | 10GB | 50GB | 250GB | 1,000GB | | **Asset Bandwidth (per month)** | 10GB | 50GB | 500GB | 1,000GB | | **API Requests (per month)** | 10,000 | 100,000 | 1,000,000 | 10,000,000 | | | | | | | | **Backups** | N/A | N/A | Weekly | Daily | | **Custom domains** | N/A | Included | Included | Included | | **Environments** | N/A | N/A | 0 included (up to 99 extra) | 1 included (up to 99 extra) | | **Emails (per month)** | 100 | Unlimited* | Unlimited* | Unlimited* | :::strapi Additional information on usage and features - General features & usage: - Database entries are the number of entries in your database. - Asset storage is the amount of storage used by your assets. - Asset bandwidth is the amount of bandwidth used by your assets. - API requests are the number of requests made to your APIs. This includes requests to the GraphQL and REST APIs, excluding requests for file and media assets counted towards CDN bandwidth and storage. - Cloud specific feature: - Backups refers to the automatic backups of Strapi Cloud projects (see [Backups documentation](/cloud/projects/settings#backups) for more information on the feature). - Custom domains refer to the ability to define a custom domain for your Strapi Cloud (see [Custom domains](/cloud/projects/settings#connecting-a-custom-domain)). - Environments refers to the number of environments included in the plan on top of the default production environment (see [Environments](/cloud/projects/settings#environments) documentation for more information on the feature). ::: :::caution The Free Plan is for personal, non-commercial use only Commercial use means any project made for financial gain, including: - Accepting or processing payments on your site - Accepting or receiving payment to create, update, or host the site - Advertising, promoting, or selling products or services - Hosting or serving advertisements for any 3rd party For more information, visit [Strapi Cloud-Legal](https://strapi.io/cloud-legal) ::: :::info Scale-to-zero and cold start on the Free plan 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 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 a project's 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. 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 is based on the usage of your Strapi Cloud account and projects. You will be billed monthly for the usage of your account and applications. You can view your usage and billing information in the section of your Strapi Cloud account. ### Overages :::caution Overages are not allowed on the Free plan. ::: If you exceed the limits of your plan for API Requests, Asset Bandwidth, or Asset Storage, you will be charged for the corresponding overages. 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 according to the following rates: | Feature | Rate | | --- | --- | | **API Requests** | $1.50 / 25k requests | | **Asset Bandwidth** | $30.00 / 100GB | | **Asset Storage** | $0.60 / GB per month | ### Project suspension Projects may end up in a **Suspended** state for various reasons, including: not paying the invoice, exceeding the limits of your free plan, or violating the . If your project is suspended, you will no longer be able to access the application or trigger new deployments. You will also be unable to access the Strapi admin panel. You can view the status of your project in the section of your Strapi Cloud account and you will be notified by email. :::warning If you do not resolve the issue within 30 days, your suspended project will be deleted and all data will be permanently lost. To avoid this situation, you will be sent a first email when your project becomes suspended, then another email every 5 days until one week left, to remind you to solve the issue. The last week before the deletion of the project, you will be sent 3 more emails: 6 days, 3 days and 1 day before your project is finally deleted. ::: #### Project suspension for exceeding the Free plan limits 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: - Users cannot trigger new deployments - Access to the application is blocked - Users cannot make changes to the project’s settings To reactivate the project immediately, users can upgrade to a paid plan. #### Project suspension after subscription cancellation If you don't pay the invoice, then after few payment attempts the subscription of your project will automatically be canceled and the project will be suspended. To reactivate your project, you can click on a *Reactivate subscription* button visible in the *Settings > Billing & Usage* tab of your suspended project (to reactivate the subscription you are on) #### Project suspension for other reasons 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 If you want to cancel your Strapi Cloud subscription, you have 2 options: - either change your project's subscription to the free plan (see [Downgrading to another plan](/cloud/projects/settings#downgrading-to-another-plan) documentation), - or completely delete your project (see [Deleting Strapi Cloud project](/cloud/projects/settings#deleting-strapi-cloud-project) documentation). # Collaboration Source: https://docs.strapi.io/cloud/projects/collaboration # Collaboration on projects 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: - Cannot share the project themselves to someone else - Cannot delete the project from the project settings - Cannot access the *Billing* section of project settings ## Sharing a project To invite a new maintainer to collaborate on a project: 1. From the *Projects* page, click on the project of your choice to be redirected to its dashboard. 2. Click on the **Share** button located in the dashboard's header. 3. In the *Share [project name]* dialog, type the email address of the person to invite in the textbox. A dropdown indicating "Invite [email address]" should appear. 4. Click on the dropdown: the email address should be displayed in a purple box right below the textbox. 5. (optional) Repeat steps 3 and 4 to invite more people. Email addresses can only entered one by one but invites can be sent to several email addresses at the same time. 6. Click on the **Send** button. 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 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 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: - Pending: the invitation email has been sent but the maintainer hasn't acted on it yet. - Expired: the email has been sent over 72 hours ago and the invitation expired. For Expired statuses, it is possible to send another invitation email by clicking on the **Manage** button, then **Resend invite**. ### Revoking maintainers To revoke a maintainer's access to the project dashboard: 1. Click on the **Share** button in the project dashboard's header. 2. In the list of *People with access*, find the maintainer whose access to revoke and click on the **Manage** button. 3. Click on the **Revoke** button. 4. In the confirmation dialog, click again on the **Revoke** button. 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. ::: # Deployments management Source: https://docs.strapi.io/cloud/projects/deploys # Deployments management The creation of a new Strapi Cloud project automatically trigger the deployment of that project. After that, deployments can be: - manually triggered whenever needed, [from the Cloud dashboard](#triggering-a-new-deployment) or [from the CLI](/cloud/cli/cloud-cli#strapi-deploy), - or automatically triggered everytime a new commit is pushed to the branch, if the Strapi Cloud project is connected to a git repository and the "deploy on push" option is enabled (see [Project settings](/cloud/projects/settings#modifying-git-repository--branch)). Ongoing deployments can also be [manually canceled](#cancelling-a-deployment) if needed. ## Triggering a new deployment 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 If for any reason you want to cancel an ongoing and unfinished deployment: 1. Go to the *Deployment details* page of the latest triggered deployment (see [Accessing log details](/cloud/projects/deploys-history#accessing-deployment-details--logs)). 2. Click on the **Cancel deployment** button in the top right corner. The status of the deployment will automatically change to *Canceled*. :::tip 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 ![Cancel button](/img/assets/icons/clear.svg) button for cancelling the deployment. ::: # Deployment history & logs Source: https://docs.strapi.io/cloud/projects/deploys-history # Deployment history and logs {#deploy-history-and-logs} 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 the deployment history {#viewing-deploy-history} In the *Deployments* tab is displayed a chronological list of cards with the details of all historical deployments for your project. , with a direct link to your git provider, and commit message - Deployment status: - *Deploying* - *Done* - *Canceled* - *Build failed* - *Deployment failed* - Last deployment time (when the deployment was triggered and the duration) - Branch ## Accessing deployment details & logs From the *Deployments* tab, you can hover a deployment card to make the ![See logs button](/img/assets/icons/Eye.svg) **Show details** button appear. Clicking on this button will redirect you to the *Deployment details* page which contains the deployment's detailed logs. , with a direct link to your git provider, and commit message used for this deployment - *Status*, which can be *Building*, *Deploying*, *Done*, *Canceled*, *Build failed*, or *Deployment failed* - *Source*: the branch and commit message for this deployment - *Duration*: the amount of time the deployment took and when it occurred # Notifications Source: https://docs.strapi.io/cloud/projects/notifications # Notifications The Notification center can be opened by clicking the bell icon in the top navigation of the Cloud dashboard. 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: - *deployment completed*: when a deployment is successfully done. - *Build failed*: when a deployment fails during the build stage. - *deployment failed*: when a deployment fails during the deployment stage. - *deployment triggered*: when a deployment is triggered by a new push to the connected repository. This notification is however not sent when the deployment is triggered manually. :::note All notifications older than 30 days are automatically removed from the Notification center. ::: # Projects overview Source: https://docs.strapi.io/cloud/projects/overview # Projects overview 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: * the project name * the last successful deployment’s date of the Production environment * the current status of the project: * *Disconnected*, if the project repository is not connected to Strapi Cloud * *Suspended*, if the project has been suspended (refer to [Project suspension](/cloud/getting-started/usage-billing#project-suspension) to reactivate the project) * *Incompatible version*, if the project is using a Strapi version that is not compatible with Strapi Cloud Each project card also displays a menu icon to access the following options: * **Visit App**: to be redirected to the application * **Go to Deployments**: to be redirected to the [*Deployment*](/cloud/projects/deploys) page * **Go to Settings**: to be redirected to the [*Settings*](/cloud/projects/settings) page :::tip Click on the * Product updates* button in the navigation bar to check out the latest features and fixes released. ::: ## 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: - use the **Share** button to invite users to collaborate on the project (see [Collaboration](/cloud/projects/collaboration)) and see the icons of those who have already been invited , - use the **Settings** button to access the settings of the project and its existing environments , - choose which environment to visualise for the project or add a new environment , - trigger a new deployment (see [Deployments management](/cloud/projects/deploys)) and visit your application . Your project's dashboard also displays: - the *Deployments* and *Runtime logs* tabs, to see the deployments history (more details in [Deploy history and logs](/cloud/projects/deploys-history)) and the runtime logs of the project (see [dedicated documentation page](/cloud/projects/runtime-logs)) - the project and environment details in a box on the right of the interface , including: - the number of API calls, - the current usage for asset bandwidth and storage, - the name of the branch and a **Manage** button to be redirect to the branch settings (see [Modifying git repository & branch](/cloud/projects/settings#modifying-git-repository--branch)), - the name of the base directory, - the Strapi version number, - the Strapi app's url. # Runtime logs Source: https://docs.strapi.io/cloud/projects/runtime-logs # Runtime logs From a chosen project's dashboard, the *Runtime logs* tab displays the live logs of the project. :::note - The *Runtime logs* are only accessible once the project is successfully deployed. - Runtime logs are not live for projects on the Free plan and are reset each time the application is scaled to zero due to inactivity. ::: # Project settings Source: https://docs.strapi.io/cloud/projects/settings # Project settings From a chosen project's dashboard, the **Settings** button, located in the header, enables you to manage the configurations and settings for your Strapi Cloud project and its environments. 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 There are 5 tabs available for the project's settings: - [*General*](#general), - [*Environments*](#environments), - [*Billing & Usage*](#billing--usage), - [Plans](#plans), - and [Invoices](#invoices). ### General The *General* tab for the project-level settings enables you to check and update the following options for the project: - *Basic information*, to see: - the name of your Strapi Cloud project — used to identify the project on the Cloud Dashboard, Strapi CLI, and deployment URLs — and change it (see [Renaming project](#renaming-project)). - the chosen hosting region for your Strapi Cloud project, meaning the geographical location of the servers where the project and its data and resources are stored. The hosting region is set at project creation (see [Project creation](/cloud/getting-started/deployment)) and cannot be modified afterwards. - the project's metadata, including the Production app internal name and the Subscription ID, which can be useful for debugging & support purposes. - *Strapi CMS license key*: to enable and use some CMS features directly on your Cloud project (see [Pricing page](https://strapi.io/pricing-self-hosted) to purchase a license). - *Connected Git repository*: to change the repository and branch used for your project (see [Modifying git repository & branch](#modifying-git-repository--branch)). Also allows to enable/disable the "deploy on push" option. - *Danger zone*, with: - *Transfer ownership*: for the project owner to transfer the ownership of the Cloud project to an already existing maintainer (see [Transferring project ownership](#transferring-project-ownership)). - *Delete project*: to permanently delete your Strapi Cloud project (see [Deleting Strapi Cloud project](#deleting-strapi-cloud-project)). #### Renaming project The project name is set at project creation (see [Project creation](/cloud/getting-started/deployment)) and can be modified afterwards via the project's settings. 1. In the *Basic information* section of the *General* tab, click on the edit button. 2. In the dialog, write the new project name of your choice in the *Project name* textbox. 3. Click on the **Rename** button to confirm the project name modification. #### Adding a CMS license key {#adding-cms-license-key} A CMS license key can be added and connected to a Strapi Cloud project to unlock additional Strapi CMS features across all of the project’s environments. The CMS features that will be accessible via the license key depend on the type of license that was purchased: please refer to the for more information and/or to purchase a license. :::note 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. In the *Strapi CMS license key* section, click on the **Add license** button. 2. In the dialog, paste your license key in the field. 3. Click on the **Save & deploy** button for the changes to take effect. 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. ::: #### Modifying git repository & branch 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's settings, it is possible to update the project's repository or switch to another git provider. :::caution 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. In the *Connected git repository* section of the *General* tab, click on the **Update repository** button. You will be redirected to another interface. 2. (optional) If you wish to not only update the repository but switch to another git provider, click on the **Switch Git provider** button at the top right corner of the interface. You will be redirected to the chosen git provider's authorization settings before getting back to the *Update repository* interface. 3. In the *Update repository* section, fill in the 2 available settings: | Setting name | Instructions | | --------------- | ------------------------------------------------------------------------ | | Account | Choose an account from the drop-down list. | | Repository | Choose a repository from the drop-down list. | 4. In the *Select Git branches* section, fill in the available settings for any of your environments. Note that the branch can be edited per environment via its own settings, see [General (environment)](#environments). | Setting name | Instructions | | --------------- | ------------------------------------------------------------------------ | | Branch | Choose a branch from the drop-down list. | | Base directory | Write the path of the base directory in the textbox. | | Auto-deploy | Tick the box to automatically trigger a new deployment whenever a new commit is pushed to the selected branch. Untick it to disable the option. | 5. Click on the **Save & deploy** button for the changes to take effect. #### Transferring project ownership {#transferring-project-ownership} 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: - The project must be on a paid plan, with no currently expired card and/or unpaid bills. - The maintainer must have filled their billing information. - No already existing ownership transfer must be pending for the project. 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. In the *Danger zone* section of the *General* tab, click on the **Transfer ownership** button. 2. In the dialog: - If you are the project owner: choose the maintainer who should be transferred the ownership by clicking on **...** > **Transfer ownership** associated with their name. - If you are a maintainer: find yourself in the list and click on **...** > **Transfer ownership** associated with your name. 3. Confirm the transfer/request in the new dialog by clicking on the **Transfer ownership** button. 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 Once the ownership transfer is done, the project will be disconnected from Strapi Cloud. As new owner, make sure to go to the *General* tab of project settings to reconnect the project. ::: #### Deleting Strapi Cloud project You can delete any Strapi Cloud project, but it will be permanent and irreversible. Associated domains, deployments and data will be deleted as well and the subscription for the project will automatically be canceled. 1. In the *Danger zone* section of the *General* tab, click on the **Delete project** button. 2. In the dialog, select the reason why you are deleting your project. If selecting "Other" or "Missing feature", a textbox will appear to let you write additional information. 3. Confirm the deletion of your project by clicking on the **Delete project** button at the bottom of the dialog. ### Environments {#environments} The *Environments* tab allows to see all configured environments for the Strapi Cloud project, as well as to create new ones. Production is the default environment, which cannot be deleted. Other environments can be created (depending on the subscription plan for your project) to work more safely on isolated instances of your Strapi Cloud project (e.g. a staging environment where tests can be made before being available on production). :::tip Clicking on the **Manage** button for any environment will redirect you to the environment's own general settings, where it is possible to change the Node version, edit the git branches and delete or reset the environment. Please [refer to the dedicated documentation](#environments) for more information. ::: :::tip A new environment can also be added from the [project dashboard](/cloud/projects/overview#accessing-a-projects-dashboard). ::: To create a new environment: 1. Click on the **Add a new environment** button. 2. In the dialog that opens, you can see the price for the new environment and the date of the next invoice. 3. Fill in the available settings: | Setting name | Instructions | | ---------------- | ------------------------------------------------------------------------ | | Environment name | (mandatory) Write a name for your project's new environment. | | Git branch | (mandatory) Select the right branch for your new environment. | | Base directory | Write the name of the base directory of your new environment. | | Import variables | Tick the box to import variable names from an existing environment. Values will not be imported, and all variables will remain blank. | | Deploy on push | Tick this box to automatically trigger a deployment when changes are pushed to your selected branch. When disabled, you will need to manually deploy the latest changes. | 4. Click on the **Add environment** button to create your project's new environment. You will then be redirected to your *Project dashboard* where you will be able to follow your new environment's creation and first deployment. :::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 The *Billing & Usage* displays your next estimated payment, all information on the current subscription plan and a detailed summary of the project's and its environments' usage. It also allows you to add new environments (please [refer to the documentation in the Environments section](#environments)) for your project. Through this tab, you also have the possibility to: - click the **Change** button to be redirected to the *Plans* tab, where you can change you subscription plan ([see related documentation](#plans)), - click the **Edit** button in order to set a new payment method (see [related documentation](/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 In the Usage section of the *Billing & Usage* tab, you can see the current monthly usage of your project compared to the maximum usage allowed by your project's subscription. Use the arrows in the top right corner to see the project's usage for any chosen month. Note also that if your usage indicates that another subscription plan would fit better for your project, a message will be displayed in the *Billing & Usage* tab to advise which plan you could switch to. ::: ### Plans The *Plans* tab displays an overview of the available Strapi Cloud plans and allows you to upgrade or downgrade from your current plan to another. :::info Strapi recently launched [new Cloud plans](https://strapi.io/pricing-cloud). For now, you can [downgrade](#downgrading-to-another-plan) or [upgrade](#upgrading-to-another-plan) to another plan directly from the Cloud dashboard, under the **Settings** > **Plans** section. If your project was created before the new plans were released, it may be on a *legacy* plan—deprecated but still supported. You can sidegrade to a new plan if desired (see [downgrade section](#downgrading-to-another-plan)). ::: #### Upgrading to another plan Strapi Cloud plan upgrades to another, higher plan are immediate and can be managed for each project via the project settings. :::note When using the Free plan, the buttons to upgrade to another plan are greyed out and unusable until you have filled in your billing information. Please refer to [Account billing details](/cloud/account/account-billing) for more information. ::: To upgrade your current plan to a higher one: 1. In the *Plans* tab of your project's settings, click on the **Upgrade** button of the plan you want to upgrade to. 2. In the window that opens, check the payment details that indicate how much you will have to pay immediately after confirming the upgrade, and the available options. a. (optional) Click the **Edit** button to select another payment method. b. (optional) Click **I have a discount code**, enter your discount code in the field, and click on the **Apply** button. 3. Click on the **Upgrade to [plan name]** button to confirm the upgrade of your Strapi project to another plan. #### Downgrading to another plan Strapi Cloud plan downgrades can be managed for each project via the project settings. Downgrades are however not immediately effective: the higher plan will still remain active until the end of the current month (e.g. if you downgrade from the Scale plan to the Pro plan on June 18th, your project will remain on the Scale plan until the end of the month: on July 1st, the Pro plan will be effective for the project). :::caution 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 the overages. You may also lose access to some features: for example, downgrading to the Essential plan which doesn't include the Backups feature, would make you lose all your project's backups. Please refer to [Information on billing & usage](/cloud/getting-started/usage-billing) for more information. Note also that you cannot downgrade if you have additional environments (i.e. extra environments that have been purchased, not the default or included environments). For instance, if you wish to downgrade from the Pro plan to the Essential plan, you first need to delete all additional environments that have been configured (see [Resetting & Deleting environment](#resetting--deleting-environment)), for the **Downgrade** button to be displayed and available again. ::: To downgrade your current plan to a lower one: 1. In the *Plans* tab of your project's settings, click on the **Downgrade** button of the plan you want to downgrade to. 2. In the window that opens, check the information related to downgrading. 3. Click on the **Downgrade** button to confirm the downgrade of your Strapi project's plan. :::tip Downgrades are effective from the 1st of the following month. Before that date, you can click on the **Cancel downgrade** button to remain on the current plan. ::: ### Invoices The *Invoices* tab displays the full list of invoices for your Strapi Cloud project as well as their status. :::strapi Invoices are also available in your profile settings. 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). ::: No invoice is issued for the Free plan. ## Environment-level settings 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*](#configuration), - [*Backups*](#backups), which are only available for the production environment, - [*Domains*](#domains), - and [*Variables*](#variables). ### Configuration The *Configuration* tab for the environment-level settings enables you to check and update the following options for the project: - *Basic information*, to see: - the name of your Strapi Cloud project's environment. The environment name is set when it is created and cannot be modified afterwards. - the Node version of the environment: to change the Node version of the project (see [Modifying Node version](#modifying-node-version)). - the app's internal name for the environment, which can be useful for debug & support purposes. - *Connected branch*: to change the branch of the GitHub repository used for your environment (see [Editing Git branch](#editing-git-branch)). Also allows to enable/disable the "deploy on push" option. - *Danger zone*: to reset or permanently delete your Strapi Cloud project's environment (see [Resetting & Deleting environment](#resetting--deleting-environment)). #### Modifying Node version 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. In the *Basic information* section of the *Configuration* tab, click on the *Node version*'s edit button. 2. Using the *Node version* drop-down in the dialog, click on the version of your choice. 3. Click on **Save**, or **Save & deploy** if you want the changes to take effect immediately. :::tip Ensure the Node version configured in your Strapi project matches the Node version shown in your project’s dashboard before deploying. ::: #### Editing Git branch 2. In the *Edit branch* dialog, edit the available settings. Note that the branch can be edited for all environments at the same time via the project's settings, see [General](#general). | Setting name | Instructions | | --------------- | ------------------------------------------------------------------------ | | Selected branch | (mandatory) Choose a branch from the drop-down list. | | Base directory | Write the path of the base directory in the textbox. | | Deploy the project on every commit pushed to this branch | Tick the box to automatically trigger a new deployment whenever a new commit is pushed to the selected branch. Untick it to disable the option. | 3. Click on the **Save & deploy** button for the changes to take effect. #### Resetting & Deleting environment 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 not be neither reset nor deleted. ##### Resetting an environment Resetting an environment deletes all environments data and resets the variables to their default. To do so: 1. In the *Danger zone* section of the *Configuration* tab, click on the **Reset environment** button. 2. In the dialog that opens, click on the **Continue** button to confirm the environment reset. 3. Fill in the available fields to reset the environment: | Setting name | Instructions | | --------------- | ------------------------------------------------------------------------ | | Environment name | (mandatory) Write a name for your project's new environment. | | Git branch | (mandatory) Choose a branch from the drop-down list. | | Base directory | Write the path of the base directory in the textbox. | | Import variables | Tick the box to import variable names from an existing environment. Values will not be imported, and all variables will remain blank. | | Auto-deploy | Deploy the project on every commit pushed to this branch | Tick the box to automatically trigger a new deployment whenever a new commit is pushed to the selected branch. Untick it to disable the option. | 4. Click on the **Reset** button. ##### Deleting an environment 1. In the *Danger zone* section of the *Configuration* tab, click on the **Delete environment** button. 2. Write in the textbox your *Environment name*. 3. Click on the **Delete environment** button to confirm the deletion. ### Backups {#backups} The *Backups* tab informs you of the status and date of the latest backup of your Strapi Cloud projects. The databases associated with all existing Strapi Cloud projects are indeed automatically backed up (weekly for Pro plans and daily for Scale plans). Backups are retained for a 28-day period. Additionally, you can create a single manual backup. :::note Notes - The backup feature is not available for Strapi Cloud projects on the Free or Essential plans. You will need to upgrade to the Pro or Scale plan to enable automatic backups and access the manual backup option. - Backups include only the database of your default Production environment. Assets uploaded to your project and databases from any secondary environments are not included. - The manual backup option becomes available shortly after the project’s first successful deployment. ::: :::tip 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 To create a manual backup, in the *Backups* section, click on the **Create backup** button. 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 If you need to restore a backup of your project: 1. In the *Backups* section, click on the **Restore backup** button. 2. In the dialog, choose one of the available backups (automatic or manual) of your project in the *Choose backup* drop-down. 3. Click on the **Restore** button of the dialog. Once the restoration is finished, your project will be back to the state it was at the time of the chosen backup. You will be able to see the restoration timestamp and the backup restored in the *Backups* tab. 4. The timestamp of the last completed restoration will be displayed to help you track when the project was last restored. #### Downloading a backup If you need to download a backup of your project: 1. In the *Backups* section, click on the **Download backup** button. 2. In the dialog, choose one of the available backups (automatic or manual) of your project in the *Choose backup* drop-down. 3. Click on the **Download** button of the dialog to download the chosen backup's archive file in `.sql` format. :::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 The *Domains* tab enables you to manage domains and connect new ones. All existing domains for your Strapi Cloud project are listed in the *Domains* tab. For each domain, you can: - see its current status: - Active: the domain is currently confirmed and active - Pending: the domain transfer is being processed, waiting for DNS changes to propagate - Failed: the domain change request did not complete as an error occured - click the edit button to access the settings of the domain - click the delete button to delete the 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. Click the **Connect new domain** button. 2. In the window that opens, fill in the following fields: | Setting name | Instructions | | ------------------------- | ------------------------------------------------------------------------- | | Domain name | Type the new domain name (e.g. *custom-domain-name.com*) | | Hostname | Type the hostname (i.e. address end-users enter in web browser, or call through APIs). | | Target | Type the target (i.e. actual address where users are redirected when entering hostname). | | Set as default domain | Tick the box to make the new domain the default one. | 3. Click on **Save**, or **Save & deploy** if you want the changes to take effect immediately. :::tip To finish setting up your custom domain, in the settings of your domain registar 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 When using custom domains, these domains do not apply to the URLs of uploaded assets. Uploaded assets keep the Strapi Cloud project-based 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`. Media library queries over REST or GraphQL always return the project media domain on Strapi Cloud. If you move from a self-hosted project, where media URLs can match your own domain or CDN, plan to keep using the absolute URLs from the API or adjust your frontend to allow the Strapi Cloud media domain (see [Cloud Fundamentals](/cloud/cloud-fundamentals) for more details). ::: ### Variables 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. In the *Variables* tab are listed both the default and custom environment variables for your Strapi Cloud project. Each variable is composed of a *Name* and a *Value*. #### Managing environment variables Hovering on an environment variable, either default or custom, displays the following available options: - **Show value** to replace the `*` characters with the actual value of a variable. - **Copy to clipboard** to copy the value of a variable. - **Actions** to access the Edit and Delete buttons. - When editing a default variable, the *Name* cannot be modified and the *Value* can only be automatically generated using the Generate value button. Don't forget to **Save**, or **Save & deploy** if you want the changes to take effect immediately. - When editing a custom variable, both the *Name* and *Value* can be modified by writing something new or by using the Generate value button. Don't forget to **Save**, or **Save & deploy** if you want the changes to take effect immediately. - When deleting a variable, you will be asked to confirm by selecting **Save**, or **Save & deploy** if you want the changes to take effect immediately. :::tip Use the search bar to find more quickly an environment variable in the list! ::: #### Creating custom environment variables 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. In the *Custom environment variables* section, click on the **Add variable** button. 2. Write the *Name* and *Value* of the new environment variable in the same-named fields. Alternatively, you can click on the icon to generate automatically the name and value. 3. (optional) Click on **Add another** to directly create one or more other custom environment variables. 4. Click on the **Save** button to confirm the creation of the custom environment variables. To apply your changes immediately, click on **Save & deploy**. # 管理面板定制 Source: https://docs.strapi.io/cms/admin-panel-customization # 管理面板定制 {#admin-panel-customization} ¥Admin panel customization Strapi 的前端部分 ¥The **front-end part of Strapi** 称为管理面板。管理面板提供了一个图形用户界面,可帮助你构建和管理可通过 Content API 访问的内容。要了解管理面板的概览,请参阅 [入门 > 管理面板](/cms/features/admin-panel) 页面。 ¥is called the admin panel. The admin panel presents a graphical user interface to help you structure and manage the content that will be accessible through the Content API. To get an overview of the admin panel, please refer to the [Getting Started > Admin panel](/cms/features/admin-panel) page. 从开发者的角度来看,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: * 自定义管理面板的某些部分,以更好地体现你的品牌标识(徽标、网站图标)或语言。 ¥Customize some parts of the admin panel to better reflect your brand identity (logos, favicon) or your language, * 替换管理面板的其他部分,例如富文本编辑器和打包器。 ¥Replace some other parts of the admin panel, such as the Rich text editor and the bundler, * 扩展主题或管理​​面板以添加新功能或自定义现有用户界面。 ¥Extend the theme or the admin panel to add new features or customize the existing user interface. ## 一般注意事项 {#general-considerations} ¥General considerations :::prerequisites 在更新代码以自定义管理面板之前: ¥Before updating code to customize the admin panel: * 将现在无效的任何配置文件重命名为新名称,并更新代码以查找该路径。 ¥Rename the default `app.example.tsx|js` file into `app.ts|js`. * 在 `/src/admin/` 中创建一个新的 `extensions` 文件夹。 ¥Create a new `extensions` folder in `/src/admin/`. * 如果你想在开发过程中实时看到你的更改,请确保管理面板服务器正在运行(如果你没有更改管理面板的默认 [主机、端口和路径](/cms/configurations/admin-panel#admin-panel-server),通常使用 `yarn develop` 或 `npm run develop` 命令完成)。 ¥If you want to see your changes applied live while developing, ensure the admin panel server is running (it's usually done with the `yarn develop` or `npm run develop` command if you have not changed the default [host, port, and path](/cms/configurations/admin-panel#admin-panel-server) of the admin panel). ::: 大多数基本的管理面板自定义将在 `/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 代码库中的详细示例 * 你可以查看完整的翻译键,例如更改欢迎消息,[在 GitHub 上](https://github.com/strapi/strapi/blob/develop/packages/core/admin/admin/src/translations)。 ¥You can see the full translation keys, for instance to change the welcome message, [on 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) 中也包含浅色和深色。 ¥Light and dark colors are also found [on 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 应用可以使用 2 个不同的打包器,[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 {#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 插件开发者,你希望开发一个 Strapi 插件,每次安装在任何 Strapi 应用中时,都会扩展管理面板。 ¥As a Strapi plugin developer, you want to develop a Strapi plugin that extends the admin panel **everytime it's installed in any Strapi application**. 👉 这可以通过利用 [管理面板 API 插件](/cms/plugins-development/admin-panel-api) 来完成。 ¥👉 This can be done by taking advantage of the [Admin Panel API for plugins](/cms/plugins-development/admin-panel-api). * 作为 Strapi 开发者,你希望为只需要扩展 Strapi 应用特定实例的 Strapi 用户开发独特的解决方案。 ¥As a Strapi developer, you want to develop a unique solution for a Strapi user who only needs to extend a specific instance of a Strapi application. 👉 这可以通过直接更新 `/src/admin/app` 文件来完成,该文件可以导入位于 `/src/admin/extensions` 中的任何文件。 ¥👉 This can be done by directly updating the `/src/admin/app` file, which can import any file located in `/src/admin/extensions`. :::strapi 其他资源 * 如果你正在寻找替换默认富文本编辑器的方法,请参阅 [相应页面](/cms/admin-panel-customization/wysiwyg-editor)。 ¥If you're searching for ways of replacing the default Rich text editor, please refer to the [corresponding page](/cms/admin-panel-customization/wysiwyg-editor). * 还提供了有关 Strapi 管理面板开发的大量附加信息。 ¥The also provide extensive additional information on developing for Strapi's admin panel. ::: # 网站图标 Source: https://docs.strapi.io/cms/admin-panel-customization/favicon # 网站图标 {#favicon} ¥Favicon Strapi 的 [管理面板](/cms/admin-panel-customization) 在多个位置显示其品牌标识,包括 [logo](/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. 要替换图标: ¥To replace the favicon: 1. 如果 `/src/admin/extensions/` 文件夹尚不存在,请创建该文件夹。 ¥Create a `/src/admin/extensions/` folder if the folder does not already exist. 2. 将你的网站图标上传到 `/src/admin/extensions/`。 ¥Upload your favicon into `/src/admin/extensions/`. 3. 将 Strapi 应用根目录中现有的 favicon.png|ico 文件替换为自定义 `favicon.png|ico` 文件。 ¥Replace the existing **favicon.png|ico** file at the Strapi application root with a custom `favicon.png|ico` file. 4. 使用以下内容更新 `/src/admin/app.[tsx|js]`: ¥Update `/src/admin/app.[tsx|js]` with the following: ```js title="./src/admin/app.js" import favicon from "./extensions/favicon.png"; export default { config: { // replace favicon with a custom icon head: { favicon: favicon, }, }, }; ``` 5. 通过在终端中运行 `yarn build && yarn develop` 来重建、启动并重新访问你的 Strapi 应用。 ¥Rebuild, launch and revisit your Strapi app by running `yarn build && yarn develop` in the terminal. :::tip 提示 可以使用相同的过程来替换登录徽标(即 `AuthLogo`)和菜单徽标(即 `MenuLogo`)(参见 [徽标定制文档](/cms/admin-panel-customization/logos))。 ¥This same process may be used to replace the login logo (i.e. `AuthLogo`) and menu logo (i.e. `MenuLogo`) (see [logos customization documentation](/cms/admin-panel-customization/logos)). ::: :::caution 提醒 确保清除缓存的图标。它可以缓存在你的 Web 浏览器中,也可以使用你的域管理工具(例如 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 # 主页自定义 {#homepage-customization} ¥Homepage customization :::note 此 API 需要 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。此对等依赖支持 Marketplace 的兼容性检查。 ¥set `^5.13.0` as their `@strapi/strapi` peerDependency in their plugin `package.json`. This peer dependency powers the Marketplace's compatibility check. * 或者,在调用 API 之前检查它是否存在: ¥or check if the API exists before calling it: ```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/). ::: 数据管理: ¥**Data management**: ![Rendering and Data management](/img/assets/homepage-customization/rendering-data-management.png) 上方的绿色框表示用户的 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 注意 * `en` 语言环境无法从构建中删除,因为它既是后备语言环境(即,如果在语言环境中找不到翻译,则将使用 `en`)和默认语言环境(即,当用户第一次打开管理面板时使用) 时间)。 ¥The `en` locale cannot be removed from the build as it is both the fallback (i.e. if a translation is not found in a locale, the `en` will be used) and the default locale (i.e. used when a user opens the administration panel for the first time). * 可用语言环境的完整列表可在 插件的键/值对在 `/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 重建管理后台 翻译更改会在管理员重新构建时生效。如果更新没有显示,请重新运行开发服务器或重新构建管理后台以刷新打包的翻译。 ¥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: ![Location of the auth logo](/img/assets/development/config-auth-logo.png) `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: ![Location of Menu logo](/img/assets/development/config-menu-logo.png) ### 更新徽标 {#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: * `config.theme.light` 键用于灯光模式 ¥the `config.theme.light` key for the Light mode * `config.theme.dark` 键用于夜间模式 ¥the `config.theme.dark` key for the Dark mode :::strapi Strapi 设计系统 默认的 # 自定义富文本编辑器 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 插件。 ¥You can install a third-party plugin, such as one for CKEditor, by visiting . * 你可以创建自己的插件来创建和注册完全自定义的所见即所得字段(参见 [自定义字段文档](/cms/features/custom-fields))。 ¥You can create your own plugin to create and register a fully custom WYSIWYG field (see [custom fields documentation](/cms/features/custom-fields)). :::tip 后续步骤 评估编辑器时,建议先从 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) 创建一个。 ¥A Strapi project has been created and is running. If you haven't set one up yet, follow the [Quick Start Guide](/cms/quick-start) to create one. * 你知道 Strapi 实例的内容 API 的 URL(例如 `http://localhost:1337/api`)。 ¥You know the URL of the Content API of your Strapi instance (e.g., `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 的通用 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?)` | 更新现有文档。 | **使用示例:** ¥**Usage examples:** ### 使用单一类型 {#working-with-single-types} ¥Working with single types Strapi 中的单一类型代表仅存在一次的唯一内容条目(例如,主页设置或站点范围的配置)。Strapi 客户端提供了一种 `single()` 方法来与这些资源交互,可用的方法如下: ¥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: | 范围 | 描述 | | ---------------------------------------- | ----- | | `find(queryParams?)` | 获取文档。 | | `update(documentID, data, queryParams?)` | 更新文档。 | | `delete(queryParams?)` | 删除文档。 | **使用示例:** ¥**Usage examples:** ```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` {#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` {#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 其他响应字段 上传响应包含除上述字段之外的其他字段。有关所有可用字段,请参阅 中的完整 FileResponse 接口。 ¥The upload response includes additional fields beyond those shown above. See the complete FileResponse interface in the for all available fields. ::: #### `delete` {#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 附加信息 有关 Strapi 客户端的更多详细信息,请参阅 。 ¥More details about the Strapi Client may be found in the . ::: # 内容 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) ¥by default through the [REST API](/cms/api/rest) * 如果你安装了 Strapi 内置 [GraphQL 插件](/cms/plugins/graphql),也可以通过 [GraphQL API](/cms/api/graphql)。 ¥and also through the [GraphQL API](/cms/api/graphql) if you installed the Strapi built-in [GraphQL plugin](/cms/plugins/graphql). 你还可以使用 [Strapi 客户端](/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 代表暴露给外部应用的 Content API 的顶层。Strapi 还提供 2 个更底层的 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` 访问,它是推荐的 API,用于在 [后端服务器](/cms/customization) 或通过 [plugins](/cms/plugins-development/developing-plugins) 与应用的数据库进行交互。文档服务是处理文档 # 文档 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: * 英语和法语语言环境的内容不同, ¥different content for the English and the French locale, * 甚至在每个语言环境中为草稿和已发布版本设置不同的内容。 ¥and even different content for the draft and published version in each locale. 包含所有语言环境的所有草稿和已发布版本内容的存储桶是一个文档。 ¥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)功能,则文档可以有多个文档语言环境。 ¥If the Internationalization (i18n) feature is enabled on the content-type, a document can have multiple **document locales**. * 如果在内容类型上启用了草稿和发布功能,则文档可以具有已发布版本和草稿版本。 ¥If the Draft & Publish feature is enabled on the content-type, a document can have a **published** and a **draft** version. :::strapi 用于查询文档数据的 API 要与文档或它们所代表的数据进行交互: ¥To interact with documents or the data they represent: * 从后端服务器(例如,从控制器、服务和插件的后端部分)使用 [文档服务 API](/cms/api/document-service)。 ¥From the back-end server (for instance, from controllers, services, and the back-end part of plugins), use the [Document Service API](/cms/api/document-service). * 从应用的前端部分,使用 [REST API](/cms/api/rest) 或 [GraphQL API](/cms/api/graphql) 查询数据。 ¥From the front-end part of your application, query your data using the [REST API](/cms/api/rest) or the [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 返回结果中的默认版本 后端和前端 API 之间的一个重要区别是关于未传递参数时返回的默认版本: ¥An important difference between the back-end and front-end APIs is about the default version returned when no parameter is passed: * 文档服务 API 默认返回草稿版本, ¥The Document Service API returns the draft version by default, * 而 REST 和 GraphQL API 默认返回已发布的版本。 ¥while REST and GraphQL APIs return the published version by default. :::
# 文档服务 API Source: https://docs.strapi.io/cms/api/document-service # 文档服务 API {#document-service-api} ¥Document Service API 文档服务 API 建立在查询引擎 API 之上 ¥The Document Service API is built on top of the **Query Engine API** 用于对文档 :::strapi 实体服务 API 在 Strapi 5 中已弃用 文档服务 API 取代了 Strapi v4 中使用的实体服务 API ( 如果找到匹配的文档,`findOne()` 方法返回该文档,否则返回 `null`。 ¥The `findOne()` method returns the matching document if found, otherwise returns `null`. ## `findFirst()` {#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) | 如果为内容类型启用了 [起草并发布](/cms/features/draft-and-publish):
发布状态,可以是: | `'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) | [填充](/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()` {#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) | 如果为内容类型启用了 [起草并发布](/cms/features/draft-and-publish):
发布状态,可以是: | `'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) | [填充](/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()` {#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()` {#update} 更新文档版本并返回它们。 ¥Updates document versions and returns them. 语法:`update(parameters: Params) => Promise ## `delete()` {#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()` {#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()` {#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()` {#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} 计算与提供的参数匹配的文档数量。 ¥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):
发布状态,可以是: | `'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'` 参数计数仍会返回与其他参数匹配的文档总数,即使某些文档已经发布并且不再在内容管理器中显示为 "draft" 或 "modified"。目前没有办法阻止已发布的文档被计算在内。 ¥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()` 方法将返回默认语言环境的文档总数: ¥If no parameter is passed, the `count()` method the total number of documents for the default locale: #### 计数已发布的文档 {#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 要选择 [查找第一个文档](/cms/api/document-service#findfirst) 与文档服务 API 匹配参数时要返回的字段: ¥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 要选择 [查找文档](/cms/api/document-service#findmany) 与文档服务 API 匹配时要返回的字段: ¥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 要选择 [创建文档](/cms/api/document-service#create) 与文档服务 API 匹配时要返回的字段: ¥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 要选择 [更新文档](/cms/api/document-service#update) 与文档服务 API 匹配时要返回的字段: ¥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 要选择 [删除文档](/cms/api/document-service#delete) 与文档服务 API 匹配时要返回的字段: ¥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 要选择 [发布文档](/cms/api/document-service#publish) 与文档服务 API 匹配时要返回的字段: ¥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 要选择 [取消发布文档](/cms/api/document-service#unpublish) 与文档服务 API 匹配时要返回的字段: ¥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 要选择 [丢弃文档的草稿版本](/cms/api/document-service#discarddraft) 与文档服务 API 匹配时要返回的字段: ¥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) | 连接 "or" 表达式中的过滤器 | | [`$and`](#and) | 连接 "and" 表达式中的过滤器 | | [`$not`](#not) | 连接 "not" 表达式中的过滤器 | ## 属性运算符 {#attribute-operators} ¥Attribute operators
### `$not` {#not} 否定嵌套条件。 ¥Negates the nested condition(s). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $not: { $contains: 'Hello World', }, }, }, }); ``` ### `$eq` {#eq} 属性等于输入值。 ¥Attribute equals input value. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $eq: 'Hello World', }, }, }); ``` `$eq` 可以省略: ¥`$eq` can be omitted: ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: 'Hello World', }, }); ``` ### `$eqi` {#eqi} 属性等于输入值(不区分大小写)。 ¥Attribute equals input value (case-insensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $eqi: 'HELLO World', }, }, }); ``` ### `$ne` {#ne} 属性不等于输入值。 ¥Attribute does not equal input value. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $ne: 'ABCD', }, }, }); ``` ### `$nei` {#nei} 属性不等于输入值(不区分大小写)。 ¥Attribute does not equal input value (case-insensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $nei: 'abcd', }, }, }); ``` ### `$in` {#in} 属性包含在输入列表中。 ¥Attribute is contained in the input list. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $in: ['Hello', 'Hola', 'Bonjour'], }, }, }); ``` 传递值数组时可以省略 `$in`: ¥`$in` can be omitted when passing an array of values: ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: ['Hello', 'Hola', 'Bonjour'], }, }); ``` ### `$notIn` {#notin} 输入列表中不包含属性。 ¥Attribute is not contained in the input list. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $notIn: ['Hello', 'Hola', 'Bonjour'], }, }, }); ``` ### `$lt` {#lt} 属性小于输入值。 ¥Attribute is less than the input value. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { rating: { $lt: 10, }, }, }); ``` ### `$lte` {#lte} 属性小于或等于输入值。 ¥Attribute is less than or equal to the input value. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { rating: { $lte: 10, }, }, }); ``` ### `$gt` {#gt} 属性大于输入值。 ¥Attribute is greater than the input value. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { rating: { $gt: 5, }, }, }); ``` ### `$gte` {#gte} 属性大于或等于输入值。 ¥Attribute is greater than or equal to the input value. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { rating: { $gte: 5, }, }, }); ``` ### `$between` {#between} 属性位于 2 个输入值之间,包括边界(例如,`$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`). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { rating: { $between: [1, 20], }, }, }); ``` ### `$contains` {#contains} 属性包含输入值(区分大小写)。 ¥Attribute contains the input value (case-sensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $contains: 'Hello', }, }, }); ``` ### `$notContains` {#notcontains} 属性不包含输入值(区分大小写)。 ¥Attribute does not contain the input value (case-sensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $notContains: 'Hello', }, }, }); ``` ### `$containsi` {#containsi} 属性包含输入值。`$containsi` 不区分大小写,而 [$包含](#contains) 则区分大小写。 ¥Attribute contains the input value. `$containsi` is not case-sensitive, while [$contains](#contains) is. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $containsi: 'hello', }, }, }); ``` ### `$notContainsi` {#notcontainsi} 属性不包含输入值。`$notContainsi` 不区分大小写,而 [$不包含](#notcontains) 则区分大小写。 ¥Attribute does not contain the input value. `$notContainsi` is not case-sensitive, while [$notContains](#notcontains) is. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $notContainsi: 'hello', }, }, }); ``` ### `$startsWith` {#startswith} 属性以输入值开头(区分大小写)。 ¥Attribute starts with input value (case-sensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $startsWith: 'ABCD', }, }, }); ``` ### `$startsWithi` {#startswithi} 属性以输入值开头(不区分大小写)。 ¥Attribute starts with input value (case-insensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $startsWithi: 'ABCD', // will return the same as filtering with 'abcd' }, }, }); ``` ### `$endsWith` {#endswith} 属性以输入值结尾(区分大小写)。 ¥Attribute ends with input value (case-sensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $endsWith: 'ABCD', }, }, }); ``` ### `$endsWithi` {#endswithi} 属性以输入值结尾(不区分大小写)。 ¥Attribute ends with input value (case-insensitive). **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $endsWith: 'ABCD', // will return the same as filtering with 'abcd' }, }, }, }); ``` ### `$null` {#null} 属性为 `null`。 ¥Attribute is `null`. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $null: true, }, }, }); ``` ### `$notNull` {#notnull} 属性不是 `null`。 ¥Attribute is not `null`. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $notNull: true, }, }, }); ``` ## 逻辑运算符 {#logical-operators} ¥Logical operators ### `$and` {#and} 所有嵌套条件必须为 `true`。 ¥All nested conditions must be `true`. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { $and: [ { title: 'Hello World', }, { createdAt: { $gt: '2021-11-17T14:28:25.843Z' }, }, ], }, }); ``` 当传递具有嵌套条件的对象时,将隐式使用 `$and`: ¥`$and` will be used implicitly when passing an object with nested conditions: ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { title: 'Hello World', createdAt: { $gt: '2021-11-17T14:28:25.843Z' }, }, }); ``` ### `$or` {#or} 一个或多个嵌套条件必须为 `true`。 ¥One or many nested conditions must be `true`. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { $or: [ { title: 'Hello World', }, { createdAt: { $gt: '2021-11-17T14:28:25.843Z' }, }, ], }, }); ``` ### `$not` {#not-1} 否定嵌套条件。 ¥Negates the nested conditions. **示例** ¥**Example** ```js const entries = await strapi.documents('api::article.article').findMany({ filters: { $not: { title: 'Hello World', }, }, }); ``` :::note 注意 `$not` 可用作: ¥`$not` can be used as: * 逻辑运算符(例如在 `filters: { $not: { // conditions… }}` 中) ¥a logical operator (e.g. in `filters: { $not: { // conditions… }}`) * [属性运算符](#not)(例如在 `filters: { attribute-name: $not: { … } }` 中)。 ¥[an attribute operator](#not) (e.g. in `filters: { attribute-name: $not: { … } }`). ::: :::tip 提示 `$and`、`$or` 和 `$not` 运算符可嵌套在另一个 `$and`、`$or` 或 `$not` 运算符内。 ¥`$and`, `$or` and `$not` operators are nestable inside of another `$and`, `$or` or `$not` operator. ::: # 使用文档服务 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 默认情况下,[文档服务 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.
Explanation: 给定以下 4 个具有不同语言环境的文档: ¥Given the following 4 documents that have various locales: * 文档 A: ¥Document A: * en * `fr` * it * 文档 B: ¥Document B: * en * it * 文档 C: ¥Document C: * `fr` * 文档 D: ¥Document D: * `fr` * it `findMany({ locale: 'fr' })` 只会返回具有 `‘fr’` 语言环境版本的文档的草稿版本,即文档 A、C 和 D。 ¥`findMany({ locale: 'fr' })` would only return the draft version of the documents that have a `‘fr’` locale version, that is documents A, C, and 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 将 `locale` 参数与文档服务 API 的 [`delete()` 方法](/cms/api/document-service#delete) 一起使用以仅删除某些语言环境。除非传递了特定的 `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.
Simplified Strapi backend diagram with controllers highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with the Document Service highlighted. The backend customization introduction page includes a complete, interactive diagram.
## 注册中间件 {#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` {#context} | 范围 | 描述 | 类型 | | ------------- | -------------------------------------------- | ------------- | | `action` | 正在运行的方法([查看可用方法](/cms/api/document-service)) | `string` | | `params` | 方法参数 ([查看可用方法](/cms/api/document-service)) | `Object` | | `uid` | 内容类型唯一标识符 | `string` | | `contentType` | 内容类型 | `ContentType` |
Examples: 以下示例显示了 `context` 可能包含的内容(具体取决于调用的方法): ¥The following examples show what `context` might include depending on the method called:
#### `next` {#next} `next` 是一个没有参数的函数,它调用堆栈中的下一个中间件并返回其响应。 ¥`next` is a function without parameters that calls the next middleware in the stack and return its response. **示例** ¥**Example** ```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 生命周期钩子 文档服务 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). ::: # 使用文档服务 API 填充 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 发布文档的一个或多个语言环境。 ¥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 默认情况下,当启用 [起草并发布](/cms/features/draft-and-publish) 功能时,[文档服务 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: * 返回文档的已发布版本, ¥return the published version of a document, * 根据文档的状态计数文档, ¥count documents depending on their status, * 并在创建或更新文档时直接发布文档。 ¥and directly publish a document while creating it or updating it. :::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()` 查询默认返回文档的草稿版本。 ¥`findOne()` queries return the draft version of a document by default. 要使用文档服务 API 返回已发布的版本,同时 [查找特定文档](/cms/api/document-service#findone) 与文档服务 API 匹配,请传递 `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()` 查询默认返回文档的草稿版本。 ¥`findFirst()` queries return the draft version of a document by default. 要使用文档服务 API 返回已发布的版本,同时 [查找第一个文档](/cms/api/document-service#findfirst) 与文档服务 API 匹配,请传递 `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()` 查询默认返回文档的草稿版本。 ¥`findMany()` queries return the draft version of documents by default. 要使用文档服务 API 返回已发布的版本,同时 [查找文档](/cms/api/document-service#findmany) 与文档服务 API 匹配,请传递 `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'` 参数计数仍会返回与其他参数匹配的文档总数,即使某些文档已经发布并且不再在内容管理器中显示为 "draft" 或 "modified"。目前没有办法阻止已发布的文档被计算在内。 ¥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} GraphQL API 允许执行查询和突变,以通过 Strapi 的 [GraphQL 插件](/cms/plugins/graphql) 与 [content-types](/cms/backend-customization/models#content-types) 进行交互。结果可以是 [filtered](#filters)、[sorted](#sorting) 和 [paginated](#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` URL 访问 GraphQL 在线运行,并可用于以交互方式构建查询和修改,以及阅读针对你的内容类型量身定制的文档: ¥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. 以下示例从 "餐厅" 内容类型中获取附加到每个文档的每个 `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` 字段来为特定语言环境创建本地化文档 # 开放 API 规范 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 操作 ¥CRUD operations for all content types * 应用中定义的自定义 API 路由 ¥Custom API routes defined in your application * 用于用户管理的身份验证端点 ¥Authentication endpoints for user management * 用于媒体处理的文件上传端点 ¥File upload endpoints for media handling * 已安装插件的插件端点 ¥Plugin endpoints from installed plugins ## 与 Swagger UI 集成 {#integrating-with-swagger-ui} ¥Integrating with Swagger UI 通过以下步骤,你可以快速生成与 [招摇的用户界面](https://swagger.io/) 兼容的页面: ¥With the following steps you can quickly generate a [Swagger UI](https://swagger.io/)-compatible page: 1. 生成规范: ¥Generate a specification: 2. 使用以下代码更新 [`/config/middlewares.js` 配置文件](/cms/configurations/middlewares): ¥Update [the `/config/middlewares.js` configuration file](/cms/configurations/middlewares) with the following code: ``` This will ensure the Swagger UI display from is not blocked by Strapi's CSP policy handled by the [security middleware](/cms/configurations/middlewares#security). ``` 3. ```` ```html API Documentation
``` ```` 4.Swagger UI 应显示如下: ¥4. Restart the Strapi server with `yarn develop` or `npm run develop` and visit the `/openapi.html` page. The Swagger UI should be displayed: ![Swagger UI example with Strapi OpenAPI specification](/img/assets/apis/swagger-open-api.png) # REST API 参考 Source: https://docs.strapi.io/cms/api/rest # REST API 参考 {#rest-api-reference} ¥REST API reference REST API 允许通过 API 端点访问 [content-types](/cms/backend-customization/models)。创建内容类型时,Strapi 会自动创建 [API 端点](#endpoints)。查询 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 参考。我们还为特定用例提供了 [guides](/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 客户端 [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:
Plural API ID vs. Singular API ID: 在下表中: ¥In the following tables: * `:singularApiId` 指的是内容类型的 "API ID(单数)" 字段的值, ¥`:singularApiId` refers to the value of the "API ID (Singular)" field of the content-type, * 而 `:pluralApiId` 指的是内容类型的 "API ID(复数)" 字段的值。 ¥and `:pluralApiId` refers to the value of the "API ID (Plural)" field of the content-type. 这些值是在内容类型生成器中创建内容类型时定义的,可以在管理面板中编辑内容类型时找到(请参阅 [用户指南](/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` ¥`:singularApiId` will be `article` * `:pluralApiId` 将为 `articles` ¥`:pluralApiId` will be `articles`
Real-world examples of endpoints: 以下端点示例取自
:::strapi 上传 API Upload 包(为 [媒体库功能](/cms/features/media-library) 提供支持)具有可通过其 [`/api/upload` 端点](/cms/api/rest/upload) 访问的特定 API。 ¥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 端点。 ¥[Components](/cms/backend-customization/models#components-json) don't have API endpoints. ::: ## 要求 {#requests} ¥Requests :::strapi Strapi 5 与 Strapi v4 Strapi 5 的内容 API 与 Strapi v4 有 2 个主要区别: ¥Strapi 5's Content API includes 2 major differences with Strapi v4: * 响应格式已扁平化,这意味着属性不再嵌套在 `data.attributes` 对象中,而是可以在 `data` 对象的第一级直接访问(例如,使用 `data.title` 访问内容类型的 "title" 属性)。 ¥The response format has been flattened, which means attributes are no longer nested in a `data.attributes` object and are directly accessible at the first level of the `data` object (e.g., a content-type's "title" attribute is accessed with `data.title`). * Strapi 5 现在使用文档 ### 获取文档 {#get} ¥Get a document 返回 `documentId` 的文档。 ¥Returns a document by `documentId`. :::strapi Strapi 5 与 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)。 ¥Even with the [Internationalization (i18n) plugin](/cms/features/internationalization) installed, it's currently not possible to [update the locale of a document](/cms/api/rest/locale#rest-update). * 在更新文档时,你可以定义其关系及其顺序(有关更多详细信息,请参阅 [通过 REST API 管理关系](/cms/api/rest/relations))。 ¥While updating a document, you can define its relations and their order (see [Managing relations through the REST API](/cms/api/rest/relations) for more details). ::: ### 删除文档 {#delete} ¥Delete a document 删除文档。 ¥Deletes a document. `DELETE` 请求仅在成功时发送 204 HTTP 状态代码,并且不会在响应正文中返回任何数据。 ¥`DELETE` requests only send a 204 HTTP status code on success and do not return any data in the response body. # 过滤器 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 功能可以提供更多过滤器: ¥The [REST API](/cms/api/rest) offers the ability to filter results found with its ["Get entries"](/cms/api/rest#get-all) method.
Using optional Strapi features can provide some more filters: * 如果在内容类型上启用了 [国际化 (i18n) 插件](/cms/features/internationalization),则可以按区域设置进行过滤。 ¥If the [Internationalization (i18n) plugin](/cms/features/internationalization) is enabled on a content-type, it's possible to filter by locale. * 如果启用了 [起草并发布](/cms/features/draft-and-publish),则可以根据 `published`(默认)或 `draft` 状态进行过滤。 ¥If the [Draft & Publish](/cms/features/draft-and-publish) is enabled, it's possible to filter based on a `published` (default) or `draft` status. :::tip 提示
JavaScript query (built with the qs library): ## 示例:查找多个 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 query (built with the qs library): ## 复杂过滤 {#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 query (built with the qs library): ## 深度过滤 {#deep-filtering} ¥Deep filtering 深度过滤是对关系的字段进行过滤。 ¥Deep filtering is filtering on a relation's fields. :::note 注意 * 默认情况下不填充关系、媒体字段、组件和动态区域。使用 `populate` 参数填充这些内容结构(参见 [`populate` 文档](/cms/api/rest/populate-select#population)) ¥Relations, media fields, components, and dynamic zones are not populated by default. Use the `populate` parameter to populate these content structures (see [`populate` documentation](/cms/api/rest/populate-select#population)) * 你可以过滤填充的内容,也可以过滤嵌套关系,但不能对多态内容结构(例如媒体字段和动态区域)使用过滤器。 ¥You can filter what you populate, you can also filter nested relations, but you can't use filters for polymorphic content structures (such as media fields and dynamic zones). ::: :::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 query (built with the qs library): # 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 想帮助其他用户吗? 本节列出的一些额外资源是为 Strapi v4 创建的,可能无法完全与 Strapi 5 一起使用。如果你想为 Strapi 5 更新以下文章之一,请随时 参加“为社区写作”计划。 ¥Some of the additional resources listed in this section have been created for Strapi v4 and might not fully work with Strapi 5. If you want to update one of the following articles for Strapi 5, feel free to for the Write for the Community program. ::: 其他教程和指南可以在以下博客文章中找到: ¥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. 将端点和端点查询参数字段中的值替换为适合你需要的内容。 ¥Replace the values in the *Endpoint* and *Endpoint Query Parameters* fields with content that fits your needs. 2. 单击“复制到剪贴板”按钮可复制自动生成的查询字符串 URL,该 URL 会在你键入时更新。 ¥Click the **Copy to clipboard** button to copy the automatically generated *Query String URL* which is updated as you type. :::info 参数使用 请参考 [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` 集合类型,请在端点字段中键入 `/api/books` 。 ¥The default endpoint path is prefixed with `/api/` and should be kept as-is unless you configured a different API prefix using [the `rest.prefix` API configuration option](/cms/configurations/api).
For instance, to query the `books` collection type using the default API prefix, type `/api/books` in the *Endpoint* field. ::: :::caution 免责声明 本页提供的 `qs` 库和交互式查询构建器: ¥The `qs` library and the interactive query builder provided on this page: * 可能无法检测到所有语法错误, ¥might not detect all syntax errors, * 不知道 Strapi 项目中可用的参数和值, ¥are not aware of the parameters and values available in a Strapi project, * 并且不提供自动补齐功能。 ¥and do not provide autocomplete features. 目前,这些工具仅用于转换内联查询字符串 URL 中的 JavaScript 对象。使用生成的查询 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} [国际化 (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` [接口参数](/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 request's body | 使用案例 | 语法格式和更多信息的链接 | | --------- | --------------------------------------------------------------------------------------- | | 为默认语言环境创建 | [`POST /api/content-type-plural-name`](#rest-create-default-locale) | | 为特定语言环境创建 | [`POST /api/content-type-plural-name`](#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 要为不同于默认区域设置的区域设置创建本地化条目,请将 `locale` 属性添加到 POST 请求的正文中: ¥To create a localized entry for a locale different from the default one, add the `locale` attribute to the body 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: * 创建文档的另一个语言环境版本, ¥create another locale version of the document, * 或更新文档的现有语言环境版本。 ¥or update an existing locale version of the document. 将 `PUT` 请求发送到相应的 URL,将 `locale=your-locale-code` 参数添加到查询 URL 并在请求正文中的 `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 要为集合类型中的现有文档创建新语言环境,请在查询中添加 `locale` 参数(位于 `documentId` 之后),并将数据传递到请求的正文: ¥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 状态代码,并且不会在响应正文中返回任何数据。 ¥`DELETE` requests only send a 204 HTTP status code on success and do not return any data in the response body. #### 在集合类型中 {#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) | 查询参数使用 (即使用方括号 `[]` 进行编码)。 ¥Query parameters use the (i.e. they are encoded using square brackets `[]`). :::tip 提示 可以使用和组合各种 REST API 参数来查询你的内容,这可能会导致查询 URL 长而复杂。
👉 你可以使用 Strapi 的 [交互式查询构建器](/cms/api/rest/interactive-query-builder) 工具更方便地构建查询 URL。🤗 ¥A wide range of REST API parameters can be used and combined to query your content, which can result in long and complex query URLs.
👉 You can use Strapi's [interactive query builder](/cms/api/rest/interactive-query-builder) tool to build query URLs more conveniently. 🤗 ::: # 填充并选择 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) 填充特定字段,使用 [`select` 参数](#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 and the [`select` parameter](#field-selection) to return only specific fields with the query results. :::tip 提示 ## 人口 {#population} ¥Population 默认情况下,REST API 不会填充任何类型的字段,因此它不会填充关系、媒体字段、组件或动态区域,除非你传递 `populate` 参数来填充各种字段类型。 ¥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. `populate` 参数可以单独使用,也可以使用 [与多个操作符结合](#combining-population-with-other-operators) 对总体进行更多控制。 ¥The `populate` parameter can be used alone or [in combination with with multiple operators](#combining-population-with-other-operators) to have much more control over the population. :::caution 提醒 必须为正在填充的内容类型启用 `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 doesn't have access to a content-type it will not be populated (see [User Guide](/cms/features/users-permissions#editing-a-role) for additional information on how to enable `find` permissions for content-types). ::: :::note 注意 目前无法仅通过请求返回 id 数组。 ¥It's currently not possible to return just an array of ids with a request. ::: :::strapi 填充指南 [REST API 指南](/cms/api/rest/guides/intro) 部分包含有关填充参数的各种可能用例的更详细信息: ¥The [REST API guides](/cms/api/rest/guides/intro) section includes more detailed information about various possible use cases for the populate parameter: * [了解填充](/cms/api/rest/guides/understanding-populate) 指南通过图表、比较和实际示例详细解释了填充的工作原理。 ¥The [Understanding populate](/cms/api/rest/guides/understanding-populate) guide explains in details how populate works, with diagrams, comparisons, and real-world examples. * [如何填充创建者字段](/cms/api/rest/guides/populate-creator-fields) 指南提供了有关如何将 `createdBy` 和 `updatedBy` 字段添加到查询响应中的分步说明。 ¥The [How to populate creator fields](/cms/api/rest/guides/populate-creator-fields) guide provides step-by-step instructions on how to add `createdBy` and `updatedBy` fields to your queries responses. ::: 下表总结了可能的填充用例及其关联的参数语法,并链接到了解填充指南的各部分,其中包括更详细的说明: ¥The following table sums up possible populate use cases and their associated parameter syntaxes, and links to sections of the Understanding populate guide which includes more detailed explanations: | 使用案例 | 参数语法示例 | 详细解释请阅读 | | -------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | 填充所有内容,深度为 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) 工具。 ¥The easiest way to build complex queries with multiple-level population is to use our [interactive query builder](/cms/api/rest/interactive-query-builder) tool. ::: ### 将 Population 与其他运算符结合起来 {#combining-population-with-other-operators} ¥Combining Population with other operators 通过利用 `populate` 运算符,可以在总体查询中组合其他运算符,例如 [字段选择](/cms/api/rest/populate-select#field-selection)、[filters](/cms/api/rest/filters) 和 [sort](/cms/api/rest/sort-pagination)。 ¥By utilizing the `populate` operator it is possible to combine 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. :::caution 提醒 总体和分页运算符不能组合使用。 ¥The population and pagination operators cannot be combined. ::: #### 使用字段选择填充 {#populate-with-field-selection} ¥Populate with field selection `fields` 和 `populate` 可以组合。 ¥`fields` and `populate` can be combined.
#### 填充过滤 {#populate-with-filtering} ¥Populate with filtering `filters` 和 `populate` 可以组合。 ¥`filters` and `populate` can be combined.
# 关系 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. 从关闭 i18n 的 [管理面板](/cms/features/content-manager#relational-fields) 到打开 i18n 的 [REST API](/cms/api/rest) 的关系: ¥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) | 连接新实体。

可以与 `disconnect` 结合使用。

可以与 [位置参数](#relations-reordering) 结合使用来定义关系的顺序。 | 部分的 | | [`disconnect`](#disconnect) | 断开实体连接。

可以与 `connect` 结合使用。 | 部分的 | | [`set`](#set) | 将实体设置为特定集合。使用 `set` 将覆盖与其他实体的所有现有连接。

不能与 `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} 在请求正文中使用 `connect` 执行部分更新,连接指定的关系。 ¥Using `connect` in the body of a request performs a partial update, connecting the specified relations. `connect` 接受简写或全写语法: ¥`connect` accepts either a shorthand or a longhand syntax: | 语法类型 | 语法示例 | | --------- | ------------------------------------------------------------------------------------------------- | | shorthand | `connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']` | | longhand | `connect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }]` | 你还可以使用 [重新排序关系](#relations-reordering) 的普通语法。 ¥You can also use the longhand syntax to [reorder relations](#relations-reordering). `connect` 可以与 [`disconnect`](#disconnect) 结合使用。 ¥`connect` can be used in combination with [`disconnect`](#disconnect). :::caution 提醒 `connect` 尚未正式支持媒体属性。高级用户理论上可以通过指定上传文件 ID 来连接媒体条目,但 Strapi 不推荐或支持此方法,并且此方法很容易出错(例如,当 Draft & Publish 使用不匹配的 ID 时)。谨慎操作。 ¥`connect` is not officially supported for media attributes. Advanced users can technically connect media entries by targeting upload file IDs, but this workaround isn't recommended or supported by Strapi and can easily break (e.g. when Draft & Publish uses mismatched IDs). Proceed with caution. ::: ### 关系重新排序 {#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' } ] ``` ### 边缘情况:草稿和发布或 i18n 已禁用 {#edge-cases-draft--publish-or-i18n-disabled} ¥Edge cases: Draft & Publish or i18n disabled 当 Strapi 5 的一些内置功能针对内容类型(例如 [起草并发布](/cms/features/draft-and-publish) 和 [国际化 (i18)](/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: **从关闭草稿和发布的 `Category` 到打开草稿和发布的 `Article` 的关系:** ¥**Relation from a `Category` with i18n *off* to an `Article` with i18n *on*:** 在这种情况下,你可以选择要连接到哪个语言环境: ¥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' }, ] } } ``` **根据你的用例阅读一些高级 `Category`。** ¥**Relation from a `Category` with Draft & Publish *off* to an `Article` with Draft & Publish *on*:** ```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} 在请求正文中使用 `disconnect` 执行部分更新,断开指定的关系。 ¥Using `disconnect` in the body of a request performs a partial update, disconnecting the specified relations. `disconnect` 接受简写或全写语法: ¥`disconnect` accepts either a shorthand or a longhand syntax: | 语法类型 | 语法示例 | | --------- | ---------------------------------------------------------------------------------------------------- | | shorthand | `disconnect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']` | | longhand | `disconnect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }]` | `disconnect` 可以与 [`connect`](#connect) 结合使用。 ¥`disconnect` can be used in combination with [`connect`](#connect).
## `set` {#set} 使用 `set` 执行完整更新,按照指定的顺序将所有现有关系替换为指定的关系。 ¥Using `set` performs a full update, replacing all existing relations with the ones specified, in the order specified. `set` 接受简写或全写语法: ¥`set` accepts a shorthand or a longhand syntax: | 语法类型 | 语法示例 | | --------- | --------------------------------------------------------------------------------------------- | | shorthand | `set: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']` | | longhand | `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 省略集合 省略任何参数都相当于使用 `set`。
例如,以下 3 种语法都是等效的: ¥Omitting any parameter is equivalent to using `set`.
For instance, the following 3 syntaxes are all equivalent: * `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 query (built with the qs library): ### 示例:使用 2 个字段排序并设置顺序 {#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 query (built with the qs library): ## 分页 {#pagination} ¥Pagination 查询可以接受 `pagination` 个参数。结果可以分页: ¥Queries can accept `pagination` parameters. Results can be paginated: * 通过 [page](#pagination-by-page)(即指定页码和每页的条目数) ¥either by [page](#pagination-by-page) (i.e., specifying a page number and the number of entries per page) * 或按 [offset](#pagination-by-offset)(即指定要跳过和返回的条目数) ¥or by [offset](#pagination-by-offset) (i.e., specifying how many entries to skip and to return) :::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]` | 布尔值 | 将条目总数和页数添加到响应中 | 真的 |
JavaScript query (built with the qs library): ### 按偏移量分页 {#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]` 的默认值和最大值可以是带有 `api.rest.defaultLimit` 和 `api.rest.maxLimit` 键的 [在 `./config/api.js` 中配置](/cms/configurations/api) 文件。 ¥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 query (built with the qs library): # 状态 Source: https://docs.strapi.io/cms/api/rest/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 应启用 [起草并发布](/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`:仅返回文档的已发布版本(默认) ¥`published`: returns only the published version of documents (default) * `draft`:仅返回文档的草稿版本 ¥`draft`: returns only the draft version of documents :::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 query (built with the qs library): # 上传文件 Source: https://docs.strapi.io/cms/api/rest/upload # REST API:上传文件 {#rest-api-upload-files} ¥REST API: Upload files [媒体库功能](/cms/features/media-library) 由 `upload` 包在 Strapi 的后端服务器中提供支持。要将文件上传到 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 : | 方法 | 路径 | 描述 | | :- | :---------------------- | :----- | | 得到 | `/api/upload/files` | 获取文件列表 | | 得到 | `/api/upload/files/:id` | 获取特定文件 | | 邮政 | `/api/upload` | 上传文件 | | 邮政 | `/api/upload?id=x` | 更新文件信息 | | 删除 | `/api/upload/files/:id` | 删除文件 | :::note 注意 * [文件夹](/cms/features/media-library#organizing-assets-with-folders) 是管理面板专用功能,不属于 Content API(REST 或 GraphQL)。通过 REST 上传的文件位于自动创建的 "API 上传" 文件夹中。 ¥[Folders](/cms/features/media-library#organizing-assets-with-folders) are an admin panel-only feature and are not part of the Content API (REST or GraphQL). Files uploaded through REST are located in the automatically created "API Uploads" folder. * GraphQL API 不支持上传媒体文件。要上传文件,请使用 REST API 或直接从管理面板中的 [媒体库](/cms/features/media-library) 添加文件。仍然可以进行一些 GraphQL 修改来更新或删除已上传的媒体文件(有关详细信息,请参阅 [GraphQL API 文档](/cms/api/graphql#mutations-on-media-files))。 ¥The GraphQL API does not support uploading media files. To upload files, use the REST API or directly add files from the [Media Library](/cms/features/media-library) in the admin panel. Some GraphQL mutations to update or delete uploaded media files are still possible (see [GraphQL API documentation](/cms/api/graphql#mutations-on-media-files) for details). ::: ## 上传文件 {#upload-files} ¥Upload files 将一个或多个文件上传到你的应用。 ¥Upload one or more files to your application. `files` 是唯一可接受的参数,并描述要上传的文件。值可以是缓冲区或流: ¥`files` is the only accepted parameter, and describes the file(s) to upload. The value(s) can be a Buffer or Stream: :::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` | 要上传的文件。该值可以是缓冲区或流。 | | `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` 是唯一可接受的参数,并描述要更新的文件信息: ¥`fileInfo` is the only accepted parameter, and describes the fileInfo to update: ```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 向 [model](/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
# 后端定制 {#backend-customization} ¥Backend customization :::strapi 消歧义:带子后端 作为无头 CMS,整个 Strapi 软件可以被视为你网站或应用的 "后端"。但 Strapi 软件本身包括 2 个不同的部分: ¥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 后端与数据库交互以创建、检索、更新和删除内容。 ¥The **back-end** part of Strapi is an HTTP server that Strapi runs. Like any HTTP server, the Strapi back end receives requests and send responses. Your content is stored in a database, and the Strapi back end interacts with the database to create, retrieve, update, and delete content. * Strapi 的前端部分称为管理面板。管理面板提供图形用户界面来帮助你构建和管理内容。 ¥The **front-end** part of Strapi is called the admin panel. The admin panel presents a graphical user interface to help you structure and manage the content. 在本开发者文档中,'后端' 专指 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 后端运行基于 (一个后端 JavaScript 框架)的 HTTP 服务器。 ¥The Strapi back end runs an HTTP server based on , a back-end JavaScript framework. 与任何 HTTP 服务器一样,Strapi 后端接收请求并发送响应。你可以向 Strapi 后端发送请求,以通过 [REST](/cms/api/rest) 或 [GraphQL](/cms/api/graphql) API 创建、检索、更新或删除数据。 ¥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 服务器收到 [request](/cms/backend-customization/requests-responses)。 ¥The Strapi server receives a [request](/cms/backend-customization/requests-responses). 2. 请求命中按顺序运行的 [全局中间件](/cms/backend-customization/middlewares)。 ¥The request hits [global middlewares](/cms/backend-customization/middlewares) that are run in a sequential order. 3. 请求命中 [route](/cms/backend-customization/routes)。
默认情况下,Strapi 会为你创建的所有内容类型生成路由文件(请参阅 [REST API 文档](/cms/api/rest)),并且可以添加和配置更多路由。 ¥The request hits a [route](/cms/backend-customization/routes).
By default, Strapi generates route files for all the content-types that you create (see [REST API documentation](/cms/api/rest)), and more routes can be added and configured. 4. [路由策略](/cms/backend-customization/policies) 充当只读验证步骤,可以阻止对路由的访问。[路由中间件](/cms/backend-customization/routes#middlewares) 可以控制请求流并在继续之前改变请求本身。 ¥[Route policies](/cms/backend-customization/policies) act as a read-only validation step that can block access to a route. [Route middlewares](/cms/backend-customization/routes#middlewares) can control the request flow and mutate the request itself before moving forward. 5. [控制器](/cms/backend-customization/controllers) 在到达路由后执行代码。[服务](/cms/backend-customization/services) 是可选的附加代码,可用于构建可由控制器重用的自定义逻辑。 ¥[Controllers](/cms/backend-customization/controllers) execute code once a route has been reached. [Services](/cms/backend-customization/services) are optional, additional code that can be used to build custom logic reusable by controllers. 6. 控制器和服务执行的代码与 [models](/cms/backend-customization/models) 交互,[models](/cms/backend-customization/models) 是存储在数据库中的内容结构的表示。
与模型所表示的数据交互由 [文档服务](/cms/api/document-service) 和 [查询引擎](/cms/api/query-engine) 处理。 ¥The code executed by the controllers and services interacts with the [models](/cms/backend-customization/models) that are a representation of the content content structure stored in the database.
Interacting with the data represented by the models is handled by the [Document Service](/cms/api/document-service) and [Query Engine](/cms/api/query-engine). 7. 你可以实现 [文档服务中间件](/cms/api/document-service/middlewares) 来控制数据,然后再将其发送到查询引擎。查询引擎也可以使用生命周期钩子,但我们建议你使用文档服务中间件,除非你绝对需要直接与数据库交互。 ¥You can implement [Document Service middlewares](/cms/api/document-service/middlewares) to control the data before it's sent to the Query Engine. The Query Engine can also use lifecycle hooks though we recommend you use Document Service middlewares unless you absolutely need to directly interact with the database. 8. 服务器返回 [response](/cms/backend-customization/requests-responses)。响应可以在发送之前通过路由中间件和全局中间件返回。 ¥The server returns a [response](/cms/backend-customization/requests-responses). The response can travel back through route middlewares and global middlewares before being sent. 全局中间件和路由中间件都包含异步回调函数 `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: * 如果中间件不返回任何内容,则请求将继续穿过后端的各个核心元素(即控制器、服务以及与数据库交互的其他层)。 ¥If a middleware returns nothing, the request will continue travelling through the various core elements of the back end (i.e., controllers, services, and the other layers that interact with the database). * 如果中间件在调用 `await next()` 之前返回,则会立即发送响应,跳过其余核心元素。然后它会沿着它出现的同一条链返回。 ¥If a middleware returns before calling `await next()`, a response will be immediately sent, skipping the rest of the core elements. Then it will go back down the same chain it came up. :::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 文件,其中包含一组称为操作的方法,客户端根据请求的 [route](/cms/backend-customization/routes)。每当客户端请求路由时,该操作都会执行业务逻辑代码并发回 [response](/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. 在大多数情况下,控制器将包含项目的大部分业务逻辑。但随着控制器的逻辑变得越来越复杂,使用 [services](/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.
Simplified Strapi backend diagram with controllers highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with controllers highlighted. The backend customization introduction page includes a complete, interactive diagram.
:::caution 清理输入和输出 覆盖核心操作时,务必验证并清理查询和响应,以避免泄露私有字段或绕过访问规则。在从自定义操作返回数据之前,使用 `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) ¥with the [interactive CLI command `strapi generate`](/cms/cli) * 或通过创建 JavaScript 文件手动: ¥or manually by creating a JavaScript file: * 在 `./src/api/[api-name]/controllers/` 中用于 API 控制器(此位置很重要,因为 Strapi 从那里自动加载控制器) ¥in `./src/api/[api-name]/controllers/` for API controllers (this location matters as controllers are auto-loaded by Strapi from there) * 或者在插件控制器的 `./src/plugins/[plugin-name]/server/controllers/` 这样的文件夹中,尽管只要插件接口在 `strapi-server.js` 文件中正确导出(请参阅 [插件服务器 API 文档](/cms/plugins-development/server-api)),它们就可以在其他地方创建 ¥or in a folder like `./src/plugins/[plugin-name]/server/controllers/` for plugin controllers, though they can be created elsewhere as long as the plugin interface is properly exported in the `strapi-server.js` file (see [Server API for Plugins documentation](/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).
Example: GET /hello route calling a basic controller 定义了具体的 `GET /hello` [route](/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 注意 当创建新的 [content-type](/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`)。在生成的控制器中覆盖任何这些操作都不需要修改路由 - 路由会保留相同的处理程序字符串并执行更新后的逻辑。 ¥Core mapping is automatic: when you generate a content-type, Strapi creates the matching controller and a router file that already targets the standard actions (`find`, `findOne`, `create`, `update`, and `delete`). Overriding any of these actions inside the generated controller does not require touching the router — the route keeps the same handler string and executes your updated logic. * 仅应为新操作或路径添加路由。如果你引入了一个全新的方法(例如 `exampleAction`),请创建或更新一个路由条目,使其 `handler` 指向该操作,以便 HTTP 请求可以访问它。使用完全限定的处理程序语法 `::..`(例如,API 控制器使用 `api::restaurant.restaurant.exampleAction`,插件控制器使用 `plugin::menus.menu.exampleAction`)。 ¥Adding a route should only be done for new actions or paths. If you introduce a brand-new method such as `exampleAction`, create or update a route entry whose `handler` points to the action so HTTP requests can reach it. Use the fully-qualified handler syntax `::..` (e.g. `api::restaurant.restaurant.exampleAction` for an API controller or `plugin::menus.menu.exampleAction` for a plugin controller). * 关于控制器和路由文件名:默认控制器名称来自 `./src/api/[api-name]/controllers/` 中的文件名。使用 `createCoreRouter` 创建的核心路由将采用相同的名称,因此生成的处理程序字符串会自动匹配。自定义路由可以遵循任何文件命名方案,只要 `handler` 字符串引用已导出的控制器操作即可。 ¥Regarding controller and route filenames: the default controller name comes from the filename inside `./src/api/[api-name]/controllers/`. Core routers created with `createCoreRouter` adopt the same name, so the generated handler string matches automatically. Custom routers can follow any file naming scheme, as long as the `handler` string references an exported controller action. 以下示例添加了一个新的控制器操作,并通过自定义路由将其公开,而不会重复现有的 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: * 用户无权创建的关系 ¥relations the user do not have permission to create * 模式中不存在的无法识别的值 ¥unrecognized values that are not present on a schema * 不可写字段和内部时间戳(如 `createdAt` 和 `createdBy` 字段)标识 ¥non-writable fields and internal timestamps like `createdAt` and `createdBy` fields * 设置或更新 `id` 字段(连接关系除外) ¥setting or updating an `id` field (except for connecting relations) #### 使用控制器工厂时的消毒 {#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` | (EXPERIMENTAL)验证输入数据(无效数据引发错误) | 这些函数自动从模型继承清理设置,并根据内容类型架构和任何内容 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` 方法,例如 [清理自定义控制器](#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` 公开以下函数以进行清理和验证: ¥Within custom controllers, Strapi exposes the following functions via `strapi.contentAPI` for sanitization and validation: | 函数名称 | 参数 | 描述 | | ----------------------------------- | --------------------------- | --------------------------------------------------------- | | `strapi.contentAPI.sanitize.input` | `data`、`schema`、`auth` | 清理请求输入,包括不可写字段、删除受限关系以及插件添加的其他嵌套 "visitors" | | `strapi.contentAPI.sanitize.output` | `data`、`schema`、`auth` | 清理响应输出,包括受限关系、私有字段、密码和插件添加的其他嵌套 "visitors" | | `strapi.contentAPI.sanitize.query` | `ctx.query`、`schema`、`auth` | 清理请求查询,包括过滤器、排序、字段和填充 | | `strapi.contentAPI.validate.query` | `ctx.query`、`schema`、`auth` | 验证请求查询,包括过滤器、排序、字段(当前未填充) | | `strapi.contentAPI.validate.input` | `data`、`schema`、`auth` | (EXPERIMENTAL)验证请求输入,包括不可写字段、删除受限关系以及插件添加的其他嵌套 "visitors" | :::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` 时,将调用 "文章" 内容类型的默认控制器的 `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. :::
Collection type examples :::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). :::
Single type examples
## 用法 {#usage} ¥Usage 控制器被声明并附加到路由。调用路由时会自动调用控制器,因此通常不需要显式调用控制器。但是,[services](/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 }, }, ], }; ```
Example of a custom timer middleware
GraphQL 插件还允许使用不同语法的 [实现自定义中间件](/cms/plugins/graphql#middlewares)。 ¥The GraphQL plugin also allows [implementing custom middlewares](/cms/plugins/graphql#middlewares), with a different syntax. :::tip 发现已加载的中间件 运行 `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` 用于应用级中间件 ¥use `global::middleware-name` for application-level middlewares * 使用 `api::api-name.middleware-name` 作为 API 级中间件 ¥use `api::api-name.middleware-name` for API-level middlewares * 使用 `plugin::plugin-name.middleware-name` 作为插件中间件 ¥use `plugin::plugin-name.middleware-name` for plugin middlewares :::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 中,这被称为 "是所有者政策"。对于 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 生成器创建中间件。 ¥From your project's folder, create a middleware with the Strapi CLI generator, by running the `yarn strapi generate` (or `npm run strapi generate`) command in the terminal. 2. 使用键盘箭头从列表中选择 `middleware`,然后按 Enter。 ¥Select `middleware` from the list, using keyboard arrows, and press Enter. 3. 为中间件命名,例如 `isOwner`。 ¥Give the middleware a name, for instance `isOwner`. 4. 从列表中选择 `Add middleware to an existing API`。 ¥Choose `Add middleware to an existing API` from the list. 5. 选择你希望中间件应用哪个 API。 ¥Select which API you want the middleware to apply. 6. 将 `/src/api/[your-api-name]/middlewares/isOwner.js` 文件中的代码替换为以下内容,将第 22 行中的 `api::restaurant.restaurant` 替换为与你在步骤 5 中选择的 API 对应的标识符(例如,如果你的 API 名称是 `blog-post`,则为 `api::blog-post.blog-post`): ¥Replace the code in the `/src/api/[your-api-name]/middlewares/isOwner.js` file with the following, replacing `api::restaurant.restaurant` in line 22 with the identifier corresponding to the API you choose at step 5 (e.g., `api::blog-post.blog-post` if your API name is `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` 中间件。

例如,如果你希望允许任何用户对 `restaurant` API 中的 `restaurant` 内容类型发起 GET 请求(映射到 `find` 和 `findOne` 操作)和 POST 请求(即 `create` 操作),但希望将 PUT 请求(即 `update` 操作)和 DELETE 请求限制为仅允许创建该条目的用户发起,则可以在 `src/api/restaurant/routes/restaurant.js` 文件中使用以下代码: ¥Ensure the middleware is configured to apply on some routes. In the `config` object found in the `src/api/[your-api–name]/routes/[your-content-type-name].js` file, define the action keys (`find`, `findOne`, `create`, `update`, `delete`, etc.) for which you would like the middleware to apply, and declare the `isOwner` middleware for these routes.

For instance, if you wish to allow GET requests (mapping to the `find` and `findOne` actions) and POST requests (i.e., the `create` action) to any user for the `restaurant` content-type in the `restaurant` API, but would like to restrict PUT (i.e., `update` action) and DELETE requests only to the user who created the entry, you could use the following code in the `src/api/restaurant/routes/restaurant.js` file: ```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).h 中找到有关路由中间件的更多信息。 ¥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-types, which can be collection types or single types, depending on how many entries they manage, * 以及可在多种内容类型中重复使用的内容结构组件。 ¥and components that are content structures re-usable in multiple content-types. 如果你刚刚开始,直接在管理面板中使用 [内容类型生成器](/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) 一起, ¥with the [Content-type Builder in the admin panel](/cms/features/content-type-builder), * 或使用 [Strapi 的交互式 CLI `strapi generate`](/cms/cli#strapi-generate) 命令。 ¥or with [Strapi's interactive CLI `strapi generate`](/cms/cli#strapi-generate) command. 内容类型使用以下文件: ¥The content-types use the following files: * `schema.json` 表示模型的 [schema](#model-schema) 定义。(使用任一方法创建内容类型时自动生成) ¥`schema.json` for the model's [schema](#model-schema) definition. (generated automatically, when creating content-type with either method) * `lifecycles.js` 为 [生命周期钩子](#lifecycle-hooks)。该文件必须手动创建。 ¥`lifecycles.js` for [lifecycle hooks](#lifecycle-hooks). This file must be created manually. 这些模型文件存储在 `./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: * [settings](#model-settings),例如模型表示的内容类型类型或应存储数据的表名称, ¥[settings](#model-settings), such as the kind of content-type the model represents or the table name in which the data should be stored, * [information](#model-information),主要用于在管理面板中显示模型并通过 REST 和 GraphQL API 访问它, ¥[information](#model-information), mostly used to display the model in the admin panel and access it through the REST and GraphQL APIs, * [attributes](#model-attributes),描述模型的内容结构, ¥[attributes](#model-attributes), which describe the content structure of the model, * [options](#model-options) 用于定义模型上的特定行为。 ¥and [options](#model-options) used to defined specific behaviors on the model. ### 模型设置 {#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` 键描述了用于在管理面板中显示模型并通过 Content 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 路由和数据库/表集合。

应该是短横线大小写。 | | `pluralName` | 字符串 | 内容类型名称的复数形式。
用于生成 API 路由和数据库/表集合。

应该是短横线大小写。 | | `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: * 标量类型(例如字符串、日期、数字、布尔值等), ¥scalar types (e.g. strings, dates, numbers, booleans, etc.), * Strapi 特定类型,例如: ¥Strapi-specific types, such as: * `media` 表示通过 [媒体库](/cms/features/content-type-builder#media) 上传的文件 ¥`media` for files uploaded through the [Media library](/cms/features/content-type-builder#media) * `relation` 描述内容类型之间的 [relation](#relations) ¥`relation` to describe a [relation](#relations) between content-types * `customField` 描述 [自定义字段](#custom-fields) 及其具体按键 ¥`customField` to describe [custom fields](#custom-fields) and their specific keys * `component` 定义 [component](#components-json)(即可在多种内容类型中使用的内容结构) ¥`component` to define a [component](#components-json) (i.e. a content structure usable in multiple content-types) * `dynamiczone` 定义 [动态区](#dynamic-zones)(即基于组件列表的灵活空间) ¥`dynamiczone` to define a [dynamic zone](#dynamic-zones) (i.e. a flexible space based on a list of components) * 以及 `locale` 和 `localizations` 类型,仅由 [国际化 (i18n) 插件](/cms/features/internationalization) 使用 ¥and the `locale` and `localizations` types, only used by the [Internationalization (i18n) plugin](/cms/features/internationalization) 属性的 `type` 参数应为以下值之一: ¥The `type` parameter of an attribute should be one of the following values: | 类型类别 | 可用类型 | | ------------------------------------------------------------------------------------- | ---- | | 字符串类型 | | | 日期类型 | | | 号码类型 | | | 其他通用类型 | | | Strapi 独有的特殊类型 | | | 国际化 (i18n) 相关类型

仅当在内容类型上启用 [国际化](/cms/features/internationalization) 时才可使用 | | #### 验证 {#validations} ¥Validations 可以使用以下参数将基本验证应用于属性: ¥Basic validations can be applied to attributes using the following parameters: | 范围 | 类型 | 描述 | 默认 | | -------------- | --- | ------------------------------------------------- | ------- | | `required` | 布尔值 | 如果是 `true`,则为此属性添加必需的验证器 | `false` | | `max` | 整数 | 检查该值是否大于或等于给定的最大值 | * | | `min` | 整数 | 检查该值是否小于或等于给定的最小值 | * | | `minLength` | 整数 | 字段输入值的最小字符数 | * | | `maxLength` | 整数 | 字段输入值的最大字符数 | * | | `private` | 布尔值 | 如果 `true`,该属性将从服务器响应中删除。

💡这对于隐藏敏感数据很有用。 | `false` | | `configurable` | 布尔值 | 如果是 `false`,则无法通过 Content-type Builder 插件配置该属性。 | `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 🚧 此 API 被认为是实验性的。 这些设置应保留给高级用途,因为它们可能会破坏某些功能。没有计划使这些设置稳定。 ¥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` | string | 更改数据库中列的名称 | * | | `defaultTo` | string | 设置数据库 `defaultTo`,通常与 `notNullable` 一起使用 | * | | `notNullable` | 布尔值 | 设置数据库 `notNullable`,确保列不能为空 | `false` | | `unsigned` | 布尔值 | 仅适用于数字列,消除了负数的能力,但最大长度加倍 | `false` | | `unique` | 布尔值 | 对已发布的条目强制执行数据库级别的唯一性。启用“草稿和发布”功能后,草稿保存会跳过检查,因此重复项仅在发布时失败。 | `false` | | `type` | string | 更改数据库类型,如果 `type` 有参数,则应将它们传递到 `args` | * | | `args` | array | 传递到 Knex.js 函数的参数会更改 `type` 等内容 | `[]` | :::caution `unique`草稿& 发布和 启用 [起草并发布](/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: * 禁用必须保持全局唯一的内容类型的“草稿和发布”功能, ¥disable Draft & Publish on content-types that must stay globally unique, * 或添加自定义验证(例如生命周期钩子或中间件),在保存前检查草稿是否重复, ¥or add custom validation (e.g. lifecycle hooks or middleware) that checks for draft duplicates before saving, * 或依赖自动生成的唯一标识符,例如 `uid` 字段和文档编辑约定。 ¥or rely on automatically generated unique identifiers such as a `uid` field and document editorial conventions. ::: ```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` 类型用于根据 2 个可选参数,使用唯一标识符 (UID)(例如文章的别名)自动预填充管理面板中的字段值: ¥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。 ¥`targetField` (string): If used, the value of the field defined as a target is used to auto-generate the UID. * `options`(字符串):如果使用,则 UID 是根据传递给 #### 自定义字段 {#custom-fields} ¥Custom fields [自定义字段](/cms/features/custom-fields) 通过向内容类型添加新类型的字段来扩展 Strapi 的功能。自定义字段在带有 `type: customField` 的模型的 [attributes](#model-attributes) 中显式定义。 ¥[Custom fields](/cms/features/custom-fields) extend Strapi’s capabilities by adding new types of fields to content-types. Custom fields are explicitly defined in the [attributes](#model-attributes) of a model with `type: customField`. 自定义字段的属性还显示以下特性: ¥Custom fields' attributes also show the following specificities: * `customField` 属性,其值充当唯一标识符,指示应使用哪个已注册的自定义字段。其值如下: ¥a `customField` attribute whose value acts as a unique identifier to indicate which registered custom field should be used. Its value follows: * 如果插件创建了自定义字段,则为 `plugin::plugin-name.field-name` 格式 ¥either the `plugin::plugin-name.field-name` format if a plugin created the custom field * 或特定于当前 Strapi 应用的自定义字段的 `global::field-name` 格式 ¥or the `global::field-name` format for a custom field specific to the current Strapi application * 以及其他参数,具体取决于注册自定义字段时定义的内容(参见 [自定义字段文档](/cms/features/custom-fields))。 ¥and additional parameters depending on what has been defined when registering the custom field (see [custom fields documentation](/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 组件字段创建内容类型和组件结构之间的关系。组件在具有 `type: 'component'` 的模型的 [attributes](#model-attributes) 中显式定义,并接受以下附加参数: ¥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](#components-json) 的混合列表在其中编写内容。 ¥Dynamic zones create a flexible space in which to compose content, based on a mixed list of [components](#components-json). 动态区域在具有 `type: 'dynamiczone'` 的模型的 [attributes](#model-attributes) 中明确定义。它们还接受 `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 响应时间戳中删除它们。

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

默认值:`true`(如果内容类型是从交互式 CLI 创建的,则为 `false`)。 | | `populateCreatorFields` | 布尔值 | 利用插件中的 `createdBy` 和 `updatedBy` 钩子的插件开发者需要重构其代码。`false`。 | ```json title="./src/api/[api-name]/content-types/restaurant/schema.json" { "options": { "privateAttributes": ["id", "createdAt"], "draftAndPublish": true } } ``` ### 插件选项 {#plugin-options} ¥Plugin options `pluginOptions` 是一个可选对象,允许插件存储模型或特定属性的配置。 ¥`pluginOptions` is an optional object allowing plugins to store configuration for a model or a specific attribute. | 密钥 | 值 | 描述 | | ---------------------- | ----------------- | ------------------ | | `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 策略是在每个请求到达 [controller](/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 项目的每个 [route](/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](#plugin-policies),并且应位于相应的 `./src/api//policies/` 或 `./src/plugins//policies/` 文件夹下。 ¥Policies can be global or scoped. [Global policies](#global-policies) can be associated to any route in the project. Scoped policies only apply to a specific [API](#api-policies) or [plugin](#plugin-policies) and should live under the corresponding `./src/api//policies/` or `./src/plugins//policies/` folder.
Simplified Strapi backend diagram with routes and policies highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with policies and routes highlighted. The backend customization introduction page includes a complete, interactive diagram.
## 执行 {#implementation} ¥Implementation 可以实现一项新政策: ¥A new policy can be implemented: * 与 [交互式 CLI 命令 `strapi generate`](/cms/cli#strapi-generate) ¥with the [interactive CLI command `strapi generate`](/cms/cli#strapi-generate) * 或通过在适当的文件夹中手动创建 JavaScript 文件(参见 [项目结构](/cms/project-structure)): ¥or manually by creating a JavaScript file in the appropriate folder (see [project structure](/cms/project-structure)): * `./src/policies/` 全局政策 ¥`./src/policies/` for global policies * API 政策的 `./src/api/[api-name]/policies/` ¥`./src/api/[api-name]/policies/` for API policies * `./src/plugins/[plugin-name]/policies/` 用于插件策略 ¥`./src/plugins/[plugin-name]/policies/` for plugin policies
全局政策实现示例: ¥Global policy implementation example: `policyContext` 是 [controller](/cms/backend-customization/controllers) 上下文的封装器。它添加了一些可用于实现 REST 和 GraphQL 策略的逻辑。 ¥`policyContext` is a wrapper around the [controller](/cms/backend-customization/controllers) context. It adds some logic that can be useful to implement a policy for both REST and 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) ¥use `global::policy-name` for [global policies](#global-policies) * 使用 `api::api-name.policy-name` 代替 [API 政策](#api-policies) ¥use `api::api-name.policy-name` for [API policies](#api-policies) * 使用 `plugin::plugin-name.policy-name` 代替 [插件政策](#plugin-policies) ¥use `plugin::plugin-name.policy-name` for [plugin policies](#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))。 ¥The Strapi back end server is based on . When you send requests through the [REST API](/cms/api/rest), a context object (`ctx`) is passed to every element of the Strapi back end (e.g., [policies](/cms/backend-customization/policies), [controllers](/cms/backend-customization/controllers), [services](/cms/backend-customization/services)). `ctx` 包括 3 个主要对象: ¥`ctx` includes 3 main objects: * [`ctx.request`](#ctxrequest) 有关客户端发出 API 请求所发送的请求的信息, ¥[`ctx.request`](#ctxrequest) for information about the request sent by the client making an API request, * [`ctx.state`](#ctxstate) 有关 Strapi 后端内请求状态的信息, ¥[`ctx.state`](#ctxstate) for information about the state of the request within the Strapi back end, * 和 [`ctx.response`](#ctxresponse) 有关服务器将返回的响应的信息。 ¥and [`ctx.response`](#ctxresponse) for information about the response that the server will return. :::tip 提示 还可以使用 [`strapi.requestContext` function](#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 信息 除了以下文档中描述的概念和参数外,你还可以在 、 和 中找到其他信息。 ¥In addition to the concepts and parameters described in the following documentation, you might find additional information in the , and . :::
Simplified Strapi backend diagram with requests and responses highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with requests and responses highlighted. The backend customization introduction page includes a complete, interactive diagram.
## `ctx.request` {#ctxrequest} `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 数组,按从上游到下游的顺序排列。

例如,如果值为 "客户端、代理 1、代理 2",你将收到 `["client", "proxy1", "proxy2"]` 数组。 | `Array` | | `ctx.request.method` | 请求方法(例如,`GET`、`POST`)。 | `String` | | `ctx.request.origin` | 第一个 `/` 之前的 URL 部分。 | `String` | | `ctx.request.params` | URL 中发送的参数。

例如,如果内部 URL 是 `/restaurants/:id`,那么你在实际请求中替换 `:id` 的任何内容都可以通过 `ctx.request.params.id` 访问。 | `Object` | | `ctx.request.path` | 请求资源的路径,不包括查询参数。 | `String` | | `ctx.request.protocol` | 正在使用的协议(例如,`https` 或 `http`)。 | `String` | | `ctx.request.query` | 表带专用 [查询参数](#ctxrequestquery)。 | `Object` | | `ctx.request.subdomains` | URL 中包含的子域名。

例如域名为 `tobi.ferrets.example.com`,则值为以下数组:`["ferrets", "tobi"]`。 | `Array` | | `ctx.request.url` | 所请求资源的路径和查询参数,不包括协议、域和端口。 | `String` |
Differences between protocol, origin, url, href, path, host, and hostname : 给定发送到 `https://example.com:1337/api/restaurants?id=123` URL 的 API 请求,以下是 `ctx.request` 对象返回的不同参数: ¥Given an API request sent to the `https://example.com:1337/api/restaurants?id=123` URL, here is what different parameters of the `ctx.request` object return: | 范围 | 返回值 | | ---------------------- | ------------------------------------------------- | | `ctx.request.href` | `https://example.com:1337/api/restaurants?id=123` | | `ctx.request.protocol` | `https` | | `ctx.request.host` | `localhost:1337` | | `ctx.request.hostname` | `localhost` | | `ctx.request.origin` | `https://example.com:1337` | | `ctx.request.url` | `/api/restaurants?id=123` | | `ctx.request.path` | `/api/restaurants` |
### `ctx.request.query` {#ctxrequestquery} `ctx.request` 提供了一个 `query` 对象,可以访问 Strapi 查询参数。下表列出了可用参数以及简短说明和相关 REST API 文档部分的链接(有关更多信息,请参阅 [REST API 参数](/cms/api/rest/parameters)): ¥`ctx.request` provides a `query` object that gives access to Strapi query parameters. The following table lists available parameters with a short description and a link to the relevant REST API documentation section (see [REST API parameters](/cms/api/rest/parameters) for more information): | 范围 | 描述 | 类型 | | ------------------------------------ | -------------------------------------------------------------------- | ------------------- | | `ctx.request.query`
`ctx.query` | 整个查询对象。 | `Object` | | `ctx.request.query.sort` | [对响应进行排序](/cms/api/rest/sort-pagination.md#sorting) 的参数 | `String` 或 `Array` | | `ctx.request.query.filters` | [过滤响应](/cms/api/rest/filters) 的参数 | `Object` | | `ctx.request.query.populate` | [填充关系、组件或动态区域](/cms/api/rest/populate-select#population) 的参数 | `String` 或 `Object` | | `ctx.request.query.fields` | [仅选择与响应一起返回的特定字段](/cms/api/rest/populate-select#field-selection) 的参数 | `Array` | | `ctx.request.query.pagination` | 参数 [逐页浏览条目](/cms/api/rest/sort-pagination.md#pagination) | `Object` | | `ctx.request.query.publicationState` | 参数 [选择草稿和发布状态](/cms/api/rest/status) | `String` | | `ctx.request.query.locale` | 参数 [选择一个或多个区域设置](/cms/api/rest/locale) | `String` 或 `Array` | ## `ctx.state` {#ctxstate} `ctx.state` 对象可以访问 Strapi 后端内的请求状态,包括有关 [user](#ctxstateuser)、[authentication](#ctxstateauth)、[route](#ctxstateroute) 的特定值: ¥The `ctx.state` object gives access to the state of the request within the Strapi back end, including specific values about the [user](#ctxstateuser), [authentication](#ctxstateauth), [route](#ctxstateroute): | 范围 | 描述 | 类型 | | --------------------------- | -------------------- | --------- | | `ctx.state.isAuthenticated` | 返回当前用户是否以任何方式进行身份验证。 | `Boolean` | ### `ctx.state.user` {#ctxstateuser} `ctx.state.user` 对象允许访问有关执行请求的用户的信息,并包含以下参数: ¥The `ctx.state.user` object gives access to information about the user performing the request and includes the following parameters: | 范围 | 描述 | 类型 | | --------------------- | -------------- | -------- | | `ctx.state.user` | 用户的信息。仅填充一种关系。 | `Object` | | `ctx.state.user.role` | 用户的角色 | `Object` | ### `ctx.state.auth` {#ctxstateauth} `ctx.state.auth` 对象提供对与身份验证相关的信息的访问,并包含以下参数: ¥The `ctx.state.auth` object gives access to information related to the authentication and includes the following parameters: | 范围 | 描述 | 类型 | | ------------------------------ | -------------------------------------------------------------------------------------------- | -------- | | `ctx.state.auth.strategy` | 当前使用的认证策略信息([用户和权限插件](/cms/features/users-permissions) 或 [API 令牌](/cms/features/api-tokens)) | `Object` | | `ctx.state.auth.strategy.name` | 当前使用的策略名称 | `String` | | `ctx.state.auth.credentials` | 用户的凭据 | `String` | ### `ctx.state.route` {#ctxstateroute} `ctx.state.route` 对象可以访问与当前路由相关的信息,并包含以下参数: ¥The `ctx.state.route` object gives access to information related to the current route and includes the following parameters: | 范围 | 描述 | 类型 | | ------------------------------ | ---------------------------------- | -------- | | `ctx.state.route.method` | 用于访问当前路由的方法。 | `String` | | `ctx.state.route.path` | 当前路由的路径。 | `String` | | `ctx.state.route.config` | 当前路由的配置信息。 | `Object` | | `ctx.state.route.handler` | 当前路由的处理程序(控制器)。 | `Object` | | `ctx.state.route.info` | 有关当前路由的其他信息,例如 apiName 和 API 请求类型。 | `Object` | | `ctx.state.route.info.apiName` | 使用的 API 的名称。 | `String` | | `ctx.state.route.info.type` | 使用的 API 的类型。 | `String` | ## `ctx.response` {#ctxresponse} `ctx.response` 对象允许访问与服务器将返回的响应相关的信息,并包含以下参数: ¥The `ctx.response` object gives access to information related to the response that the server will return and includes the following parameters: | 范围 | 描述 | 类型 | | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | `ctx.response.body` | 响应正文。 | `Any` | | `ctx.response.status` | 响应的状态代码。 | `Integer` | | `ctx.response.message` | 响应的状态消息。

默认情况下,`response.message` 与 `response.status` 关联。 | `String` | | `ctx.response.header`
`ctx.response.headers` | 随响应一起发送的标头。 | `Object` | | `ctx.response.length` | 标头值(如果存在)作为数字,或者在可能的情况下从 `ctx.body` 推断出来;否则,返回 `undefined`。 | `Integer` | | `ctx.response.redirect`
`ctx.response.redirect(url, [alt])` | 对 URL 执行 `302` 重定向。字符串 "back" 是特殊大小写的,以提供 Referrer 支持;当 Referrer 不存在时,使用 alt 或 "/"。

示例:`ctx.response.redirect('back', '/index.html');` | `Function` | | `ctx.response.attachment`

`ctx.response.attachment([filename], [options])` | 将 标头设置为 "attachment",以向客户端发出信号提示下载。可选择指定下载的文件名和一些 。 | `Function` | | `ctx.response.type` | 标头,没有 "charset" 等参数。 | `String` | | `ctx.response.lastModified` | 标头作为日期(如果存在)。 | `DateTime` | | `ctx.response.etag` | 设置响应的 ,包括封装的“s。
没有相应的 `response.etag` getter。 | `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); }, }; ``` **示例:** ¥**Example:** ```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 功能使上下文在任何地方都可用。 ¥Strapi uses a Node.js feature called to make the context available anywhere. ::: # 路由 Source: https://docs.strapi.io/cms/backend-customization/routes # 路由 {#routes} ¥Routes 通过任何 URL 发送到 Strapi 的请求均由路由处理。默认情况下,Strapi 为所有内容类型生成路由(参见 [REST API 文档](/cms/api/rest))。路由可以是 [added](#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](#policies),这是一种阻止访问路由的方法, ¥with [policies](#policies), which are a way to block access to a route, * 以及 [middlewares](#middlewares),这是一种控制和更改请求流和请求本身的方法。 ¥and with [middlewares](#middlewares), which are a way to control and change the request flow and the request itself. 一旦存在一条路由,到达该路由就会执行一些由控制器处理的代码(参见 [控制器文档](/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. :::
Simplified Strapi backend diagram with routes highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with routes highlighted. The backend customization introduction page includes a complete, interactive diagram.
## 执行 {#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) ¥configuring [core routers](#configuring-core-routers) * 或创建 [定制路由](#creating-custom-routers)。 ¥or creating [custom routers](#creating-custom-routers). ### 配置核心路由 {#configuring-core-routers} ¥Configuring core routers 核心路由(即 `find`、`findOne`、`create`、`update` 和 `delete`)对应于创建新 [content-type](/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: * 将配置选项传递给每个路由 ¥passing in configuration options to each router * 并禁用一些核心路由到 [创建自定义的](#creating-custom-routers)。 ¥and disabling some core routers to [create custom ones](#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` | 只会加载的核心路由

任何不在此数组中的内容都会被忽略。 | `Array` | --> | | `except` | 不应加载的核心路由

这在功能上与 `only` 参数相反。 | `Array` | | | `config` | 配置处理路由的 [policies](#policies)、[middlewares](#middlewares) 和 [公开可用性](#public-routes) | `Object` | |

通用实现示例: ¥Generic implementation example: 这仅允许来自核心 `find` [controller](/cms/backend-customization/controllers) 的 `/restaurants` 路径上的 `GET` 请求,无需身份验证。在自定义路由中引用自定义控制器操作时,为了清晰起见,建议使用完整的 `api::..` 格式(例如 `api::restaurant.restaurant.review`)。 ¥This only allows a `GET` request on the `/restaurants` path from the core `find` [controller](/cms/backend-customization/controllers) without authentication. When you reference custom controller actions in custom routers, prefer the fully‑qualified `api::..` form for clarity (e.g., `api::restaurant.restaurant.review`). ### 创建自定义路由 {#creating-custom-routers} ¥Creating custom routers 创建自定义路由包括创建一个导出对象数组的文件,每个对象都是具有以下参数的路由: ¥Creating custom routers consists in creating a file that exports an array of objects, each object being a route with the following parameters: | 范围 | 描述 | 类型 | | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | | `method` | 与路由相关的方法(即 `GET`、`POST`、`PUT`、`DELETE` 或 `PATCH`) | `String` | | `path` | 到达路径,以正斜线开头(例如 `/articles`) | `String` | | `handler` | 到达路由时要执行的函数。
使用完全限定语法 `api::api-name.controllerName.actionName`(或 `plugin::plugin-name.controllerName.actionName`)。旧版项目的简短 `.` 形式也适用。 | `String` | | `config`

可选 | 配置处理路由的 [policies](#policies)、[middlewares](#middlewares) 和 [公开可用性](#public-routes)

| `Object` |
可以使用参数和正则表达式创建动态路由。这些参数将在 `ctx.params` 对象中公开。有关更多详细信息,请参阅
## 配置 {#configuration} ¥Configuration [核心路由](#configuring-core-routers) 和 [定制路由](#creating-custom-routers) 具有相同的配置选项。路由配置在 `config` 对象中定义,可用于处理 [policies](#policies) 和 [middlewares](#middlewares) 或 [公开路由](#public-routes)。 ¥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) 可以添加到路由配置中: ¥[Policies](/cms/backend-customization/policies) can be added to a route configuration: * 通过指向 `./src/policies` 中注册的策略,无论是否传递自定义配置 ¥by pointing to a policy registered in `./src/policies`, with or without passing a custom configuration * 或直接声明策略实现,将其作为以 `policyContext` 扩展 ### 中间件 {#middlewares} ¥Middlewares [中间件](/cms/backend-customization/middlewares) 可以添加到路由配置中: ¥[Middlewares](/cms/backend-customization/middlewares) can be added to a route configuration: * 通过指向 `./src/middlewares` 中注册的中间件,无论是否传递自定义配置 ¥by pointing to a middleware registered in `./src/middlewares`, with or without passing a custom configuration * 或直接声明中间件实现,将其作为以 ### 公共路由 {#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`: # 服务 Source: https://docs.strapi.io/cms/backend-customization/services # 服务 {#services} ¥Services 服务是一组可重用的功能。它们对于尊重 "不要重复自己" (DRY) 编程概念和简化 [controllers](/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.
Simplified Strapi backend diagram with services highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with services highlighted. The backend customization introduction page includes a complete, interactive diagram.
## 执行 {#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) ¥with the [interactive CLI command `strapi generate`](/cms/cli#strapi-generate) * 或通过在适当的文件夹中手动创建 JavaScript 文件(参见 [项目结构](/cms/project-structure.md)): ¥or manually by creating a JavaScript file in the appropriate folder (see [project structure](/cms/project-structure.md)): * `./src/api/[api-name]/services/` 用于 API 服务 ¥`./src/api/[api-name]/services/` for API services * 或 `./src/plugins/[plugin-name]/services/` 对应 [插件服务](/cms/plugins-development/server-api#services)。 ¥or `./src/plugins/[plugin-name]/services/` for [plugin services](/cms/plugins-development/server-api#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 文档服务 API 要开始创建你自己的服务,请参阅 [文档服务 API](/cms/api/document-service) 文档中的 Strapi 内置函数。 ¥To get started creating your own services, see Strapi's built-in functions in the [Document Service API](/cms/api/document-service) documentation. :::
Example of a custom email service (using 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 注意 当创建新的 [content-type](/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 核心服务是为每种内容类型创建的,[controllers](/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`). :::
Collection type examples
Single type examples
## 用法 {#usage} ¥Usage 创建服务后,可以从 [controllers](/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 核心服务方法接受与其底层 [文档服务 API](/cms/api/document-service) 调用相同的参数,例如 `fields`, `filters`、`sort`、`pagination`、`populate`、`locale` 和 `status`。当未提供 `status` 时,Strapi 会自动设置 `status: 'published'`,因此只返回已发布的内容。要查询草稿文档,请显式传递 `status: 'draft'` 或文档服务支持的其他值。 ¥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 是告诉第三方提供商开始某些处理(CI、构建、部署...)的好方法。 ¥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). ## 用户内容类型 webhook {#user-content-type-webhooks} ¥User content-type webhooks 为了防止无意中将任何用户信息发送到其他应用,Webhooks 不适用于用户内容类型。如果需要通知其他应用有关 Users 集合中的更改,可以通过使用 `./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`.conf 中设置 webhook 配置。 ¥You can set webhook configurations inside the file `./config/server`. * `webhooks` * `defaultHeaders`:你可以设置用于 Webhook 请求的默认标头。此选项将被 webhook 本身中设置的标头覆盖。 ¥`defaultHeaders`: You can set default headers to use for your webhook requests. This option is overwritten by the headers set in the webhook itself. **配置示例** ¥**Example configuration** ## 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: * 生成共享密钥并将其存储在环境变量中。 ¥Generate a shared secret and store it in environment variables * 让发送方对原始请求正文加上时间戳计算 HMAC(例如,SHA-256)。 ¥Have the sender compute an HMAC (e.g., SHA‑256) over the raw request body plus a timestamp * 在标头中发送签名(和时间戳)(例如,`X‑Webhook‑Signature`、`X‑Webhook‑Timestamp`) ¥Send the signature (and timestamp) in headers (e.g., `X‑Webhook‑Signature`, `X‑Webhook‑Timestamp`) * 收到请求后,重新计算 HMAC 并使用恒定时间检查进行比较。 ¥On receipt, recompute the HMAC and compare using a constant‑time check * 如果签名无效或时间戳过旧,无法避免重放攻击,则拒绝请求。 ¥Reject if the signature is invalid or the timestamp is too old to mitigate replay
Example: Verify HMAC signatures (Node.js) 以下是一个最小化的 Node.js 中间件示例(伪代码),展示了 ` 以下是一些额外的外部示例: ¥Here 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) | 发布版本时触发(参见 [发布](/cms/features/releases))。
此事件仅适用于 Strapi CMS 的 或 计划。 | *仅当在此内容类型上启用 `draftAndPublish` 时。 ¥*only when `draftAndPublish` is enabled on this Content Type. ## 有效载荷 {#payloads} ¥Payloads :::tip 注意 打印当前安装的 Strapi 版本。 ¥Private fields and s 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` {#entrycreate} 创建新条目时会触发此事件。 ¥This event is triggered when a new entry is created. **有效负载示例** ¥**Example payload** ```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` {#entryupdate} 当条目更新时会触发此事件。 ¥This event is triggered when an entry is updated. **有效负载示例** ¥**Example payload** ```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` {#entrydelete} 当删除条目时会触发此事件。 ¥This event is triggered when an entry is deleted. **有效负载示例** ¥**Example payload** ```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` {#entrypublish} 发布条目时会触发此事件。 ¥This event is triggered when an entry is published. **有效负载示例** ¥**Example payload** ```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` {#entryunpublish} 当条目未发布时会触发此事件。 ¥This event is triggered when an entry is unpublished. **有效负载示例** ¥**Example payload** ```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` {#mediacreate} 当你在条目创建时或通过媒体界面上传文件时,会触发此事件。 ¥This event is triggered when you upload a file on entry creation or through the media interface. **有效负载示例** ¥**Example payload** ```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` {#mediaupdate} 当你通过媒体接口更换媒体或更新媒体元数据时,会触发该事件。 ¥This event is triggered when you replace a media or update the metadata of a media through the media interface. **有效负载示例** ¥**Example payload** ```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` {#mediadelete} 仅当你通过媒体接口删除媒体时才会触发该事件。 ¥This event is triggered only when you delete a media through the media interface. **有效负载示例** ¥**Example payload** ```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` {#review-workflowsupdateentrystage} 此事件仅适用于 Strapi 的 计划。
当内容移至新的审核阶段(参见 [审查工作流程](/cms/features/review-workflows#configuration))时会触发此事件。 ¥This event is only available with the plan of Strapi.
The event is triggered when content is moved to a new review stage (see [Review Workflows](/cms/features/review-workflows#configuration)). **有效负载示例** ¥**Example payload** ```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. **有效负载示例** ¥**Example payload** ```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 * 通过检查标头和有效负载签名来验证传入请求。 ¥Validate incoming requests by checking headers and payload signatures. * 对失败的 webhook 请求实现重试以处理瞬态错误。 ¥Implement retries for failed webhook requests to handle transient errors. * 记录 webhook 事件以进行调试和监控。 ¥Log webhook events for debugging and monitoring. * 使用安全的 HTTPS 端点接收 webhook。 ¥Use secure, HTTPS endpoints for receiving webhooks. * 设置速率限制以避免被多个 webhook 请求淹没。 ¥Set up rate limiting to avoid being overwhelmed by multiple webhook requests. :::tip 提示 如果你想了解更多关于如何在 Next.js 中使用 webhook 的信息,请查看 [专用博客文章](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`)或专用节点包执行器(例如 `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 -- --
### `compression` {#compression} `compression` 中间件基于
### `cors` {#cors} 此安全中间件是关于跨源资源共享(CORS)的,基于
Example: Custom configuration for the cors middleware within a function as parameter `origin` 可以接受遵循以下签名的函数作为参数 ¥`origin` can take a Function as parameter following this signature ```ts title="./config/middlewares.ts" // ... { name: 'strapi::cors', config: { origin: (ctx): string | string[] => { const origin = ctx.request.header.origin; if (origin === 'http://localhost:3000') { return origin; // The returns will be part of the Access-Control-Allow-Origin header } return ''; // Fail cors check } }, }, // ... ] ```
### `errors` {#errors} 错误中间件处理代码抛出的 [errors](/cms/error-handling.md)。它根据错误类型为响应设置适当的 HTTP 状态。默认情况下,任何不应向终端用户公开的错误都将导致 500 HTTP 响应。 ¥The errors middleware handles [errors](/cms/error-handling.md) thrown by the code. Based on the type of error it sets the appropriate HTTP status to the response. By default, any error not supposed to be exposed to the end user will result in a 500 HTTP response. 中间件没有任何配置选项。 ¥The middleware doesn't have any configuration options. ### `favicon` {#favicon} `favicon` 中间件提供图标服务,基于
#### `ip` {#ip} `ip` 中间件是一个 IP 过滤器中间件,基于
### `logger` {#logger} `logger` 中间件用于记录请求。 ¥The `logger` middleware is used to log requests. 要为 `logger` 中间件定义自定义配置,请创建专用配置文件 (`./config/logger.js`)。它应该导出一个对象,该对象必须是完整或部分的
### `poweredBy` {#poweredby} `poweredBy` 中间件在响应头中添加了 `X-Powered-By` 参数。它接受以下选项: ¥The `poweredBy` middleware adds a `X-Powered-By` parameter to the response header. It accepts the following options: | 选项 | 描述 | 类型 | 默认值 | | ----------- | ------------------- | -------- | ---------------------- | | `poweredBy` | `X-Powered-By` 标头的值 | `String` | `'Strapi '` |
details Example: Custom configuration for the poweredBy middleware
### `query` {#query} `query` 中间件是一个基于
### `response-time` {#response-time} `response-time` 中间件启用响应标头的 `X-Response-Time`(以毫秒为单位)。 ¥The `response-time` middleware enables the `X-Response-Time` (in milliseconds) for the response header. 中间件没有任何配置选项。 ¥The middleware doesn't have any configuration options. ### `public` {#public} `public` 中间件是一个静态文件服务中间件,基于
### `security` {#security} 安全中间件基于
### `session` {#session} `session` 中间件允许使用基于 cookie 的会话,基于
# 插件配置 Source: https://docs.strapi.io/cms/configurations/plugins # 插件配置 {#plugins-configuration} ¥Plugins configuration 插件配置存储在 `/config/plugins.js|ts` 中(参见 [项目结构](/cms/project-structure))。每个插件都可以配置以下可用参数: ¥Plugin configurations are stored in `/config/plugins.js|ts` (see [project structure](/cms/project-structure)). Each plugin can be configured with the following available parameters: | 范围 | 描述 | 类型 | | ------------------------- | --------------------------------------------------------------------------------------- | --- | | `enabled` | 启用 (`true`) 或禁用 (`false`) 已安装的插件 | 布尔值 | | `config`

可选 | 用于覆盖默认插件配置([在 Strapi-server.js 中定义](/cms/plugins-development/server-api#configuration)) | 目的 | | `resolve`
可选,仅本地插件需要 | 插件文件夹的路径 | 字符串 | :::note 注意 Strapi 的一些功能由插件提供,以下插件也可以具有特定的配置选项:[GraphQL](/cms/plugins/graphql#code-based-configuration) 插件、支持媒体库的 [上传](/cms/features/media-library#available-options) 软件包以及 [用户和权限](/cms/features/users-permissions#code-based-configuration)。 ¥Some features of Strapi are provided by plugins and the following plugins can also have specific configuration options: the [GraphQL](/cms/plugins/graphql#code-based-configuration) plugin, the [Upload](/cms/features/media-library#available-options) package which powers the Media Library, and [Users & Permissions](/cms/features/users-permissions#code-based-configuration). ::: **插件的基本示例自定义配置:** ¥**Basic example custom configuration for plugins:** :::tip 提示 如果不需要具体配置,也可以使用简写语法 `'plugin-name': true` 来声明插件。 ¥If no specific configuration is required, a plugin can also be declared with the shorthand syntax `'plugin-name': true`. ::: # 服务器配置 Source: https://docs.strapi.io/cms/configurations/server # 服务器配置 {#server-configuration} ¥Server configuration `/config/server.js` 文件用于定义 Strapi 应用的服务器配置。 ¥The `/config/server.js` file is used to define the server configuration for a Strapi application. :::caution 提醒 对 `server.js` 文件的更改需要重建管理面板。保存修改后的文件后,在终端中运行 `yarn build` 或 `npm run build` 以实现更改。 ¥Changes to the `server.js` file require rebuilding the admin panel. After saving the modified file run either `yarn build` or `npm run build` in the terminal to implement the changes. ::: ## 可用选项 {#available-options} ¥Available options `./config/server.js` 文件可以包含以下参数: ¥The `./config/server.js` file can include the following parameters: | 范围 | 描述 | 类型 | 默认 | | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | | `host`

❗️必填 | 主机名 | string | `localhost` | | `port`

❗️必填 | 服务器应运行的端口。 | integer | `1337` | | `app.keys`

❗️必填 | 声明会话密钥(基于 # TypeScript 配置 Source: https://docs.strapi.io/cms/configurations/typescript # TypeScript 配置 {#typescript-configuration} ¥TypeScript configuration 支持 [TypeScript](/cms/typescript) 的 Strapi 项目具有特定的项目结构,并通过 [`tsconfig.json` files](#project-structure-and-typescript-specific-configuration-files) 处理 TypeScript 项目配置。 ¥[TypeScript](/cms/typescript)-enabled Strapi projects have a specific project structure and handle TypeScript project configuration through [`tsconfig.json` files](#project-structure-and-typescript-specific-configuration-files). Strapi 还具有配置为 [在 `config/typescript.js|ts` 文件中](#strapi-specific-configuration-for-typescript) 的专用 TypeScript 功能。 ¥Strapi also has dedicated TypeScript features that are configured [in the `config/typescript.js|ts` file](#strapi-specific-configuration-for-typescript). ## 项目结构和特定于 TypeScript 的配置文件 {#project-structure-and-typescript-specific-configuration-files} ¥Project structure and TypeScript-specific configuration files 支持 TypeScript 的 Strapi 应用有一个特定的 [项目结构](/cms/project-structure),其中包含以下专用文件夹和配置文件: ¥TypeScript-enabled Strapi applications have a specific [project structure](/cms/project-structure) with the following dedicated folders and configuration files: | TypeScript 特定的目录和文件 | 地点 | 目的 | | ------------------- | -------------- | ------------------------------------------------------------------------ | | `./dist` 目录 | 应用根目录 | 添加项目 JavaScript 源代码的编译位置。 | | `build` 目录 | `./dist` | 包含已编译的管理面板 JavaScript 源代码。该目录是在第一个 `yarn build` 或 `npm run build` 命令上创建的 | | `tsconfig.json` 文件 | 应用根目录 | 管理服务器的 TypeScript 编译。 | | `tsconfig.json` 文件 | `./src/admin/` | 管理管理面板的 TypeScript 编译。 | ## TypeScript 的 Strapi 特定配置 {#strapi-specific-configuration-for-typescript} ¥Strapi-specific configuration for TypeScript :::caution 🚧 此功能被视为实验性的。 这些设置被视为实验性的,可能会出现问题或破坏某些功能。 ¥These settings are considered experimental and might have issues or break some features. ::: Strapi 生成的类型基于用户项目结构。一旦类型定义被发送到其专用文件中,Strapi 就会读取类型定义以相应地调整自动补齐结果。 ¥Types generated by Strapi are based on the user project structure. Once the type definitions are emitted into their dedicated files, Strapi reads the type definitions to adapt the autocompletion results accordingly. 为了避免每次服务器重新启动时都必须 [手动生成类型](/cms/typescript/development#generate-typings-for-content-types-schemas),可以添加一个可选的 `config/typescript.js|ts` 配置文件,该文件目前只接受一个参数: ¥To avoid having to [manually generate types](/cms/typescript/development#generate-typings-for-content-types-schemas) every time the server restarts, an optional `config/typescript.js|ts` configuration file can be added, which currently accepts only one parameter: | 范围 | 描述 | 类型 | 默认 | | -------------- | ------------------- | --------- | ------- | | `autogenerate` | 启用或禁用服务器重新启动时自动生成类型 | `Boolean` | `false` | **示例:** ¥**Example:** # 定制化 Source: https://docs.strapi.io/cms/customization # 定制化 {#customization} ¥Customization Strapi 包括 2 个主要组件: ¥Strapi includes 2 main components: * Strapi 的后端部分是一个服务器,它接收请求并处理它们以返回响应,这些响应可以显示你通过内容类型生成器和内容管理器构建和保存的数据。后端服务器在 [后端定制介绍](/cms/backend-customization) 中有更详细的描述。后端服务器的大部分部分都可以定制。 ¥The back-end part of Strapi is a **server** that receives requests and handles them to return responses that can surface the data you built and saved through the Content-Type Builder and Content Manager. The backend server is described in more details in the [Backend Customization introduction](/cms/backend-customization). Most of the parts of the backend server can be customized. * Strapi 面向用户的前端部分称为管理面板。管理面板是你用来构建内容结构、创建和管理内容以及执行可由内置或第三方插件管理的各种其他操作的图形用户界面 (GUI)。管理面板的某些部分可以自定义。 ¥The front-end, user-facing part of Strapi is called the **admin panel**. The admin panel is the graphical user interface (GUI) that you use to build a content structure, create and manage content, and perform various other actions that can be managed by built-in or 3rd-party plugins. Some parts of the admin panel can be customized. 从更大的角度来看,这就是 Strapi 在典型的通用设置中的集成方式:Strapi 包括两个部分:后端服务器和管理面板,并与数据库(存储数据)和显示数据的外部前端应用交互。Strapi 的两个部分都可以在一定程度上进行定制。 ¥From a bigger picture, this is how Strapi integrates in a typical, generic setup: Strapi includes 2 parts, a back-end server and an admin panel, and interact with a database (which stores data) and an external, front-end application that displays your data. Both parts of Strapi can be customized to some extent. :::info 信息 自定义数据库或外部前端应用超出了本文档部分的范围。 ¥Customizing the database or the external, front-end application are outside of the scope of the present documentation section. * 你可以通过阅读安装文档(其中列出了 [支持的数据库](/cms/installation/cli#preparing-the-installation))和配置文档(描述了如何对你的项目进行 [配置数据库](/cms/configurations/database))来了解有关 Strapi 数据库使用情况的更多信息。 ¥You can learn more about databases usage with Strapi by reading the installation documentation, which lists [supported databases](/cms/installation/cli#preparing-the-installation), and the configuration documentation, which describes how to [configure a database](/cms/configurations/database) with your project. * 你可以通过阅读 Strapi 的 了解有关外部前端应用如何与 Strapi 交互的更多信息。 ¥You can learn more about how external front-end applications can interact with Strapi by reading the Strapi's . ::: # 数据库迁移 Source: https://docs.strapi.io/cms/database-migrations # 数据库迁移 {#database-migrations} ¥Database migrations 数据库迁移的目的是对数据库运行一次性查询,通常是在升级 Strapi 应用时修改表结构或数据。这些迁移会在应用启动时自动运行,并在 Strapi 启动时执行的自动模式迁移之前执行。 ¥Database migrations exist to run one-time queries against the database, typically to modify the tables structure or the data when upgrading the Strapi application. These migrations are run automatically when the application starts and are executed before the automated schema migrations that Strapi also performs on boot. :::callout 🚧 实验特性 数据库迁移是实验性的。该功能仍在开发中,并将继续更新和改进。同时,请随时在 此外,如果你想继续使用现有的 JavaScript 迁移和 TypeScript 迁移,你可以在 `tsconfig.json` 文件的编译器选项中设置 `allowJs: true`,如 [数据库配置文档](/cms/configurations/database#settings-configuration-object) 中所述。 ¥Additionally, if you want to continue using existing JavaScript migrations alongside TypeScript migrations, you can set `allowJs: true` in your `tsconfig.json` file's compiler options, as mentioned in the [database configuration documentation](/cms/configurations/database#settings-configuration-object). # 数据库事务 Source: https://docs.strapi.io/cms/database-transactions # 数据库事务 {#database-transactions} ¥Database transactions :::caution 提醒 这是一个实验性功能,可能会在未来版本中发生变化。 ¥This is an experimental feature and is subject to change in future versions. ::: Strapi 5 提供一个 API 来将一组操作封装在一个事务中,以确保数据的完整性。 ¥Strapi 5 provide an API to wrap a set of operations in a transaction that ensures the integrity of data. 事务是一组作为单个单元一起执行的操作。如果任何操作失败,则整个事务失败,数据将回滚到其先前的状态。如果所有操作都成功,则提交事务并将数据永久保存到数据库中。 ¥Transactions are a set of operations that are executed together as a single unit. If any of the operations fail, the entire transaction fails and the data is rolled back to its previous state. If all operations succeed, the transaction is committed and the data is permanently saved to the database. ## 用法 {#usage} ¥Usage 事务通过将处理程序函数传递到 `strapi.db.transaction` 来处理: ¥Transactions are handled by passing a handler function into `strapi.db.transaction`: ```js await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => { // It will implicitly use the transaction await strapi.entityService.create(); await strapi.entityService.create(); }); ``` 执行事务处理程序后,如果所有操作都成功,则提交事务。如果任何操作抛出,则回滚事务并将数据恢复到其先前的状态。 ¥After the transaction handler is executed, the transaction is committed if all operations succeed. If any of the operations throws, the transaction is rolled back and the data is restored to its previous state. :::note 注意 在事务块中执行的每个 `strapi.entityService` 或 `strapi.db.query` 操作都将隐式使用该事务。 ¥Every `strapi.entityService` or `strapi.db.query` operation performed in a transaction block will implicitly use the transaction. ::: ### 事务处理程序属性 {#transaction-handler-properties} ¥Transaction handler properties 处理程序函数接收具有以下属性的对象: ¥The handler function receives an object with the following properties: | 属性 | 描述 | | ------------ | ------------------------ | | `trx` | 事务对象。它可用于在事务中执行 knex 查询。 | | `commit` | 用于提交事务的函数。 | | `rollback` | 用于回滚事务的函数。 | | `onCommit` | 用于注册将在事务提交后执行的回调的函数。 | | `onRollback` | 用于注册将在事务回滚后执行的回调的函数。 | ### 嵌套事务 {#nested-transactions} ¥Nested transactions 事务可以嵌套。当事务嵌套时,当外部事务提交或回滚时,内部事务也会提交或回滚。 ¥Transactions can be nested. When a transaction is nested, the inner transaction is committed or rolled back when the outer transaction is committed or rolled back. ```js await strapi.db.transaction(async () => { // It will implicitly use the transaction await strapi.entityService.create(); // Nested transactions will implicitly use the outer transaction await strapi.db.transaction(async ({}) => { await strapi.entityService.create(); }); }); ``` ### onCommit 和 onRollback {#oncommit-and-onrollback} ¥onCommit and onRollback `onCommit` 和 `onRollback` 钩子可用于在事务提交或回滚后执行代码。 ¥The `onCommit` and `onRollback` hooks can be used to execute code after the transaction is committed or rolled back. ```js await strapi.db.transaction(async ({ onCommit, onRollback }) => { // It will implicitly use the transaction await strapi.entityService.create(); await strapi.entityService.create(); onCommit(() => { // This will be executed after the transaction is committed }); onRollback(() => { // This will be executed after the transaction is rolled back }); }); ``` ### 使用 knex 查询 {#using-knex-queries} ¥Using knex queries 事务也可以与 knex 查询一起使用,但在这些情况下必须明确调用 `.transacting(trx)`。 ¥Transactions can also be used with knex queries, but in those cases `.transacting(trx)` must be explicitly called. ```js await strapi.db.transaction(async ({ trx, rollback, commit }) => { await knex('users').where('id', 1).update({ name: 'foo' }).transacting(trx); }); ``` ## 何时使用事务 {#when-to-use-transactions} ¥When to use transactions 在多个操作应一起执行且它们的执行相互依赖的情况下,应使用事务。例如,在创建新用户时,应在数据库中创建该用户,并向该用户发送欢迎电子邮件。如果电子邮件发送失败,则不应在数据库中创建用户。 ¥Transactions should be used in cases where multiple operations should be executed together and their execution is dependent on each other. For example, when creating a new user, the user should be created in the database and a welcome email should be sent to the user. If the email fails to send, the user should not be created in the database. ## 何时不使用事务 {#when-not-to-use-transactions} ¥When not to use transactions 事务不应用于不相互依赖的操作,因为它可能导致性能损失。 ¥Transactions should not be used for operations that are not dependent on each other since it can result in performance penalties. ## 事务的潜在问题 {#potential-problems-of-transactions} ¥Potential problems of transactions 在事务内执行多个操作可能会导致锁定,这可能会阻止其他进程执行事务,直到原始事务完成。 ¥Performing multiple operations within a transaction can lead to locking, which can block the execution of transactions from other processes until the original transaction is complete. 此外,如果事务未正确提交或回滚,则可能会停滞。 ¥Furthermore, transactions can stall if they are not committed or rolled back appropriately. 例如,如果打开了事务,但代码中有一个路径没有关闭它,则事务将无限期保持打开状态,并可能导致不稳定,直到重新启动服务器并强制关闭连接。这些问题可能难以调试,因此在必要时请谨慎使用事务。 ¥For example, if a transaction is opened but there is a path in your code that does not close it, the transaction will be left open indefinitely and could cause instability until your server is restarted and the connection is forced to close. These issues can be difficult to debug, so use transactions with care in the cases they are necessary. # 部署 Source: https://docs.strapi.io/cms/deployment # 部署 {#deployment} ¥Deployment Strapi 为你的项目或应用提供了许多部署选项。你的 Strapi 应用可以部署在传统托管服务器或你首选的托管提供者上。 ¥Strapi provides many deployment options for your project or application. Your Strapi applications can be deployed on traditional hosting servers or your preferred hosting provider. 以下文档介绍了如何使用几个常见的托管选项准备 Strapi 以进行部署的基础知识。 ¥The following documentation covers the basics of how to prepare Strapi for deployment on with several common hosting options. :::strapi Strapi 云 你可以使用 [Strapi 云](/cloud/intro) 快速部署和托管你的项目。 ¥You can use [Strapi Cloud](/cloud/intro) to quickly deploy and host your project. ::: :::tip 提示 如果你已经使用 Content-Type Builder 创建了内容结构,并通过 Content Manager 将一些数据添加到本地(开发)Strapi 实例,则可以利用 [数据管理系统](/cms/features/data-management) 将数据从 Strapi 实例传输到另一个实例。 ¥If you already created a content structure with the Content-Type Builder and added some data through the Content Manager to your local (development) Strapi instance, you can leverage the [data management system](/cms/features/data-management) to transfer data from a Strapi instance to another one. 另一种可能的工作流程是首先在本地创建内容结构,将项目推送到基于 git 的存储库,将更改部署到生产环境,然后再将内容添加到生产实例。 ¥Another possible workflow is to first create the content structure locally, push your project to a git-based repository, deploy the changes to production, and only then add content to the production instance. ::: ## 一般准则 {#general-guidelines} ¥General guidelines ### 硬件和软件要求 {#hardware-and-software-requirements} ¥Hardware and software requirements 为了为 Strapi 提供尽可能最佳的环境,以下要求适用于开发(本地)以及登台和生产工作流程。 ¥To provide the best possible environment for Strapi the following requirements apply to development (local) and staging and production workflows. 使用 `production` 设置运行服务器: ¥Run the server with the `production` settings: :::caution 提醒 我们强烈建议使用 来管理你的流程。 ¥We highly recommend using to manage your process. ::: 如果你需要 server.js 文件能够运行 `node server.js` 而不是 `npm run start`,则创建一个 `./server.js` 文件,如下所示: ¥If you need a server.js file to be able to run `node server.js` instead of `npm run start` then create a `./server.js` file as follows: ```js title="path: ./server.js" const strapi = require('@strapi/strapi'); strapi.createStrapi(/* {...} */).start(); ``` :::caution 提醒 如果你正在开发基于 `TypeScript` 的项目,则必须提供 `distDir` 选项来启动服务器。如需了解更多信息,请参阅 [TypeScript 文档](/cms/typescript/development#use-the-createstrapi-factory)。 ¥If you are developing a `TypeScript`-based project you must provide the `distDir` option to start the server. For more information, consult the [TypeScript documentation](/cms/typescript/development#use-the-createstrapi-factory). ::: :::tip 健康检查端点 Strapi 在 `/_health` 处公开了一条轻量级的健康检查路由,供正常运行时间监控器和负载均衡器使用。服务器准备就绪后,会返回 HTTP `204 No Content` 状态码和 `strapi: You are so French!` 标头值,你可以使用这些信息来确认应用是否可访问。 ¥Strapi exposes a lightweight health check route at `/_health` for uptime monitors and load balancers. When the server is ready, it responds with an HTTP `204 No Content` status and a `strapi: You are so French!` header value, which you can use to confirm the application is reachable. ::: ### 高级配置 {#advanced-configurations} ¥Advanced configurations 如果你想在 API 之外的另一台服务器上托管管理,请使用 [请看一下这个专门的部分](/cms/configurations/admin-panel#deploy-on-different-servers)。 ¥If you want to host the administration on another server than the API, [please take a look at this dedicated section](/cms/configurations/admin-panel#deploy-on-different-servers). ## 其他资源 {#additional-resources} ¥Additional resources :::prerequisites * 你的 Strapi 项目是 [created](/cms/installation),其代码托管在 GitHub 上。 ¥Your Strapi project is [created](/cms/installation) and its code is hosted on GitHub. * 你已阅读 [一般部署指南](/cms/deployment#general-guidelines)。 ¥You have read the [general deployment guidelines](/cms/deployment#general-guidelines). ::: Strapi 网站的 包含有关如何将 Strapi 与许多资源集成的信息,包括如何在以下第三方平台上部署 Strapi: ¥The of the Strapi website include information on how to integrate Strapi with many resources, including how to deploy Strapi on the following 3rd-party platforms:
此外,社区维护的其他提供商指南可在 中找到。这包括以下指南: ¥In addition, community-maintained guides for additional providers are available in the . This includes the following guides:
以下外部指南(非 Strapi 官方维护)可能也有助于在各种环境中部署 Strapi: ¥The following external guide(s), not officially maintained by Strapi, might also help deploy Strapi on various environments: :::strapi 多租户 如果你正在寻找多租户选项,Strapi 博客有一个 。 ¥If you're looking for multi-tenancy options, the Strapi Blog has a . ::: # 错误处理 Source: https://docs.strapi.io/cms/error-handling # 错误处理 {#error-handling} ¥Error handling Strapi 本身就以标准格式处理错误。 ¥Strapi is natively handling errors with a standard format. 错误处理有 2 个用例: ¥There are 2 use cases for error handling: * 作为通过 [REST](/cms/api/rest) 或 [GraphQL](/cms/api/graphql) API 查询内容的开发者,你可能会 [接收错误](#receiving-errors) 来响应请求。 ¥As a developer querying content through the [REST](/cms/api/rest) or [GraphQL](/cms/api/graphql) APIs, you might [receive errors](#receiving-errors) in response to the requests. * 作为自定义 Strapi 应用后端的开发者,你可以使用 [抛出错误](#throwing-errors) 的控制器和服务。 ¥As a developer customizing the backend of your Strapi application, you could use controllers and services to [throw errors](#throwing-errors). ## 接收错误 {#receiving-errors} ¥Receiving errors 错误包含在带有 `error` 键的响应对象中,并包含 HTTP 状态代码、错误名称和其他信息等信息。 ¥Errors are included in the response object with the `error` key and include information such as the HTTP status code, the name of the error, and additional information. ### REST 错误 {#rest-errors} ¥REST errors REST API 引发的错误包含在具有以下格式的 [response](/cms/api/rest#requests) 中: ¥Errors thrown by the REST API are included in the [response](/cms/api/rest#requests) that has the following format: ```json { "data": null, "error": { "status": "", // HTTP status "name": "", // Strapi error name ('ApplicationError' or 'ValidationError') "message": "", // A human readable error message "details": { // error info specific to the error type } } } ``` ### GraphQL 错误 {#graphql-errors} ¥GraphQL errors GraphQL API 抛出的错误包含在具有以下格式的响应中: ¥Errors thrown by the GraphQL API are included in the response that has the following format: ```json { "errors": [ { "message": "", // A human reable error message "extensions": { "error": { "name": "", // Strapi error name ('ApplicationError' or 'ValidationError'), "message": "", // A human reable error message (same one as above); "details": {}, // Error info specific to the error type }, "code": "" // GraphQL error code (ex: BAD_USER_INPUT) } } ], "data": { "graphQLQueryName": null } } ``` ## 投掷错误 {#throwing-errors} ¥Throwing errors
### 控制器和中间件 {#controllers-and-middlewares} ¥Controllers and middlewares 使用 Strapi 开发任何自定义逻辑时抛出错误的推荐方法是让 [controller](/cms/backend-customization/controllers) 或 [中间件](/cms/backend-customization/middlewares) 以正确的状态和正文进行响应。 ¥The recommended way to throw errors when developing any custom logic with Strapi is to have the [controller](/cms/backend-customization/controllers) or [middleware](/cms/backend-customization/middlewares) respond with the correct status and body. 这可以通过在上下文(即 `ctx`)上调用错误函数来完成。可用的错误函数列在 ### 服务和模型生命周期 {#services-and-models-lifecycles} ¥Services and models lifecycles 一旦你在比控制器或中间件更深的层上工作,就会有专用的错误类可用于引发错误。这些类是 #### 示例:在模型生命周期中抛出错误\*\* {#example-throwing-an-error-in-a-model-lifecycle} ¥Example: Throwing an error in a model lifecycle\*\* 此示例展示了构建 [自定义模型生命周期](/cms/backend-customization/models#lifecycle-hooks) 并能够抛出错误以停止请求并向管理面板返回正确的错误消息。一般来说,你应该只在 `beforeX` 生命周期中抛出错误,而不是 `afterX` 生命周期中。 ¥This example shows building a [custom model lifecycle](/cms/backend-customization/models#lifecycle-hooks) and being able to throw an error that stops the request and will return proper error messages to the admin panel. Generally you should only throw an error in `beforeX` lifecycles, not `afterX` lifecycles. ### 政策 {#policies} ¥Policies [政策](/cms/backend-customization/policies) 是一种特殊类型的中间件,在控制器之前执行。它们用于检查用户是否被允许执行该操作。如果不允许用户执行该操作并且使用了 `return false`,则将引发一般错误。或者,你可以使用嵌套类扩展从 Strapi `ForbiddenError` 类、`ApplicationError` 类(两个类均参见 [默认错误类别](#default-error-classes))以及最后的 ### 默认错误类别 {#default-error-classes} ¥Default error classes 默认错误类可从 `@strapi/utils` 包中获取,并且可以在代码中导入和使用。任何默认错误类都可以扩展以创建自定义错误类。然后可以在代码中使用自定义错误类来引发错误。 ¥The default error classes are available from the `@strapi/utils` package and can be imported and used in your code. Any of the default error classes can be extended to create a custom error class. The custom error class can then be used in your code to throw errors. # 管理面板 Source: https://docs.strapi.io/cms/features/admin-panel # 管理面板 {#administration-panel} ¥Administration panel 管理面板是 Strapi 应用的后台。从管理面板,你将能够管理内容类型并编写其实际内容,还可以管理用户(包括管理员和 Strapi 应用的终端用户)。 ¥The admin panel is the back office of your Strapi application. From the admin panel, you will be able to manage content-types and write their actual content, but also manage users, both administrators and end users of your Strapi application. ### 修改个人资料信息(名称、电子邮件、用户名) {#modifying-profile-information-name-email-username} ¥Modifying profile information (name, email, username) 1. 转到个人资料的个人资料部分。 ¥Go to the *Profile* section of your profile. 2. 填写以下选项: ¥Fill in the following options: | 简介与经验 | 指示 | | ----- | ------------------ | | 名 | 在文本框中写下你的名字。 | | 姓 | 在文本框中写下你的姓氏。 | | 电子邮件 | 在文本框中写下你的完整电子邮件地址。 | | 用户名 | (可选)在文本框中写入用户名。 | 3. 单击“保存”按钮。 ¥Click on the **Save** button. ### 更改账户密码 {#changing-account-password} ¥Changing account password 1. 转到个人资料的更改密码部分。 ¥Go to the *Change password* section of your profile. 2. 填写以下选项: ¥Fill in the following options: | 密码修改 | 指示 | | ---- | -------------- | | 当前密码 | 在文本框中写下你当前的密码。 | | 密码 | 在文本框中输入新密码。 | | 密码确认 | 在文本框中输入相同的新密码。 | 3. 单击“保存”按钮。 ¥Click on the **Save** button. :::tip 提示 你可以单击 图标以显示密码。 ¥You can click on the icon for the passwords to be shown. ::: ### 选择界面语言 {#choosing-interface-language} ¥Choosing interface language 在个人资料的体验部分中,使用界面语言下拉菜单选择你的首选语言。 ¥In the *Experience* section of your profile, select your preferred language using the *Interface language* dropdown. :::note 注意 请记住,选择界面语言仅适用于管理面板上的账户。同一应用管理面板的其他用户可以使用不同的语言。 ¥Keep in mind that choosing an interface language only applies to your account on the admin panel. Other users of the same application's admin panel can use a different language. ::: ### 选择界面模式(浅色、深色) {#choosing-interface-mode-light-dark} ¥Choosing interface mode (light, dark) 默认情况下,所选的界面模式基于浏览器的模式。但是,你可以在个人资料的“体验”部分中,使用界面模式下拉列表手动选择“亮模式”或“夜间模式”。 ¥By default, the chosen interface mode is based on your browser's mode. You can however, in the *Experience* section of your profile, manually choose either the Light Mode or Dark Mode using the *Interface mode* dropdown. :::note 注意 请记住,选择界面模式仅适用于管理面板上的账户。 ¥Keep in mind that choosing an interface mode only applies to your account on the admin panel. ::: ### 重置导览 {#resetting-guided-tour} ¥Resetting guided tour 在你个人资料的“导览”部分,你可以点击“重置导览”按钮来重置管理面板主页上的导览。如果你之前关闭了管理面板的导览,你可以再次查看导览,并再次遵循其各个步骤。 ¥In the *Guided tour* section of your profile, you can click the **Reset guided tour** button to reset the guided tour which is available in the homepage of the admin panel. It allows you to see again the guided tour of the admin panel if you closed it beforehand, and to follow again its various steps. ### 定制徽标 {#customizing-the-logo} ¥Customizing the logo 配置管理面板的路径: 设置 > 全局设置 > 概览 ¥**Path to configure the admin panel:** *Settings > Global settings > Overview* 可以修改 Strapi 应用主导航和身份验证页面中显示的默认 Strapi 徽标。 ¥The default Strapi logos, displayed in the main navigation of a Strapi application and the authentication pages, can be modified. 1. 单击菜单徽标或身份验证徽标的上传区域。 ¥Click on the upload area for *Menu logo* or *Auth logo*. 2. 通过浏览文件、将文件拖放到右侧区域或使用 URL 来上传你选择的徽标。徽标不应超过 750x750 像素。 ¥Upload your chosen logo, either by browsing files, drag & dropping the file in the right area, or by using a URL. The logo shouldn't be more than 750x750px. 3. 单击上传窗口中的上传徽标按钮。 ¥Click on the **Upload logo** button in the upload window. 4. 单击右上角的“保存”按钮。 ¥Click on the **Save** button in the top right corner. 上传后,新徽标可以用另一个替换,或者用默认的 Strapi 徽标或配置文件中设置的徽标重置。 ¥Once uploaded, the new logo can be replaced with another one , or reset with the default Strapi logo or the logo set in the configuration files. :::note 注意 这两个徽标也可以通过 Strapi 应用的配置文件以编程方式进行自定义(请参阅 [管理面板定制](/cms/admin-panel-customization/logos))。但是,通过管理面板上传的徽标将取代通过配置文件设置的任何徽标。 ¥Both logos can also be customized programmatically via the Strapi application's configuration files (see [Admin panel customization](/cms/admin-panel-customization/logos)). However, the logos uploaded via the admin panel supersedes any logo set through the configuration files. ::: ## 用法 {#usage} ¥Usage :::caution 提醒 为了访问管理面板,必须启动你的 Strapi 应用,并且你必须知道其管理面板的 URL(例如 `api.example.com/admin`)。 ¥In order to access the admin panel, your Strapi application must be launched, and you must be aware of the URL to its admin panel (e.g. `api.example.com/admin`). ::: 要访问管理面板: ¥To access the admin panel: 1. 转至 Strapi 应用管理面板的 URL。 ¥Go to the URL of your Strapi application's admin panel. 2. 输入你的凭据以登录。 ¥Enter your credentials to log in. 3. 单击登录按钮。你应该被重定向到管理面板的主页。 ¥Click on the **Login** button. You should be redirected to the homepage of the admin panel. :::note 注意 如果你更喜欢或需要通过 SSO 提供商登录,请参阅 [单点登录文档](/cms/features/sso)。 ¥If you prefer or are required to log in via an SSO provider, please refer to the [Single Sign-On documentation](/cms/features/sso). ::: # API 令牌 Source: https://docs.strapi.io/cms/features/api-tokens # API 令牌 {#api-tokens} ¥API Tokens API 令牌允许用户验证 REST 和 GraphQL API 查询(请参阅 [API 介绍](/cms/api/content-api))。 ¥API tokens allow users to authenticate REST and GraphQL API queries (see [APIs introduction](/cms/api/content-api)). :::caution 安全 优先使用只读令牌进行公共访问,将服务器令牌的范围限定在所需范围内,轮换长期有效的令牌,并将它们存储在密钥管理器中。切勿在客户端代码中暴露管理员令牌。 ¥Prefer read‑only tokens for public access, scope server tokens to only what you need, rotate long‑lived tokens, and store them in a secrets manager. Never expose admin tokens in client‑side code. ::: 此密钥用于加密和解密令牌值。如果没有此密钥,令牌仍然可用,但在首次显示后将无法查看。新的 Strapi 项目将自动生成此密钥。 ¥This key is used to encrypt and decrypt token values. Without this key, tokens remain usable, but will not be viewable after initial display. New Strapi projects will have this key automatically generated. ## 用法 {#usage} ¥Usage 使用 API 令牌允许以经过身份验证的用户身份在 [REST API](/cms/api/rest) 或 [GraphQL API](/cms/api/graphql) 端点上执行请求。 ¥Using API tokens allows executing a request on [REST API](/cms/api/rest) or [GraphQL API](/cms/api/graphql) endpoints as an authenticated user. API 令牌有助于授予人员或应用访问权限,而无需管理用户账户或更改用户和权限插件中的任何内容。 ¥API tokens can be helpful to give access to people or applications without managing a user account or changing anything in the Users & Permissions plugin. 在对 Strapi 的 REST API 执行请求时,应使用以下语法将 API 令牌添加到请求的 `Authorization` 标头中:`bearer your-api-token`。 ¥When performing a request to Strapi's REST API, the API token should be added to the request's `Authorization` header with the following syntax: `bearer your-api-token`. :::note 注意 只读 API 令牌只能访问 `find` 和 `findOne` 功能。 ¥Read-only API tokens can only access the `find` and `findOne` functions. ::: # 审核日志 Source: https://docs.strapi.io/cms/features/audit-logs # 审核日志 {#audit-logs} ¥Audit Logs 审计日志功能提供可搜索和可过滤的显示,显示 Strapi 应用用户执行的所有活动。 ¥The Audit Logs feature provides a searchable and filterable display of all activities performed by users of the Strapi application. ## 用法 {#usage} ¥Usage 使用功能的路径: 设置 > 管理面板 - 审核日志 ¥**Path to use the feature:** Settings > Administration Panel - Audit Logs 审计日志功能记录以下事件: ¥The Audit Logs feature logs the following events: | 事件 | 行动 | | --------- | ------------------------------------------------ | | 内容类型 | `create`、`update`、`delete` | | 入口(草稿/发布) | `create`、`update`、`delete`、`publish`、`unpublish` | | 媒体 | `create`、`update`、`delete` | | 登录/注销 | `success`、`fail` | | 角色/权限 | `create`、`update`、`delete` | | 用户 | `create`、`update`、`delete` | 对于每个日志项,将显示以下信息: ¥For each log item, the following information is displayed: * 行动:用户执行的操作类型(例如 `create` 或 `update`)。 ¥Action: type of action performed by the user (e.g.`create` or `update`). * 日期:操作的日期和时间。 ¥Date: date and time of the action. * 用户:执行操作的用户。 ¥User: user who performed the action. * 细节:显示一个模式,其中包含有关操作的更多详细信息(例如用户 IP 地址、请求正文或响应正文)。 ¥Details: displays a modal with more details about the action (e.g. the User IP address, the request body, or the response body). ### 过滤日志 {#filtering-logs} ¥Filtering logs 默认情况下,所有日志均按时间倒序显示。你可以通过以下方式过滤日志: ¥By default, all logs are displayed in reverse chronological order. You can filter the logs by: * 行动:选择要过滤的操作类型(例如 `create` 或 `update`)。 ¥Action: select the type of action to filter by (e.g `create` or `update`). * 用户:选择要过滤的用户。 ¥User: select the user to filter by. * 日期:选择要过滤的日期(范围)和时间。 ¥Date: select a date (range) and time to filter by. ### 访问日志详细信息 {#log-details} ¥Accessing log details 对于任何日志项,单击 图标以访问包含有关该操作的更多详细信息的模式。在模式中,Payload 部分在交互式 JSON 组件中显示详细信息,使你能够展开和折叠 JSON 对象。 ¥For any log item, click the icon to access a modal with more details about that action. In the modal, the *Payload* section displays the details in an interactive JSON component, enabling you to expand and collapse the JSON object. # 内容历史记录 Source: https://docs.strapi.io/cms/features/content-history # 内容历史记录 {#content-history} ¥Content History ## 用法 {#usage} ¥Usage 使用功能的路径: 内容管理器
从内容类型的编辑视图:单击 (右上角),然后单击 内容历史记录。 ¥**Path to use the feature:** Content Manager
From the edit view of a content type: click (top right corner) then **Content History**. ### 浏览内容历史记录 {#browsing-content-history} ¥Browsing Content History 使用内容历史记录,你可以通过以下方式浏览内容: ¥With Content History, you can browse your content through: * 左侧的主视图列出了右侧侧边栏中所选版本的字段及其内容。 ¥The main view on the left, which lists the fields and their content for the version selected in the sidebar on the right. * 右侧的侧边栏列出了可用版本的总数以及每个版本: ¥The sidebar on the right, which lists the total number of versions available, and for each version: * 创建版本的日期和时间, ¥the date and time when the version was created, * 创建它的用户, ¥the user who created it, * 以及其状态是草稿、已修改还是已发布(有关文档状态的更多信息,请参阅 [起草并发布](/cms/features/draft-and-publish))。 ¥and whether its status is Draft, Modified, or Published (see [Draft & Publish](/cms/features/draft-and-publish) for more information about document statuses). :::note 注意 内容历史记录的主视图清楚地说明了字段在内容类型的其他版本中是不存在、删除还是重命名。所选版本未知的字段将显示在其他字段下方的未知字段标题下。 ¥The main view of Content History clearly states whether a field was inexistent, deleted, or renamed in other versions of the content-type. Fields that are unknown for the selected version will be displayed under an *Unknown fields* heading below the other fields. ::: ### 恢复以前的版本 {#restoring-a-previous-version} ¥Restoring a previous version 你可以选择恢复文档的先前版本。当恢复版本时,此版本的内容将覆盖当前草稿版本的内容。文档切换到“已修改”状态,然后你可以随时发布内容(参见 [发布草稿](/cms/features/draft-and-publish#publishing-a-draft))。 ¥You can choose to restore a previous version of a document. When restoring a version, the content of this version will override the content of the current draft version. The document switches to the Modified status and you will then be able to publish the content whenever you want (see [Publishing a draft](/cms/features/draft-and-publish#publishing-a-draft)). 1. 浏览内容历史记录并通过右侧的侧边栏选择一个版本。 ¥Browse the Content History and select a version via the sidebar on the right. 2. 单击恢复按钮。 ¥Click the **Restore** button. 3. 在确认窗口中,单击恢复。 ¥In the *Confirmation* window, click **Restore**. :::note 注意 如果内容类型启用了 [国际化(i18n)](/cms/features/internationalization) 功能,则恢复具有唯一字段的版本(即,所有语言环境的内容相同的字段)将恢复所有语言环境的此字段的内容。 ¥If the [Internationalization (i18n)](/cms/features/internationalization) feature is enabled for the content-type, restoring a version with a unique field (i.e. a field whose content is the same for all locales) will restore the content of this field for all locales. ::: # 内容管理者 Source: https://docs.strapi.io/cms/features/content-manager # 内容管理者 {#content-manager} ¥Content Manager 从 ## 概述 {#overview} ¥Overview ### 配置编辑视图 {#edit-view-settings} ¥Configuring the edit view ## 用法 {#usage} ¥Usage
### 创建和编写内容 {#creating--writing-content} ¥Creating & Writing content 在 Strapi 中,编写内容包括填写字段,这些字段旨在包含特定内容(例如文本、数字、媒体等)。这些字段预先通过 [内容类型生成器](/cms/features/content-type-builder).config 配置为集合或单一类型。 ¥In Strapi, writing content consists in filling up fields, which are meant to contain specific content (e.g. text, numbers, media, etc.). These fields were configured for the collection or single type beforehand, through the [Content-type Builder](/cms/features/content-type-builder). #### 动态区域 {#dynamic-zones} ¥Dynamic zones 动态区域是组件的组合,组件本身又由多个字段组成。写入动态区域的内容需要额外的步骤才能访问这些字段。 ¥Dynamic zones are a combination of components, which themselves are composed of several fields. Writing the content of a dynamic zone requires additional steps in order to access the fields. :::tip 提示 * 默认情况下并未列出所有条目:单击“加载更多”按钮可以显示更多内容。此外,你可以单击任何关系字段下拉列表并键入来搜索特定条目,而不是通过滚动列表来选择条目。 ¥Not all entries are listed by default: more can be displayed by clicking on the **Load more** button. Also, instead of choosing an entry by scrolling the list, you can click any relational field drop-down list and type to search a specific entry. * 单击条目名称以显示模式,你可以从中编辑关系字段的内容类型。目前,你只能即时编辑关系,而不能创建新关系。 ¥Click on the name of an entry to display a modal from where you will be able to edit the relational field's content-type. For now, you can only edit a relation on-the-fly and not create a new one. ::: :::note 注意 * 如果为关系字段所属的内容类型激活了 [草稿和发布功能](/cms/features/draft-and-publish),你会注意到下拉列表中条目名称旁边的蓝点或绿点。它们指示条目的状态,分别是草稿或已发布的内容。 ¥If the [Draft & Publish feature](/cms/features/draft-and-publish) is activated for the content-type the relational field belongs to, you will notice blue or green dots next to the entries names in the drop-down list. They indicate the status of the entry, respectively draft or published content. * 如果为内容类型启用了 [国际化 (i18n) 功能](/cms/features/internationalization),则条目列表可能会受到限制或因语言环境而异。仅列出可能为关系字段选择的相关条目。 ¥If the [Internationalization (i18n) feature](/cms/features/internationalization) is enabled for the content-type, the list of entries may be limited or differ from one locale to another. Only relevant entries that can possibly be chosen for a relational field will be listed. ::: ### 删除内容 {#deleting-content} ¥Deleting content 你可以通过删除集合类型的任意条目或单一类型的默认条目来删除内容。 ¥You can delete content by deleting any entry of a collection type, or the default entry of a single type. 1. 在条目的编辑视图中,点击界面右上角的,然后点击删除文档按钮。
如果内容类型启用了国际化,你还可以选择仅删除当前选定的语言环境,方法是点击删除语言环境按钮。 ¥In the edit view of the entry, click on at the top right of the interface, and click the **Delete document** button.
If Internationalization is enabled for the content-type, you can also choose to delete only the currently selected locale by clicking on the **Delete locale** button. 2. 在弹出的窗口中,单击确认按钮确认删除。 ¥In the window that pops up, click on the **Confirm** button to confirm the deletion. :::tip 提示 你可以通过单击表中条目记录右侧的 ,然后选择 删除文档按钮,从集合类型的列表视图中删除条目。
如果内容类型启用了 [国际化](/cms/features/internationalization),则删除文档会删除所有语言环境,而删除语言环境只会删除当前列出的语言环境。 ¥You can delete entries from the list view of a collection type, by clicking on on the right side of the entry's record in the table, then choosing the **Delete document** button.
If [Internationalization](/cms/features/internationalization) is enabled for the content-type, **Delete document** deletes all locales while **Delete locale** only deletes the currently listed locale. # 内容类型生成器 Source: https://docs.strapi.io/cms/features/content-type-builder # 内容类型生成器 {#content-type-builder} ¥Content-type Builder 从 ## 概述 {#overview} ¥Overview 3. 点击对话框中的“完成”按钮。 ¥Click the **Finish** button in the dialog. 4. 点击内容类型构建器导航栏中的“保存”按钮。 ¥Click the **Save** button in the Content-Type Builder navigation. #### 字段 {#fields} ¥Fields 从列出内容类型字段的表格中,你可以: ¥From the table that lists the fields of your content-type, you can: * 点击 #### 富文本(块) {#rich-text-blocks} ¥ Rich Text (Blocks) 富文本(块)字段显示具有实时渲染功能的编辑器以及用于管理富文本的各种选项。该字段可用于长的书面内容,甚至包括图片和代码。 ¥The Rich Text (Blocks) field displays an editor with live rendering and various options to manage rich text. This field can be used for long written content, even including images and code. :::strapi React 渲染器 如果使用 Blocks 编辑器,我们建议你还使用 #### 日期 {#date} ¥ Date 日期字段可以显示日期(年、月、日)、时间(时、分、秒)或日期时间(年、月、日、时、分、秒)选择器。 ¥The Date field can display a date (year, month, day), time (hour, minute, second) or datetime (year, month, day, hour, minute, and second) picker. #### 密码 {#img-width28-srcimgassetsiconsv5ctbpasswordsvg--password} ¥ Password 密码字段显示已加密的密码字段。 ¥The Password field displays a password field that is encrypted. #### 媒体 {#media} ¥ Media 媒体字段允许从应用媒体库中上传的媒体文件中选择一个或多个媒体文件(例如图片、视频)。 ¥The Media field allows to choose one or more media files (e.g. image, video) from those uploaded in the Media Library of the application. #### 关系 {#relation} ¥ Relation Relation 字段允许与另一个内容类型建立关系,该内容类型必须是集合类型。 ¥The Relation field allows to establish a relation with another content-type, that must be a collection type. 有 6 种不同类型的关系: ¥There are 6 different types of relations: * 一种方法:内容类型 A 有一个内容类型 B ¥ One way: Content-type A *has one* Content-type B * 一对一:内容类型 A 具有并属于一个内容类型 B ¥ One-to-one: Content-type A *has and belong to one* Content-type B * 一对多:内容类型 A 属于多个内容类型 B ¥ One-to-many: Content-type A *belongs to many* Content-type B * 多对一:内容类型 B 有许多内容类型 A ¥ Many-to-one: Content-type B *has many* Content-type A * 多对多:内容类型 A 拥有并属于多个内容类型 B ¥ Many-to-many: Content-type A *has and belongs to many* Content-type B * 多种方式:内容类型 A 有许多内容类型 B ¥ Many way: Content-type A *has many* Content-type B :::info 多重关系和单重关系 至少一方可以引用多个条目的关系称为多重关系。在内容类型构建器中,这包括一对多、多对一、多对多和多路关系。这些关系在内容管理器中显示为多选字段,并从 REST、GraphQL 和文档服务 API 返回数组;而单个关系(单向和一对一关系)则返回单个链接条目(更多信息请参见 [管理与 API 请求的关系](/cms/api/rest/relations))。 ¥Relations where at least one side can reference several entries are called multi relations. In the Content-type Builder, this includes one-to-many, many-to-one, many-to-many, and many-way relations. These relations appear as multi-select fields in the Content Manager and return arrays from the REST, GraphQL, and Document Service APIs; while single relations (one-way and one-to-one relations) return a single linked entry (see [Managing relations with API requests](/cms/api/rest/relations) for more information). ::: #### 布尔值 {#boolean} ¥ Boolean 布尔字段显示一个切换按钮来管理布尔值(例如是或否、1 或 0、True 或 False)。 ¥The Boolean field displays a toggle button to manage boolean values (e.g. Yes or No, 1 or 0, True or False). #### JSON {#json} JSON 字段允许以 JSON 格式配置数据,以存储 JSON 对象或数组。 ¥The JSON field allows to configure data in a JSON format, to store JSON objects or arrays. #### 电子邮件 {#email} ¥ Email 电子邮件字段显示带有格式验证的电子邮件地址字段,以确保电子邮件地址有效。 ¥The Email field displays an email address field with format validation to ensure the email address is valid. #### 密码 {#password} ¥ Password 密码字段显示已加密的密码字段。 ¥The Password field displays a password field that is encrypted. #### 枚举 {#enum} ¥ Enumeration 枚举字段允许配置下拉列表中显示的值列表。 ¥The Enumeration field allows to configure a list of values displayed in a drop-down list. :::caution 提醒 枚举值应始终在任何数字前有一个字母字符,否则在安装 GraphQL 插件时可能会导致服务器崩溃而不另行通知。 ¥Enumeration values should always have an alphabetical character preceding any number as it could otherwise cause the server to crash without notice when the GraphQL plugin is installed. ::: #### UID {#uid} UID 字段显示设置唯一标识符的字段,可以选择基于相同内容类型的现有其他字段。 ¥The UID field displays a field that sets a unique identifier, optionally based on an existing other field from the same content-type. :::tip 提示 UID 字段可用于根据 Attached 字段创建 slug。 ¥The UID field can be used to create a slug based on the Attached field. ::: #### 富文本(Markdown) {#rich-text-markdown} ¥ Rich Text (Markdown) 富文本 (Markdown) 字段显示一个带有基本格式选项的编辑器,用于管理以 Markdown 编写的富文本。该字段可用于长的书面内容。 ¥The Rich Text (Markdown) field displays an editor with basic formatting options to manage rich text written in Markdown. This field can be used for long written content. #### 组件 {#components} ¥ Components 组件是多个字段的组合。组件允许创建可重用的字段集,这些字段可以快速添加到内容类型、动态区域,也可以嵌套到其他组件中。 ¥Components are a combination of several fields. Components allow to create reusable sets of fields, that can be quickly added to content-types, dynamic zones but also nested into other components. 通过内容类型生成器配置组件时,可以: ¥When configuring a component through the Content-type Builder, it is possible to either: * 通过单击创建新组件来创建新组件(参见 [创建一个新组件](#new-component)), ¥create a new component by clicking on *Create a new component* (see [Creating a new component](#new-component)), * 或者通过单击“使用现有组件”来使用现有组件。 ¥or use an existing one by clicking on *Use an existing component*. #### 动态区域 {#dynamiczones} ¥ Dynamic zones 动态区域是可以添加到内容类型的组件的组合。它们允许灵活的内容结构,就像在内容管理器中一样,管理员可以选择按照自己的意愿组合和重新排列动态区域的组件。 ¥Dynamic zones are a combination of components that can be added to content-types. They allow a flexible content structure as once in the Content Manager, administrators have the choice of composing and rearranging the components of the dynamic zone how they want. 配置动态区域的设置后,还必须配置其组件。可以选择现有组件或创建新组件。 ¥After configuring the settings of the dynamic zone, its components must be configured as well. It is possible to either choose an existing component or create a new one. :::caution 提醒 使用动态区域时,不同组件不能具有不同类型(或枚举字段、不同值)的相同字段名称。 ¥When using dynamic zones, different components cannot have the same field name with different types (or with enumeration fields, different values). ::: #### 自定义字段 {#custom-fields} ¥Custom fields [自定义字段](/cms/features/custom-fields) 是一种通过向内容类型或组件添加新类型的字段来扩展 Strapi 功能的方法。安装后(请参阅 [市场](/cms/plugins/installing-plugins-via-marketplace) 文档),在为内容类型选择字段时,自定义字段将列在“自定义”选项卡中。 ¥[Custom fields](/cms/features/custom-fields) are a way to extend Strapi’s capabilities by adding new types of fields to content-types or components. Once installed (see [Marketplace](/cms/plugins/installing-plugins-via-marketplace) documentation), custom fields are listed in the *Custom* tab when selecting a field for a content-type. 每个自定义字段类型都可以有基本和高级设置。 列出了可用的自定义字段,并为每个自定义字段提供专用文档,包括特定设置。 ¥Each custom field type can have basic and advanced settings. The lists available custom fields, and hosts dedicated documentation for each custom field, including specific settings. ### 删除内容类型 {#deleting-content-types} ¥Deleting content-types 内容类型和组件可以通过内容类型生成器删除。删除内容类型会自动从内容管理器中删除基于该内容类型的所有条目。删除组件也是如此,该组件会从使用它的每个内容类型或条目中自动删除。 ¥Content types and components can be deleted through the Content-type Builder. Deleting a content-type automatically deletes all entries from the Content Manager that were based on that content-type. The same goes for the deletion of a component, which is automatically deleted from every content-type or entry where it was used. 1. 在 内容类型构建器子导航中,单击要删除的内容类型或组件的名称。 ¥In the Content-type Builder sub navigation, click on the name of the content-type or component to delete. 2. 在所选内容类型或组件的版本界面中,单击内容类型或组件名称右侧的 编辑按钮。 ¥In the edition interface of the chosen content-type or component, click on the **Edit** button on the right side of the content-type's or component's name. 3. 在版本窗口中,单击删除按钮。 ¥In the edition window, click on the **Delete** button. 4. 在确认窗口中,确认删除。 ¥In the confirmation window, confirm the deletion. 5. 点击内容类型构建器子导航栏中的“保存”按钮。 ¥Click on the **Save** button in the Content-type Builder sub navigation. :::caution 提醒 删除内容类型只会删除内容类型生成器中创建和可用的内容,并在一定程度上从 Strapi 应用的管理面板中删除。然而,基于该内容类型创建的所有数据都保留在数据库中。有关更多信息,请参阅相关的。 ¥Deleting a content-type only deletes what was created and available from the Content-type Builder, and by extent from the admin panel of your Strapi application. All the data that was created based on that content-type is however kept in the database. For more information, please refer to the related . ::: # 自定义字段 Source: https://docs.strapi.io/cms/features/custom-fields # 自定义字段 {#custom-fields} ¥Custom Fields 自定义字段通过向内容类型和组件添加新类型的字段来扩展 Strapi 的功能。通过插件创建或添加到 Strapi 后,自定义字段可以像内置字段一样在内容类型生成器和内容管理器中使用。 ¥Custom fields extend Strapi’s capabilities by adding new types of fields to content-types and components. Once created or added to Strapi via plugins, custom fields can be used in the Content-Type Builder and Content Manager just like built-in fields. ## 配置 {#configuration} ¥Configuration 可以在 [市场](https://market.strapi.io/plugins?categories=Custom+fields) 上找到现成的自定义字段。安装这些插件后,无需其他配置,即可开始使用(参见 [usage](#usage))。 ¥Ready-made custom fields can be found on the [Marketplace](https://market.strapi.io/plugins?categories=Custom+fields). Once installed these, no other configuration is required, and you can start using them (see [usage](#usage)). 你也可以开发自己的自定义字段。 ¥You can also develop your own custom field. ### 开发你自己的自定义字段 {#developing-your-own-custom-field} ¥Developing your own custom field 虽然添加自定义字段的推荐方法是通过创建插件,但特定于应用的自定义字段也可以在 `src/index` 和 `src/admin/app` 文件中找到的全局 `register` [function](/cms/configurations/functions) 中注册。 ¥Though the recommended way to add a custom field is through creating a plugin, app-specific custom fields can also be registered within the global `register` [function](/cms/configurations/functions) found in `src/index` and `src/admin/app` files. :::note 当前限制 * 自定义字段只能使用插件在 Marketplace 上共享和分发。 ¥Custom fields can only be shared and distributed on the Marketplace using plugins. * 自定义字段无法向 Strapi 添加新数据类型,必须使用 [模型的属性](/cms/backend-customization/models#model-attributes) 文档中描述的现有内置 Strapi 数据类型。 ¥Custom fields cannot add new data types to Strapi and must use existing, built-in Strapi data types described in the [models' attributes](/cms/backend-customization/models#model-attributes) documentation. * 你也无法修改现有的数据类型。 ¥You also cannot modify an existing data type. * Strapi 特有的特殊数据类型(例如关系、媒体、组件或动态区域数据类型)不能在自定义字段中使用。 ¥Special data types unique to Strapi, such as relation, media, component, or dynamic zone data types, cannot be used in custom fields. ::: :::prerequisites 如果你没有 CLI 生成器构建的插件代码,也可以直接在 `strapi-server.js` 文件中声明自定义字段: ¥The custom field could also be declared directly within the `strapi-server.js` file if you didn't have the plugin code scaffolded by the CLI generator: #### 在管理面板中注册自定义字段 {#registering-a-custom-field-in-the-admin-panel} ¥Registering a custom field in the admin panel :::prerequisites ##### 组件 {#components} ¥Components `app.customFields.register()` 必须传递带有 `Input` React 组件的 `components` 对象,以便在内容管理器的编辑视图中使用。 ¥`app.customFields.register()` must pass a `components` object with an `Input` React component to use in the Content Manager's edit view. **示例:注册输入组件:** ¥**Example: Registering an Input component:** 在以下示例中,`color-picker` 插件是使用 CLI 生成器创建的(请参阅 [插件开发](/cms/plugins-development/developing-plugins.md)): ¥In the following example, the `color-picker` plugin was created using the CLI generator (see [plugins development](/cms/plugins-development/developing-plugins.md)):
Props passed to the custom field Input component: | 属性 | 描述 | 类型 | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | | `attribute` | 具有自定义字段的基础 Strapi 类型和选项的属性对象 | `{ type: String, customField: String }` | | `description` | [配置视图](/cms/features/content-manager#edit-view-settings) 中设置的字段描述 | | | `placeholder` | [配置视图](/cms/features/content-manager#edit-view-settings) 中设置的字段占位符 | | | `hint` | [配置视图](/cms/features/content-manager#edit-view-settings) 中设置的字段描述以及最小/最大 [验证要求](/cms/backend-customization/models#validations) | `String` | | `name` | 内容类型构建器中设置的字段名称 | `String` | | `intlLabel` | 在内容类型构建器或配置视图中设置的字段名称 | | | `onChange` | 输入更改事件的处理程序。`name` 参数引用字段名称。`type` 参数引用底层 Strapi 类型 | `({ target: { name: String value: unknown type: String } }) => void` | | `contentTypeUID` | 该字段所属的内容类型 | `String` | | `type` | 自定义字段 uid,例如 `plugin::color-picker.color` | `String` | | `value` | 底层 Strapi 类型期望的输入值 | `unknown` | | `required` | 该字段是否为必填字段 | `boolean` | | `error` | 验证后收到错误 | | | `disabled` | 是否禁用输入 | `boolean` | 从 Strapi v4.13.0 开始,内容管理器中的字段可以通过 `URLSearchParam` `field` 自动聚焦。建议将输入组件封装在 React 的 :::tip 提示 有关提供给 customFields 的 props 的更详细视图及其使用方式,请查看 Strapi 代码库中的 :::tip 提示 Strapi 代码库给出了如何描述设置对象的示例:检查 文件以了解 `base` 设置,检查 文件以了解 `advanced` 设置。基本表单以内联方式列出设置项,但高级表单从 文件中获取设置项。 ¥The Strapi codebase gives an example of how settings objects can be described: check the file for the `base` settings and the file for the `advanced` settings. The base form lists the settings items inline but the advanced form gets the items from an file. ::: ## 用法 {#usage} ¥Usage
### 在管理面板中 {#in-the-admin-panel} ¥In the admin panel 你可以通过从 [市场](/cms/plugins/installing-plugins-via-marketplace) 安装自定义字段或创建自己的字段来将自定义字段添加到 Strapi。 ¥Custom fields can be added to Strapi either by installing them from the [Marketplace](/cms/plugins/installing-plugins-via-marketplace) or by creating your own. 自定义字段添加到 Strapi 后,即可添加到任何内容类型。在为内容类型选择字段时,自定义字段会在“自定义”选项卡中列出。 ¥Once added to Strapi, custom fields can be added to any content type. Custom fields are listed in the *Custom* tab when selecting a field for a content-type. 每个自定义字段类型都可以有基本和高级设置。 列出了可用的自定义字段,并为每个自定义字段提供专用文档,包括特定设置。 ¥Each custom field type can have basic and advanced settings. The lists available custom fields, and hosts dedicated documentation for each custom field, including specific settings. ### 在代码中 {#in-the-code} ¥In the code 创建和使用后,自定义字段的定义就像模型架构中的任何其他属性一样。 ¥Once created and used, custom fields are defined like any other attribute in the model's schema. 自定义字段在带有 `type: customField` 的模型的 [attributes](/cms/backend-customization/models#model-attributes) 中显式定义。 ¥Custom fields are explicitly defined in the [attributes](/cms/backend-customization/models#model-attributes) of a model with `type: customField`. 与其他类型的模型定义方式相比,自定义字段的属性还具有以下特性: ¥As compared to how other types of models are defined, custom fields' attributes also show the following specificities: * 自定义字段具有 `customField` 属性。它的值作为唯一标识符,用于指示应使用哪个已注册的自定义字段,并遵循以下两种格式之一: ¥Custom field have a `customField` attribute. Its value acts as a unique identifier to indicate which registered custom field should be used, and follows one of these 2 formats: | 格式 | 起源 | | -------------------------------- | ----------------------------------------------------------------------------------- | | `plugin::plugin-name.field-name` | 自定义字段是通过插件创建的。 | | `global::field-name` | 自定义字段特定于当前 Strapi 应用,并直接在 `register` [function](/cms/configurations/functions) 中创建。 | * 自定义字段可以包含其他参数,具体取决于注册自定义字段时定义的内容(参见 [服务器注册](#registering-a-custom-field-on-the-server) 和 [管理面板注册](#registering-a-custom-field-in-the-admin-panel))。 ¥Custom fields can have additional parameters depending on what has been defined when registering the custom field (see [server registration](#registering-a-custom-field-on-the-server) and [admin panel registration](#registering-a-custom-field-in-the-admin-panel)). **示例:一个简单的 `color` 自定义字段模型定义:** ¥**Example: A simple `color` custom field model definition:** ```json title="/src/api/[apiName]/[content-type-name]/content-types/schema.json" { // … "attributes": { "color": { // name of the custom field defined in the Content-Type Builder "type": "customField", "customField": "plugin::color-picker.color", "options": { "format": "hex" } } } // … } ``` # 数据管理 Source: https://docs.strapi.io/cms/features/data-management # 数据管理 {#data-management} ¥Data Management 数据管理功能可用于导入、导出或传输数据。数据管理仅基于 CLI,但部分配置在管理面板中。 ¥The Data Management feature can be used to import, export, or transfer data. Data Management is CLI-based only, but is partly configured in the admin panel. ## 配置 {#configuration} ¥Configuration 数据管理功能的一些配置选项在管理面板中可用,一些通过你的 Strapi 项目的代码处理。 ¥Some configuration options for the Data Management feature are available in the admin panel, and some are handled via your Strapi project's code. ### 管理面板设置 {#admin-panel-settings} ¥Admin panel settings :::prerequisites `transfer.token.salt` 应在 `config/admin` 配置文件中定义(参见 [基于代码的配置](#code-based-configuration))。 ¥A `transfer.token.salt` should be defined in the `config/admin` configuration file (see [code-based configuration](#code-based-configuration)). ::: 配置功能的路径: ## 用法 {#usage} ¥Usage 数据管理系统仅基于 CLI,这意味着任何导入、导出或传输命令都必须从终端执行。每个命令的详尽文档可从以下页面访问: ¥The Data Management system is CLI-based only, meaning any import, export, or transfer command must be executed from the terminal. Exhaustive documentation for each command is accessible from the following pages: # 起草并发布 Source: https://docs.strapi.io/cms/features/draft-and-publish # 起草并发布 {#draft--publish} ¥Draft & Publish 草稿和发布功能允许管理内容的草稿。 ¥The Draft & Publish feature allows to manage drafts for your content. 在 Strapi 的后端服务器上,文档服务 API 还可用于与本地化内容进行交互: ¥On the back-end server of Strapi, the Document Service API can also be used to interact with localized content: # 电子邮件 Source: https://docs.strapi.io/cms/features/email # 电子邮件 {#email} ¥Email 电子邮件功能使 Strapi 应用能够从服务器或外部提供商发送电子邮件。 ¥The Email feature enables Strapi applications to send emails from a server or an external provider. ## 配置 {#configuration} ¥Configuration 电子邮件功能的大多数配置选项都通过你的 Strapi 项目的代码处理。电子邮件功能无法在管理面板中配置,但是如果管理员已设置电子邮件,用户可以测试电子邮件传递。 ¥Most configuration options for the Email feature are handled via your Strapi project's code. The Email feature is not configurable in the admin panel, however users can test email delivery if it has been setup by an administrator. :::info 提供程序与主机 * 电子邮件提供商指的是 Strapi 调用来发送电子邮件的软件包(例如,官方提供商 Sendgrid 或社区软件包 `@strapi/provider-email-nodemailer`)。当 Strapi 调用提供程序时,提供程序会实现发送邮件的逻辑。 ¥The email provider refers to the package that Strapi calls to send an email (e.g. official providers such as Sendgrid or community packages such as `@strapi/provider-email-nodemailer`). Providers implement the logic for sending mail when Strapi invokes them. * 提供程序主机(或服务器)指的是提供程序公开的连接详细信息(例如 SMTP 主机名、端口或 REST API 端点)。有些服务商将这些细节隐藏在 API 密钥之后,而另一些则要求你在配置中提供与主机相关的选项。 ¥The provider host (or server) refers to the connection details (e.g. an SMTP hostname, port, or REST API endpoint) that the provider exposes. Some providers hide these details behind an API key, while others require you to supply host-related options in your configuration. 电子邮件功能仅处理出站邮件。接收或解析传入邮件超出了内置插件的功能范围,必须通过你的邮件服务提供商的入站 Webhook 或自定义集成来实现。 ¥The Email feature only handles outbound delivery. Receiving or parsing incoming messages is outside the scope of the built-in plugin and must be implemented with your email provider's inbound webhooks or a custom integration. ::: ### 管理面板设置 {#admin-panel-settings} ¥Admin panel settings 配置功能的路径: :::tip 可交付性 为了获得最佳送达率,请向你的电子邮件提供商配置 SPF/DKIM,并确保 `defaultFrom` 域名与你向提供商验证的域名一致。 ¥For best deliverability, configure SPF/DKIM with your email provider and ensure the `defaultFrom` domain aligns with the domain you verified with the provider. ::: ##### 配置提供者 {#configuring-providers} ¥Configuring providers 新安装的提供程序在 [`/config/plugins` 文件](/cms/configurations/plugins) 中启用并配置。如果该文件不存在,则必须创建它。 ¥Newly installed providers are enabled and configured in [the `/config/plugins` file](/cms/configurations/plugins). If this file does not exist you must create it. 每个提供者都有不同的可用配置设置。查看 [市场](/cms/plugins/installing-plugins-via-marketplace) 或 :::note 注意 * 当每个环境使用不同的提供程序时,请在 `/config/env/${yourEnvironment}/plugins.js|ts` 中指定正确的配置(请参阅 [环境](/cms/configurations/environment))。 ¥When using a different provider per environment, specify the correct configuration in `/config/env/${yourEnvironment}/plugins.js|ts` (See [Environments](/cms/configurations/environment)). * 一次只有一个电子邮件提供者处于活动状态。如果 Strapi 未选择电子邮件提供者设置,请验证 `plugins.js|ts` 文件是否位于正确的文件夹中。 ¥Only one email provider will be active at a time. If the email provider setting isn't picked up by Strapi, verify the `plugins.js|ts` file is in the correct folder. * 使用在 Strapi 设置期间创建的两个电子邮件模板测试新电子邮件提供者时,模板上的发送者电子邮件默认为 `no-reply@strapi.io`,需要根据你的电子邮件提供者进行更新,否则将无法通过测试(请参阅 [本地配置模板](/cms/features/users-permissions#templating-emails))。 ¥When testing the new email provider with those two email templates created during strapi setup, the *shipper email* on the template defaults to `no-reply@strapi.io` and needs to be updated according to your email provider, otherwise it will fail the test (See [Configure templates locally](/cms/features/users-permissions#templating-emails)). ::: ###### 每个环境的配置 {#configuration-per-environment} ¥Configuration per environment 配置提供程序时,你可能希望根据 `NODE_ENV` 环境变量更改配置或使用特定于环境的凭据。 ¥When configuring your provider you might want to change the configuration based on the `NODE_ENV` environment variable or use environment specific credentials. 你可以在 `/config/env/{env}/plugins.js|ts` 配置文件中设置特定配置,它将用于覆盖默认配置。 ¥You can set a specific configuration in the `/config/env/{env}/plugins.js|ts` configuration file and it will be used to overwrite the default configuration. 某些提供商会公开 SMTP 风格的连接详细信息,而不是(或除了)API 密钥。在 `providerOptions` 中添加这些值,以便 Strapi 可以访问提供程序主机。例如,社区 Nodemailer 提供程序需要主机、端口和身份验证凭据: ¥Some providers expose SMTP-style connection details instead of (or in addition to) an API key. Add those values in `providerOptions` so Strapi can reach the provider host. For instance, the community Nodemailer provider expects the host, port, and authentication credentials: 如果你的提供商提供的是单个 URL 而不是主机和端口值,请使用包所需的键将该 URL(例如 `https://api.eu.mailgun.net`)传递到 `providerOptions` 中。 ¥If your provider gives you a single URL instead of host and port values, pass that URL (for example `https://api.eu.mailgun.net`) in `providerOptions` using the key the package expects. ##### 创建提供者 {#creating-providers} ¥Creating providers 要实现你自己的自定义提供程序,你必须 在发送功能中,你将可以访问: ¥In the send function you will have access to: * `providerOptions` 包含用 `plugins.js|ts` 编写的配置 ¥`providerOptions` that contains configurations written in `plugins.js|ts` * `settings` 包含用 `plugins.js|ts` 编写的配置 ¥`settings` that contains configurations written in `plugins.js|ts` * `options` 包含你从电子邮件插件服务调用发送函数时发送的选项 ¥`options` that contains options you send when you call the send function from the email plugin service 你可以查看 # 国际化 Source: https://docs.strapi.io/cms/features/internationalization # 国际化(i18n) {#internationalization-i18n} ¥Internationalization (i18n) 国际化功能允许管理不同语言的内容,称为 "locales"。 ¥The Internationalization feature allows to manage content in different languages, called "locales". 在 Strapi 的后端服务器上,文档服务 API 还可用于与本地化内容进行交互: ¥On the back-end server of Strapi, the Document Service API can also be used to interact with localized content: # 媒体库 Source: https://docs.strapi.io/cms/features/media-library # 媒体库 {#media-library} ¥Media Library :::info 信息 当前页面上的基于代码的配置说明详细介绍了默认上传提供商的选项。如果使用其他提供商,请参阅该提供商文档中可用的配置参数。 ¥Code-based configuration instructions on the present page detail options for the default upload provider. If using another provider, please refer to the available configuration parameters in that provider's documentation. ::: #### 可用选项 {#available-options} ¥Available options 使用默认上传提供程序时,可以在 [`config/plugins` 文件](/cms/configurations/plugins) 中的 `upload.config` 对象中声明以下特定配置选项。所有参数都是可选的: ¥When using the default upload provider, the following specific configuration options can be declared in an `upload.config` object within [the `config/plugins` file](/cms/configurations/plugins). All parameters are optional: | 范围 | 描述 | 类型 | 默认 | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -- | ----------------------------------------------------------- | | `providerOptions.localServer` | 将传递给 #### 本地服务器 {#local-server} ¥Local server 默认情况下,Strapi 接受本地上传文件的 `localServer` 配置。这些将作为 #### 最大文件大小 {#max-file-size} ¥Max file size 负责解析请求的 Strapi 中间件需要配置为支持大于默认值 200MB 的文件大小。除了传递给 `sizeLimit` 的上传包的提供程序选项之外,还必须执行此操作。 ¥The Strapi middleware in charge of parsing requests needs to be configured to support file sizes larger than the default of 200MB. This must be done in addition to provider options passed to the Upload package for `sizeLimit`. :::caution 提醒 你可能还需要调整任何上游代理、负载平衡器或防火墙,以允许更大的文件大小。例如, 除了中间件配置外,你还可以在 [/config/plugins 文件](/cms/configurations/plugins) 中传递 `sizeLimit`(以字节为单位的整数): ¥In addition to the middleware configuration, you can pass the `sizeLimit`, which is an integer in bytes, in the [/config/plugins file](/cms/configurations/plugins): #### 安全性 #### 上传请求超时 {#upload-request-timeout} ¥Upload request timeout 默认情况下,`strapi.server.httpServer.requestTimeout` 的值设置为 330 秒。这包括上传。 ¥By default, the value of `strapi.server.httpServer.requestTimeout` is set to 330 seconds. This includes uploads. 为了使互联网连接速度慢的用户能够上传大文件,可能需要增加此超时限制。建议的方法是设置 [`config/servers` 文件](/cms/configurations/server) 中的 `http.serverOptions.requestTimeout` 参数。 ¥To make it possible for users with slow internet connection to upload large files, it might be required to increase this timeout limit. The recommended way to do it is by setting the `http.serverOptions.requestTimeout` parameter in [the `config/servers` file](/cms/configurations/server). 另一种方法是在 Strapi 启动之前运行的 [`bootstrap` 函数](/cms/configurations/functions#bootstrap) 中设置 `requestTimeout` 值。这在需要以编程方式更改的情况下很有用 - 例如,暂时禁用并重新启用它: ¥An alternate method is to set the `requestTimeout` value in [the `bootstrap` function](/cms/configurations/functions#bootstrap) that runs before Strapi gets started. This is useful in cases where it needs to change programmatically—for example, to temporarily disable and re-enable it: #### 响应式图片 {#responsive-images} ¥Responsive Images 启用 [`Responsive friendly upload` 管理面板设置](#admin-panel-configuration) 后,插件将生成以下响应式图片大小: ¥When the [`Responsive friendly upload` admin panel setting](#admin-panel-configuration) is enabled, the plugin will generate the following responsive image sizes: | 名称 | 最大维度 | | :----- | :------ | | large | 1000 像素 | | medium | 750 像素 | | small | 500 像素 | 这些尺寸可以在 `/config/plugins` 中被覆盖: ¥These sizes can be overridden in `/config/plugins`: :::caution 提醒 断点更改仅适用于新图片,现有图片不会调整大小或生成新尺寸。 ¥Breakpoint changes will only apply to new images, existing images will not be resized or have new sizes generated. ::: ## 用法 {#usage} ¥Usage 使用功能的路径: ### 在代码中使用公共资源 {#public-assets} ¥Use public assets in your code 公共资源是指你希望外部访问的静态文件(例如,图片、视频、CSS 文件等)。 ¥Public assets are static files (e.g., images, video, CSS files, etc.) that you want to make accessible to the outside world. 由于 API 可能需要提供静态资源,因此每个新的 Strapi 项目默认都包含一个名为 `/public` 的文件夹。如果请求的路径与任何其他定义的路由不匹配并且与公共文件名匹配(例如,可以通过 `/company-logo.png` URL 访问 `./public/` 中名为 `company-logo.png` 的图片),则可以访问此目录中的任何文件。 ¥Because an API may need to serve static assets, every new Strapi project includes by default a folder named `/public`. Any file located in this directory is accessible if the request's path doesn't match any other defined route and if it matches a public file name (e.g. an image named `company-logo.png` in `./public/` is accessible through `/company-logo.png` URL). :::tip 提示 如果请求对应于文件夹名称,则提供 `index.html` 文件(`/pictures` url 将尝试提供 `public/pictures/index.html` 文件)。 ¥`index.html` files are served if the request corresponds to a folder name (`/pictures` url will try to serve `public/pictures/index.html` file). ::: :::caution 提醒 点文件没有暴露。这意味着不会提供以 `.` 开头的每个文件名,例如 `.htaccess` 或 `.gitignore`。 ¥The dotfiles are not exposed. It means that every file name that starts with `.`, such as `.htaccess` or `.gitignore`, are not served. ::: # 预览 Source: https://docs.strapi.io/cms/features/preview # 预览 {#preview} ¥Preview 使用预览功能,你可以直接从 Strapi 的管理面板预览前端应用。这有助于了解内容管理器编辑视图中的内容更新将如何影响最终结果。 ¥With the Preview feature, you can preview your front end application directly from Strapi's admin panel. This is helpful to see how updates to your content in the Edit View of the Content Manager will affect the final result.
Caching in Next.js: 在 Next.js 中,[缓存持久性](https://next.nodejs.cn/docs/app/building-your-application/caching) 可能需要额外的步骤。你可能需要通过从客户端向服务器发出 API 调用来使缓存无效,重新验证逻辑将在服务器处理。有关详细信息,请参阅 Next.js 文档,例如 [revalidatePath() 方法](https://next.nodejs.cn/docs/app/building-your-application/caching#revalidatepath)。
¥In Next.js, [cache persistence](https://next.nodejs.cn/docs/app/building-your-application/caching) may require additional steps. You might need to invalidate the cache by making an API call from the client side to the server, where the revalidation logic will be handled. Please refer to Next.js documentation for details, for instance with the [revalidatePath() method](https://next.nodejs.cn/docs/app/building-your-application/caching#revalidatepath).
#### 内容源映射 {#content-source-maps} ¥Content source maps 实时预览能够识别前端与 Strapi 字段对应的部分。这可以通过内容源映射来完成,内容源映射是将元数据编码为字符串内容(例如,文本字段)中的隐藏字符。它使用 库来编码和解码这些元数据。 ¥Live Preview is able to identify the parts of your frontend that correspond to fields in Strapi. This is done through content source maps, which are metadata encoded as hidden characters in your string-based content (e.g., text fields). It uses the library to encode and decode this metadata. 仅当 `strapi-encode-source-maps` 标头设置为 `true` 时,元数据才会添加到 Content API 响应中。你可以在数据获取实用程序中设置此标头。请确保仅在检测到网站在预览环境中渲染时才传递标头。 ¥Metadatas will only be added in your Content API responses when the `strapi-encode-source-maps` header is set to `true`. You can set this header in your data fetching utility. Make sure to only pass the header when you detect that your site is rendered in a preview context. 对于 Next.js 应用,你可以使用 `next/headers` 中的 `draftMode()` 方法检测是否启用了草稿模式,并在所有 API 调用中相应地设置标头: ¥For a Next.js application, you may use the `draftMode()` method from `next/headers` to detect if draft mode is enabled, and set the header accordingly in all your API calls: ```typescript {20-23} contentType: string, params: Record = {} ): Promise { // Check if Next.js draft mode is enabled const { isEnabled: isDraftMode } = await draftMode(); try { const queryParams = { ...params }; // Add status=draft parameter when draft mode is enabled if (isDraftMode) { queryParams.status = "draft"; } const url = `${baseURL}/${contentType}?${qs.stringify(queryParams)}`; const response = await fetch(url, { headers: { // Enable content source maps in preview mode "strapi-encode-source-maps": isDraftMode ? "true" : "false", }, }); if (!response.ok) { throw new Error( `Failed to fetch data from Strapi (url=${url}, status=${response.status})` ); } return await response.json(); } catch (error) { console.error("Error fetching content:", error); throw error; } } ``` ## 用法 {#usage} ¥Usage 使用功能的路径: 内容管理器,内容类型的编辑视图 ¥**Path to use the feature:** Content Manager, edit view of your content type :::strapi 预览 vs. 实时预览 根据你的 CMS 计划,你使用预览的体验将有所不同: ¥Based on your CMS plan, your experience with Preview will be different: * 使用免费计划,预览将仅全屏显示。 ¥With the Free plan, Preview will be full screen only. * 使用 和 套餐,你可以享受名为“实时预览”的增强体验。使用实时预览功能,你可以在内容管理器的编辑视图旁边查看预览,还可以通过双击任何内容直接在预览中编辑内容。 ¥With the and plans, you get access to an enhanced experience called Live Preview. With Live Preview, you can see the Preview alongside the Edit view of the Content Manager, and you can also edit the content directly within the preview itself by double-clicking on any content. ::: 正确设置预览功能后,[内容管理器的编辑视图](/cms/features/content-manager#overview) 右侧将显示一个打开预览按钮。单击它将显示你的内容预览,因为它将出现在你的前端应用中,但直接在 Strapi 的管理面板中。 ¥Once the Preview feature is properly set up, an **Open preview** button is visible on the right side of the [Content Manager's edit view](/cms/features/content-manager#overview). Clicking it will display the preview of your content as it will appear in your front-end application, but directly within Strapi's the admin panel. 打开预览后,你可以: ¥Once the Preview is open, you can: * 点击左上角的关闭按钮 返回内容管理器的编辑视图, ¥click the close button in the upper left corner to go back to the Edit View of the Content Manager, * 使用预览内容上方的下拉菜单在桌面版和移动版预览之间切换, ¥switch between the Desktop and Mobile preview using the dropdown above the previewed content, * 在预览草稿和已发布版本之间切换(如果内容类型启用了 [起草并发布](/cms/features/draft-and-publish)), ¥switch between previewing the draft and the published version (if [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type), * 然后单击右上角的链接图标 复制预览链接。根据你当前正在查看的预览选项卡,这将复制指向草稿预览或已发布版本的链接。 ¥and click the link icon in the upper right corner to copy the preview link. Depending on the preview tab you are currently viewing, this will either copy the link to the preview of the draft or the published version. :::note 注意 在内容管理器的编辑视图中,如果有未保存的更改,则打开预览按钮将被禁用。保存最新更改,然后你就可以再次预览内容了。 ¥In the Edit view of the Content Manager, the Open preview button will be disabled if you have unsaved changes. Save your latest changes and you should be able to preview content again. ::: ### 实时预览 {#live-preview} ¥Live Preview 实时预览是 Strapi 付费 CMS 方案提供的增强预览体验。 ¥Live Preview is the enhanced Preview experience available with Strapi’s paid CMS plans. 使用实时预览功能,除了免费套餐中包含的功能外,你还可以: ¥With Live Preview, in addition to what’s included in the Free plan, you can: * 使用侧边编辑器并排查看内容管理器中条目的编辑视图和前端预览。你还可以使用 和 按钮在全屏和并排预览之间切换。 ¥Use the Side Editor to view both the entry’s Edit view in the Content Manager and the front-end preview side by side. You can also switch between full-screen and side-by-side preview using the and buttons. * 双击预览窗格中的任意内容即可进行编辑。这将打开一个弹出窗口,将前端内容与 Strapi 中的相应字段同步。 ¥Double-click any content in the preview pane to edit it in place. This opens a popover that syncs the front-end content with the corresponding field in Strapi. :::caution 实验特性 此功能目前处于实验阶段。欢迎与 Strapi 团队分享 或 。 ¥This feature is currently experimental. Feel free to share or with the Strapi team. 当前版本的实时预览存在以下限制: ¥The current version of Live Preview comes with the following limitations: * 块字段不会被检测到,在侧边编辑器中更改它们不会反映在预览中。更新后点击“保存”仍然有效。 ¥Blocks fields are not detected, and changing them in the Side Editor won’t be reflected in the preview. Clicking on Save after updates should however still work. * 动态区域中的媒体资源和字段不予处理。 ¥Media assets and fields in dynamic zones are not handled. ::: # 基于角色的访问控制 (RBAC) Source: https://docs.strapi.io/cms/features/rbac # 基于角色的访问控制 (RBAC) {#role-based-access-control-rbac} ¥Role-Based Access Control (RBAC) 基于角色的访问控制 (RBAC) 功能允许管理管理员,他们是管理面板的用户。更具体地说,RBAC 管理管理员的账户和角色。 ¥The Role-Based Access Control (RBAC) feature allows the management of the administrators, who are the users of the admin panel. More specifically, RBAC manages the administrators' accounts and roles. 4. 单击右上角的“保存”按钮。 ¥Click on the **Save** button on the top right corner. :::tip 提示 要为你的自定义插件创建管理员权限,请参考我们的 [专用指南](/cms/plugins-development/guides/admin-permissions-for-plugins)。 ¥To create admin permissions for your custom plugin, please refer to our [dedicated guide](/cms/plugins-development/guides/admin-permissions-for-plugins). ::: #### 设置权限的自定义条件 {#setting-custom-conditions-for-permissions} ¥Setting custom conditions for permissions 对于每个类别的每个权限,都会显示一个 ## 用法 {#usage} ¥Usage 使用功能的路径: 设置 > 管理面板 > 用户 ¥**Path to use the feature:** *Settings > Administration panel > Users* 用户界面显示一个表格,列出了 Strapi 应用的所有管理员。更具体地说,对于表中列出的每个管理员,都会显示他们的主要账户信息,包括名称、电子邮件和归属角色。还显示了他们账户的状态:活动或非活动,取决于管理员是否已登录激活账户。 ¥The *Users* interface displays a table listing all the administrators of your Strapi application. More specifically, for each administrator listed in the table, their main account information are displayed, including name, email and attributed role. The status of their account is also indicated: active or inactive, depending on whether the administrator has already logged in to activate the account or not. 通过该界面,可以: ¥From this interface, it is possible to: * 进行文本搜索 以查找特定管理员, ¥make a textual search to find specific administrators, * 设置过滤器 以查找特定管理员, ¥set filters to find specific administrators, * 创建一个新的管理员账户(参见 [创建新账户](#creating-a-new-account)), ¥create a new administrator account (see [Creating a new account](#creating-a-new-account)) , * 删除管理员账户 (参见 [删除账户](#deleting-an-account)), ¥delete an administrator account (see [Deleting an account](#deleting-an-account)), * 或访问有关管理员账户的信息,并对其进行编辑 (参见 [编辑账户](#editing-an-account))。 ¥or access information regarding an administrator account, and edit it (see [Editing an account](#editing-an-account)). :::tip 提示 可以为表中显示的大多数字段启用排序。单击表标题中的字段名称可对该字段进行排序。 ¥Sorting can be enabled for most fields displayed in the table. Click on a field name, in the header of the table, to sort on that field. ::: ### 创建新账户 {#creating-a-new-account} ¥Creating a new account 1. 单击 邀请新用户按钮。 ¥Click on the **Invite new user** button. 2. 在邀请新用户窗口中,填写有关新管理员的详细信息: ¥In the *Invite new user* window, fill in the Details information about the new administrator: | 用户信息 | 指示 | | ---- | ------------------------- | | 名 | (强制的)在文本框中写下管理员的名字。 | | 姓 | (强制的)在文本框中写入管理员的姓氏。 | | 电子邮件 | (强制的)在文本框中写入管理员的完整电子邮件地址。 | 3. 填写新管理员的登录设置: ¥Fill in the Login settings about the new administrator: | 环境 | 指示 | | --------- | ------------------------------------ | | 用户的角色 | (强制的)从下拉列表中选择要归属于新管理员的角色。 | | 使用 SSO 连接 | (可选)单击 TRUE 或 FALSE 将新管理员账户与 SSO 连接。 | 4. 单击添加新用户窗口右下角的邀请用户按钮。 ¥Click on the **Invite user** button in the bottom right corner of the *Add new user* window. 5. URL 将出现在窗口顶部:这是向新管理员发送的 URL,以便他们首次登录你的 Strapi 应用。单击复制按钮 复制 URL。 ¥A URL appears at the top of the window: it is the URL to send the new administrator for them to log in for the first time to your Strapi application. Click the copy button to copy the URL. 6. 单击右下角的“完成”按钮以完成新管理员账户的创建。新管理员现在应列在表中。 ¥Click on the **Finish** button in the bottom right corner to finish the new administrator account creation. The new administrator should now be listed in the table. :::note 注意 管理员邀请 URL 可从管理员账户访问,直至激活。 ¥The administrator invitation URL is accessible from the administrator's account until it has been activated. ::: ### 删除账户 {#deleting-an-account} ¥Deleting an account 可以同时删除一个或多个管理员账户。 ¥It is possible to delete one or several administrator accounts at the same time. 1. 点击账户记录右侧的删除按钮 ,或通过勾选账户记录左侧的框来选择一个或多个账户,然后单击表格上方的 删除按钮。 ¥Click on the delete button on the right side of the account's record, or select one or more accounts by ticking the boxes on the left side of the accounts' records then click on the **Delete** button above the table. 2. 在删除窗口中,点击确认按钮确认删除。 ¥In the deletion window, click on the **Confirm** button to confirm the deletion. ### 编辑账户 {#editing-an-account} ¥Editing an account 1. 单击要编辑其账户的管理员的名称。 ¥Click on the name of the administrator whose account you want to edit. 2. 在详细信息区域中,编辑你选择的账户详细信息: ¥In the *Details* area, edit your chosen account details: | 用户信息 | 指示 | | ---- | -------------------- | | 名 | 在文本框中写下管理员的名字。 | | 姓 | 在文本框中写入管理员的姓氏。 | | 电子邮件 | 在文本框中写入管理员的完整电子邮件地址。 | | 用户名 | 在文本框中写入管理员的用户名。 | | 密码 | 在文本框中写入新管理员账户的密码。 | | 确认密码 | 在文本框中写入新密码以进行确认。 | | 积极的 | 单击 TRUE 激活管理员账户。 | 3. (可选)在“角色”区域中,编辑管理员的角色: ¥(optional) In the *Roles* area, edit the role of the administrator: * 单击下拉列表选择一个新角色,和/或将其添加到已归属的角色中。 ¥Click on the drop-down list to choose a new role, and/or add it to the already attributed one. * 单击删除按钮 删除已分配的角色。 ¥Click on the delete button to delete an already attributed role. 4. 单击右上角的“保存”按钮。 ¥Click on the **Save** button in the top right corner. # 发布 Source: https://docs.strapi.io/cms/features/releases # 发布 {#releases} ¥Releases 发布功能使内容管理员能够将条目组织到可以同时执行发布和取消发布操作的容器中。版本可以包含来自不同内容类型的条目,并且可以混合区域设置。 ¥The Releases feature enables content managers to organize entries into containers that can perform publish and unpublish actions simultaneously. A release can contain entries from different content types and can mix locales. ## 配置 {#configuration} ¥Configuration 为了能够将你的内容包含在发布中,并安排和发布这些发布,你必须首先创建它们。你还可以修改发布计划时使用的发布默认时区,以及删除过时或不相关的发布。 ¥To be able to include your content in releases, and to schedule and publish those releases, you must first create them. You can also modify the releases' default timezone to use when scheduling a publication, as well as deleting releases that are obsolete or irrelevant. ### 选择默认时区 {#choosing-default-timezone} ¥Choosing default timezone 配置功能的路径: 设置 ¥**Path to configure the feature:** Settings 1. 单击默认时区下拉列表并选择要使用的默认时区。 ¥Click on the *Default timezone* dropdown list and choose the default timezone to use. 2. 单击“保存”。 ¥Click **Save**. ### 创建发布 {#creating-a-release} ¥Creating a release 配置功能的路径: 发布 ¥**Path to configure the feature:** Releases 1. 单击右上角的 新版本按钮。 ¥Click the **New Release** button in the upper right corner. 2. 为发布命名。 ¥Give the release a name. 3. (可选)如果你想安排发布而不是手动发布,请选中“安排发布”复选框并定义发布的日期、时间和时区。 ¥(*optional*) If you want to schedule the release publication instead of publishing the release manually, check the **Schedule release** checkbox and define the date, time, and timezone for publication. 4. 单击“继续”按钮。 ¥Click the **Continue** button. :::tip 提示 之后,你可以重命名你的发布版本,方法是使用 然后 编辑按钮编辑发布版本。 ¥Your releases can be renamed afterwards, by editing the release using the then **Edit** buttons. ::: ### 删除发布 {#deleting-a-release} ¥Deleting a release 路径: 发布 ¥**Path:** Releases 删除版本只会删除版本本身,而不会删除版本中包含的内容类型条目。 ¥Deleting a release will only delete the release itself, but not the content-type entries included in the release. 1. 单击管理面板右上角的 按钮。 ¥Click on the button in the top right corner of the admin panel. 2. 选择 删除。 ¥Select **Delete**. 3. 在确认对话框中,单击 确认。 ¥In the confirmation dialog, click **Confirm**. ## 用法 {#usage} ¥Usage 使用功能的路径: 发布和 内容管理器 ¥**Path to use the feature:** Releases and Content Manager :::caution 提醒 由于通过版本发布条目意味着将草稿条目转变为已发布条目,因此如果内容类型禁用 [起草并发布](/cms/features/draft-and-publish),则版本将不起作用。 ¥Since publishing an entry with a release means turning a draft entry into a published entry, Releases will not work if [Draft & Publish](/cms/features/draft-and-publish) is disabled for the content-type. ::: ### 在发布中包含内容 {#including-content-in-a-release} ¥Including content in a release :::prerequisites * 在将条目添加到发布之前,你必须从 发布页面创建发布。 ¥Before entries can be added to a release, you must create a release from the Releases page. * 将内容添加到版本需要 Content-Releases 插件的适当权限(请参阅 [配置管理员角色](/cms/features/users-permissions))。 ¥Adding content to a release requires the appropriate permissions for the Content-Releases plugin (see [configuring administrator roles](/cms/features/users-permissions)). ::: #### 一次一个条目 {#one-entry-at-a-time} ¥One entry at a time 路径:编辑 内容管理器的视图 ¥**Path:** Edit view of the Content Manager 1. 单击界面右侧输入区域中的 。 ¥Click on in the *Entry* area on the right side of the interface. 2. 在列表中,单击 添加到发布按钮。 ¥In the list, click on the **Add to release** button. 3. 选择要将此条目添加到哪个版本。 ¥Select which release to add this entry to. 4. 单击“发布”或“取消发布”按钮,具体取决于你希望在发布版本本身时发布还是取消发布条目,然后单击“继续”。 ¥Click on the **Publish** or **Unpublish** button depending on whether you want the entry to be published or unpublished when the release itself is published, then click **Continue**. 右侧的发布框应显示条目包含在哪个版本中。 ¥The *Releases* box on the right should show which release(s) the entry is included in. :::info 信息 如果启用 [发布安排](/cms/features/releases#scheduling-a-release) 并将条目添加到计划发布中,则还将显示发布日期和时间。 ¥If [Releases scheduling](/cms/features/releases#scheduling-a-release) is enabled and the entry is added to a scheduled release, the release date and time will also be displayed. ::: #### 一次输入多个条目 {#multiple-entries-at-a-time} ¥Multiple entries at a time 路径: 内容管理器的列表视图 ¥**Path:** List view of the Content Manager 1. 通过勾选条目记录左侧的框来选择要添加的条目。 ¥Select which entries you want to add by ticking the box on the left side of the entries' record. 2. 单击表标题上方的“添加到版本”按钮。 ¥Click on the **Add to release** button located above the header of the table. 3. 在模式中,选择要将这些条目添加到哪个版本。 ¥In the modal, select which release to add these entries to. 4. 单击“发布”或“取消发布”按钮来决定在发布版本时是否发布或取消发布这些条目,然后单击“继续”。 ¥Click on the **Publish** or **Unpublish** button to decide whether these entries will be published or unpublished when the release is published, then click **Continue**. ### 从发布中删除内容 {#removing-an-entry-from-a-release} ¥Removing content from a release 路径:编辑 内容管理器的视图 ¥**Path:** Edit view of the Content Manager 1. 在右侧边栏的“发布”框中,单击发布名称下方的。 ¥In the *Releases* box in the right sidebar, click on below the name of the release. 2. 点击从发布中删除按钮。 ¥Click the **Remove from release** button. ### 安排发布 {#scheduling-a-release} ¥Scheduling a release 路径: 发布 ¥**Path:** Releases 发布可以是 [手动发布](#publishing-a-release) 或计划在给定日期和时间(使用你选择的时区)自动发布。 ¥Releases can be [published manually](#publishing-a-release) or scheduled to be automatically published at a given date and time, with the timezone of your choice. 你可以安排发布: ¥You can schedule a release: * 当 [创建发布](#creating-a-release) 时, ¥when [creating the release](#creating-a-release), * 或者一旦创建了版本,就可以对其进行编辑。 ¥or once the release is already created, by editing it. 要在发布页面上安排现有发布: ¥To schedule an existing release, while on a release page: 1. 单击管理面板右上角的 按钮。 ¥Click on the button in the top right corner of the admin panel. 2. 选择 编辑。 ¥Select **Edit**. 3. 在模式中,选中计划发布复选框。 ¥In the modal, check the **Schedule release** checkbox. 4. 选择要发布的版本的日期、时间和时区。 ¥Select a date, time, and timezone for the release to be published. 5. 单击“保存”。 ¥Click **Save**. ### 发布版本 {#publishing-a-release} ¥Publishing a release 路径: 发布 ¥**Path:** Releases 发布版本意味着为版本中包含的每个条目定义的所有操作(发布或取消发布)将同时执行。 ¥Publishing a release means that all the actions (publish or unpublish) defined for each entry included in the release will be performed simultaneously. 要发布版本,请单击管理面板右上角的“发布”按钮。在此之前,请务必检查版本及其条目的状态。 ¥To publish a release, click the **Publish** button in the top right corner of the admin panel. Before, make sure to check the status of both the release and its entries. * 界面顶部的徽章指示你的发布状态: ¥A badge at the top of the interface indicates the status of your release: * `Empty`:尚未将任何条目添加到发布版本 ¥`Empty`: no entry has been added to the release yet * `Blocked`:内容已添加到发布版本,但条目中至少有一个问题阻止发布版本 ¥`Blocked`: content has been added to the release but at least one issue in an entry prevents the release from being published * `Ready`:内容已添加到发布版本,所有检查均已通过,可以发布发布版本 ¥`Ready`: content has been added to the release, all checks have been passed and the release can be published * `Done`:发布版本已发布,现已完成 ¥`Done`: the release has been released and is now done * 状态列显示每个条目的状态: ¥The *Status* column displays the status of each entry: * 已发布:该条目已发布,发布版本不会影响该条目 ¥ Already published: the entry is already published and publishing the release will not affect this entry * 已取消发布:条目已取消发布,发布版本不会影响此条目。 ¥ Already unpublished: the entry is already unpublished, and publishing the release will not affect this entry. * 准备发布:该条目已准备好随版本一起发布 ¥ Ready to publish: the entry is ready to be published with the release * 准备取消发布:条目已准备好随版本取消发布 ¥ Ready to unpublish: the entry is ready to be unpublished with the release * 尚未准备好发布:无法发布该条目,因为某些字段填写不正确,或者尚未达到发布所需的阶段。在这种情况下,发布将被指示为已阻止,直到所有问题都已修复。 ¥ Not ready to publish: the entry cannot be published because some fields are incorrectly filled, or it hasn't reached the required stage for publishing. In this case, the release will be indicated as *Blocked* until all issues have been fixed. 如果你的版本号为 `Blocked`,因为部分条目的状态为 ,请点击 按钮,然后编辑该条目以修复问题,直到所有条目的状态都变为 。 ¥If your release is `Blocked` because some of your entries have a status, click the button, then **Edit the entry** to fix the issues until all entries have the status. :::note 注意 修复各种条目问题后,你需要点击“刷新”按钮来更新发布页面。 ¥You will have to click on the **Refresh** button to update the release page as you fix the various entries issues. ::: :::caution 提醒 版本发布后,版本本身就无法更新。你不能使用经过某些修改的同一组条目重新发布该特定版本;你必须创建另一个版本。 ¥Once a release is published, the release itself cannot be updated. You can not re-release that specific release with the same group of entries with some modifications; you must create another release. ::: # 审查工作流程 Source: https://docs.strapi.io/cms/features/review-workflows # 审查工作流程 {#review-workflows} ¥Review Workflows 审核工作流程功能允许你为各种内容类型创建和管理工作流程。每个工作流程可以包含内容的任何审核阶段,使你的团队能够在从草稿到发布的内容创建流程中进行协作。 ¥The Review Workflows feature allows you to create and manage workflows for your various content-types. Each workflow can consist of any review stages for your content, enabling your team to collaborate in the content creation flow from draft to publication. ## 配置 {#configuration} ¥Configuration 配置功能的路径: 设置 > 全局设置 > 审核工作流程 ¥**Path to configure the feature:** Settings > Global settings > Review Workflows 为了使审核工作流在 [内容管理者](/cms/features/content-manager) 中可用,应配置默认工作流或创建新工作流。 ¥For the review workflows to be usable in the [Content Manager](/cms/features/content-manager), the default one should be configured or a new one should be created. 默认工作流程配置为有 4 个阶段:待办事项、进行中、准备审查和已审查。所有 4 个阶段都可以根据需要进行编辑、重新排序或删除,也可以添加新阶段。 ¥The default workflow is configured to have 4 stages: To do, In progress, Ready to review, and Reviewed. All 4 stages can be edited, reordered or deleted as needed, and it is also possible to add new stages. ### 创建新的工作流程 {#creating-a-new-workflow} ¥Creating a new workflow 1. 单击创建新工作流按钮或工作流的编辑按钮 。 ¥Click on the **Create new workflow** button or on the edit button of a workflow. 2. 在工作流编辑界面中,配置新的工作流: ¥In the workflow edit interface, configure the new workflow: | 设置名称 | 指示 | | ------ | ---------------------------------------- | | 工作流程名称 | 为工作流编写一个唯一的名称。 | | 关联到 | (可选)将此工作流分配给一个或多个现有内容类型。 | | 阶段 | 添加审核阶段(参见 [添加新阶段](#adding-a-new-stage))。 | 3. 单击“保存”按钮。新的工作流程将显示在列表视图中,并针对分配的每种内容类型显示。 ¥Click on the **Save** button. The new workflow will be displayed in the list view and for every content-type assigned. :::note 注意 的最大数量。 ¥The maximum number of . ::: ### 编辑工作流程 {#editing-a-workflow} ¥Editing a workflow #### 添加新阶段 {#adding-a-new-stage} ¥Adding a new stage 1. 单击添加新阶段按钮。 ¥Click on the **Add new stage** button. 2. 写下舞台名称。 ¥Write the *Stage name*. 3. 选择一种颜色。 ¥Select a *Color*. 4. 如果实体当前处于该审核阶段,请选择可以更改阶段的角色。 ¥Select *Roles* that can change the stage, if the entity is currently in that review stage. 5. 单击“保存”按钮。 ¥Click on the **Save** button. 默认情况下,会附加新阶段,但可以随时使用 按钮重新排序。 ¥By default new stages are appended, but they can be reordered anytime using the button. :::tip 提示 要为每个阶段设置角色,你可以单击 "适用于所有阶段" 将当前角色应用到工作流的所有其他阶段,或者使用阶段上下文菜单的 "冗余阶段"。 ¥To set up roles for each stage, you can either click "Apply to all stages" to apply the current roles to all other stages of the workflow or use "Duplicate stage" of the stage context menu. ::: #### 复制舞台 {#duplicating-a-stage} ¥Duplicating a stage 1. 单击舞台上下文菜单中的“复制舞台”。 ¥Click **Duplicate Stage** in the context menu of the stage. 2. 更改复制阶段的名称。 ¥Change the name of the duplicated stage. 3. 单击“保存”按钮。 ¥Click on the **Save** button. #### 删除阶段 {#deleting-a-stage} ¥Deleting a stage 要删除阶段,请单击阶段上下文菜单中的 ,然后单击删除。 ¥To delete a stage, click in the context menu of the stage, then **Delete**. 如果你删除有待审核的阶段,审核将移至工作流程的第一阶段。每个工作流程需要至少包含一个阶段,因此无法删除最后一个阶段。 ¥If you delete a stage that has pending reviews, the reviews will be moved to first stage in the workflow. Every workflow needs to contain at least one stage and therefore it is not possible to delete the last stage. ### 删除工作流程 {#deleting-a-workflow} ¥Deleting a workflow 要删除工作流,请在列表视图中单击工作流的删除按钮 。 ¥To delete a workflow click on the delete button of a workflow in the list view. :::note 注意 无法删除最后一个工作流程。 ¥It is not possible to delete the last workflow. ::: ## 用法 {#usage} ¥Usage 使用功能的路径: 内容管理器 ¥**Path to use the feature:** Content Manager ### 更改审核阶段 {#change-review-stage} ¥Changing review stage 随着你的团队创建和修改内容,你可以将内容的审核阶段更改为审核工作流中定义的任何阶段。 ¥As content is created and revised among your team, you can change the review stage of the content to any stage defined in the review workflow. 1. 访问你的内容类型的编辑视图。 ¥Access the edit view of your content-type. 2. 在界面右侧的“审核工作流”框中,单击“审核阶段”下拉列表。 ¥In the *Review Workflows* box on the right side of the interface, click on the *Review stage* drop-down list. 3. 选择你入口的新审核阶段。它会自动保存。 ¥Choose the new review stage of your entry. It is automatically saved. ### 定义受让人 {#change-assignee} ¥Defining assignee 审核工作流程内容类型的条目可以分配给 Strapi 中的任何管理员用户进行审核。 ¥Entries of a review workflow content type can be assigned to any admin user in Strapi for review. 1. 访问你的内容类型的编辑视图。 ¥Access the edit view of your content-type. 2. 在界面右侧的“审核工作流”框中,单击“受让人”下拉列表。 ¥In the *Review Workflows* box on the right side of the interface, click on the *Assignee* drop-down list. 3. 选择你条目的新受让人。它会自动保存。 ¥Choose the new assignee of your entry. It is automatically saved. # 单点登录 (SSO) Source: https://docs.strapi.io/cms/features/sso # 单点登录 (SSO) {#single-sign-on-sso} ¥Single Sign-On (SSO) 可以在 Strapi 应用上提供单点登录 (SSO) 功能,以允许管理员通过身份提供者(例如 Microsoft Azure Active Directory)进行身份验证。 ¥The Single Sign-On (SSO) feature can be made available on a Strapi application to allow administrators to authenticate through an identity provider (e.g. Microsoft Azure Active Directory). ## 用法 {#usage} ¥Usage 要使用特定提供商访问管理面板,而不是使用常规 Strapi 管理员账户登录: ¥To access the admin panel using a specific provider instead of logging in with a regular Strapi administrator account: 1. 转至 Strapi 应用管理面板的 URL。 ¥Go to the URL of your Strapi application's admin panel. 2. 单击所选提供商,其徽标应显示在登录表单的底部。如果你看不到你的提供商,请单击 按钮以访问所有可用提供商的完整列表。 ¥Click on a chosen provider, which logo should be displayed at the bottom of the login form. If you cannot see your provider, click the button to access the full list of all available providers. 3. 你将被重定向到提供者自己的登录页面,你可以在其中进行身份验证。 ¥You will be redirected to your provider's own login page where you will be able to authenticate. # 用户和权限 Source: https://docs.strapi.io/cms/features/users-permissions # 用户和权限 {#users--permissions} ¥Users & Permissions 用户和权限功能允许管理终端用户 ¥The Users & Permissions feature allows the management of the end-users Strapi 项目的。它提供基于 JSON Web Tokens (JWT) 的完整身份验证过程来保护你的 API,以及访问控制列表 (ACL) 策略,使你能够管理用户组之间的权限。 ¥of a Strapi project. It provides a full authentication process based on JSON Web Tokens (JWT) to protect your API, and an access-control list (ACL) strategy that enables you to manage permissions between groups of users. ## 管理面板配置 {#admin-panel-configuration} ¥Admin panel configuration 用户和权限功能可从管理面板设置和代码库进行配置。 ¥The Users & Permissions feature is configured from both the admin panel settings, and via the code base. ### 角色 {#roles} ¥Roles 用户和权限功能允许为终端用户创建和管理角色,以配置他们可以访问的内容。 ¥The Users & Permissions feature allows to create and manage roles for end users, to configure what they can have access to. #### 创建新角色 {#creating-a-new-role} ¥Creating a new role 路径: ### 电子邮件模板 {#email-templates} ¥Email templates 路径: ### 注册配置 {#registration-configuration} ¥Registration configuration 如果你在用户模型中添加了任何其他字段 ¥If you have added any additional fields in your User **model** 需要在注册时接受,你需要将它们添加到 [`/config/plugins` 文件](/cms/configurations/plugins) 的 `config.register` 对象中允许的字段列表中,否则将不被接受。 ¥that need to be accepted on registration, you need to added them to the list of allowed fields in the `config.register` object of [the `/config/plugins` file](/cms/configurations/plugins), otherwise they will not be accepted. 以下示例显示如何确保 API 在用户注册时接受名为 "nickname" 的字段: ¥The following example shows how to ensure a field called "nickname" is accepted by the API on user registration: ### 速率限制配置 {#rate-limiting-configuration} ¥Rate limiting configuration 对身份验证和注册端点应用速率限制以防止滥用。可以配置以下参数来更改其行为。` ### 模板化电子邮件 {#templating-emails} ¥Templating emails 默认情况下,该插件附带两个模板:重置密码和电子邮件地址确认。模板使用 ### 安全配置 {#security-configuration} ¥Security configuration JWT 可以被验证和信任,因为信息是经过数字签名的。要签署令牌,需要一个秘密。默认情况下,Strapi 生成并将其存储在 `/extensions/users-permissions/config/jwt.js` 中。 ¥JWTs can be verified and trusted because the information is digitally signed. To sign a token a *secret* is required. By default Strapi generates and stores it in `/extensions/users-permissions/config/jwt.js`. 这在开发期间很有用,但出于安全原因,建议在部署到生产时通过环境变量 `JWT_SECRET` 设置自定义令牌。 ¥This is useful during development but for security reasons it is recommended to set a custom token via an environment variable `JWT_SECRET` when deploying to production. 默认情况下,你可以设置 `JWT_SECRET` 环境变量,它将用作秘密。如果你想使用其他变量,你可以更新配置文件。 ¥By default you can set a `JWT_SECRET` environment variable and it will be used as secret. If you want to use another variable you can update the configuration file. #### 创建自定义回调验证器 {#creating-a-custom-password-validation} ¥Creating a custom callback validator 默认情况下,Strapi SSO 仅重定向到与配置中的 URL 完全相等的重定向 URL: ¥By default, Strapi SSO only redirects to the redirect URL that is exactly equal to the url in the configuration: 要退出所有会话,请发送以下请求: ¥To log out of all sessions, send the following request: #### 标识符 {#identifier} ¥Identifier 请求中发送的 `identifier` 参数可以是电子邮件或用户名,如下例所示: ¥The `identifier` parameter sent with requests can be an email or username, as in the following examples: #### 令牌使用 {#token-usage} ¥Token usage 然后,`jwt` 可用于发出权限受限的 API 请求。要以用户身份发出 API 请求,请将 JWT 放入 `GET` 请求的 `Authorization` 标头中。 ¥The `jwt` may then be used for making permission-restricted API requests. To make an API request as a user place the JWT into an `Authorization` header of the `GET` request. 默认情况下,任何没有令牌的请求都将采用 `public` 角色权限。在管理仪表板中修改每个用户角色的权限。 ¥Any request without a token will assume the `public` role permissions by default. Modify the permissions of each user's role in the admin dashboard. 身份验证失败会返回 `401 (unauthorized)` 错误。 ¥Authentication failures return a `401 (unauthorized)` error. `token` 变量是登录或注册时收到的 `data.jwt`。 ¥The `token` variable is the `data.jwt` received when logging in or registering. ```js const token = 'YOUR_TOKEN_HERE'; // Request API. axios .get('http://localhost:1337/posts', { headers: { Authorization: `Bearer ${token}`, }, }) .then(response => { // Handle success. console.log('Data: ', response.data); }) .catch(error => { // Handle error. console.log('An error occurred:', error.response); }); ``` #### 用户注册 {#user-registration} ¥User registration 可以像以下示例一样在数据库中创建一个默认角色为 'registered' 的新用户: ¥Creating a new user in the database with a default role as 'registered' can be done like in the following example: ```js // Request API. // Add your own code here to customize or restrict how the public can register new users. axios .post('http://localhost:1337/api/auth/local/register', { username: 'Strapi user', email: 'user@strapi.io', password: 'strapiPassword', }) .then(response => { // Handle success. console.log('Well done!'); console.log('User profile', response.data.user); console.log('User token', response.data.jwt); }) .catch(error => { // Handle error. console.log('An error occurred:', error.response); }); ``` #### Strapi 上下文中的用户对象 {#user-object-in-strapi-context} ¥User object in Strapi context `user` 对象可用于成功验证的请求。 ¥The `user` object is available to successfully authenticated requests. 经过身份验证的 `user` 对象是 `ctx.state` 的属性。 ¥The authenticated `user` object is a property of `ctx.state`. ```js create: async ctx => { const { id } = ctx.state.user; const depositObj = { ...ctx.request.body, depositor: id, }; const data = await strapi.services.deposit.add(depositObj); // Send 201 `created` ctx.created(data); }; ``` # 安装 Source: https://docs.strapi.io/cms/installation # 安装 {#installation} ¥Installation Strapi 项目可以安装在本地计算机上或远程服务器上。以下安装指南提供了有关如何在本地计算机上安装和创建新 Strapi 项目的分步说明: ¥Strapi projects can be installed either locally on a computer or on a remote server. The following installation guide provides step-by-step instructions on how to install and create a new Strapi project on your local machine: 如果你的本地机器上已经有现有的 Strapi 项目,以下指南提供了为你的项目创建自定义 Docker 映像的分步说明: ¥If you already have an existing Strapi project on your local machine, the following guide provides step-by-step instructions on creating a custom Docker image for your project: # 迁移到 Strapi 5 的附加资源 Source: https://docs.strapi.io/cms/migration/v4-to-v5/additional-resources/introduction # 升级到 Strapi 5 的附加资源 {#additional-resources-for-upgrading-to-strapi-5} ¥Additional resources for upgrading to Strapi 5 以下页面涵盖了升级到 Strapi 5 时针对特定用例的一些专用主题。在继续之前,请确保你已阅读 [升级到 Strapi 5 的介绍](/cms/migration/v4-to-v5/introduction-and-faq) 和 [分步指南](/cms/migration/v4-to-v5/step-by-step)。 ¥The following pages cover some dedicated topics for specific use cases when upgrading to Strapi 5. Please ensure you have read the [introduction to upgrading to Strapi 5](/cms/migration/v4-to-v5/introduction-and-faq) and [step-by-step guide](/cms/migration/v4-to-v5/step-by-step) before moving forward. # 重大更改 Source: https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes # Strapi v4 到 Strapi 5 重大变化 {#strapi-v4-to-strapi-5-breaking-changes} ¥Strapi v4 to Strapi 5 breaking changes 本页面列出了 Strapi 5 中引入的所有重大更改。重大更改分为与主题相关的类别,对于下表中的每一行,你将找到: ¥The present page lists all the breaking changes introduced in Strapi 5. Breaking changes are grouped into topic-related categories, and for each line in the following tables line you will find: * 重大更改的简短描述, ¥a short description of the breaking change, * 以及另外 2 列,"影响插件" 和 "由 codemods 处理",总结重大更改是否也会影响插件,以及重大更改是否由 [升级 CLI 工具](/cms/upgrade-tool) 中的 codemod 自动处理。 ¥and 2 other columns, "Affects plugins" and "Handled by codemods", that sum up whether the breaking change also affects plugins and whether the breaking change is automatically handled by a codemod from the [upgrade CLI tool](/cms/upgrade-tool). 你可以单击下表中任何重大更改的描述以跳转到包含更多详细信息的相应页面。 ¥You can click on the description of any breaking change in the following tables to jump to the corresponding page with more details. :::tip 提示 * 要查看可用 codemods 的完整列表,请在终端中运行 `npx @strapi/upgrade codemods ls` 命令。 ¥To view a full list of available codemods, run the `npx @strapi/upgrade codemods ls` command in your terminal. * 要深入了解 codemods 执行的代码,请转到 GitHub 存储库中的 。 ¥To have a deeper look at the code executed by the codemods, head over to the in the GitHub repository. ::: ## 数据库 {#database} ¥Database | 描述 | 影响插件 | 由 codemods 处理 | | ----------------------------------------------------------------------------------------------------------- | ---- | ------------- | | [内容类型始终具有功能列](/cms/migration/v4-to-v5/breaking-changes/database-columns) | 是的 | 不 | | [不再支持 MySQL v5](/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported) | 不 | 不 | | [长度超过 55 个字符的数据库标识符将自动缩短](/cms/migration/v4-to-v5/breaking-changes/database-identifiers-shortened) | 是的 | ✅ 是的 | | [SQLite 客户端仅支持 `better-sqlite3` 包](/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite) | 不 | ✅ 是的 | | [MySQL 客户端仅支持 `mysql2` 包](/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql) | 不 | ✅ 是的 | ## 依赖 {#dependencies} ¥Dependencies | 描述 | 影响插件 | 由 codemods 处理 | | ----------------------------------------------------------------------------------------------------- | ---- | ------------- | | [CLI 默认包管理器不再是 yarn](/cms/migration/v4-to-v5/breaking-changes/yarn-not-default) | 不 | 不 | | [Vite 是 Strapi 5 中的默认打包器](/cms/migration/v4-to-v5/breaking-changes/vite) | 是的 | 不 | | [Strapi 5 使用 `react-router-dom` v6](/cms/migration/v4-to-v5/breaking-changes/react-router-dom-6) | 是的 | ✅ 是的 | | [Strapi 5 使用 `koa-body` v6](/cms/migration/v4-to-v5/breaking-changes/koa-body-v6) | 是的 | 不 | | [Strapi 5 中删除了 Webpack 别名](/cms/migration/v4-to-v5/breaking-changes/webpack-aliases-removed) | 是的 | 不 | | [Apollo Server v3 升级到 Apollo Server v4](/cms/migration/v4-to-v5/breaking-changes/upgrade-to-apollov4) | 是的 | 不 | ## 配置 {#configuration} ¥Configuration | 描述 | 影响插件 | 由 codemods 处理 | | -------------------------------------------------------------------------------------------------------------------- | ---- | ------------- | | [某些 `env` 专用配置选项由服务器配置处理](/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options) | 不 | 不 | | [配置文件名应满足严格要求](/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files) | 不 | 不 | | [服务器日志级别为 `http`](/cms/migration/v4-to-v5/breaking-changes/server-default-log-level) | 不 | 不 | | [模型配置路径使用 uid 而不是点符号](/cms/migration/v4-to-v5/breaking-changes/model-config-path-uses-uid) | 是的 | 👷 部分 | | [`webhooks.populateRelations` 服务器配置已被删除](/cms/migration/v4-to-v5/breaking-changes/remove-webhook-populate-relations) | 是的 | 不 | | [`public` 中间件中已删除 `defaultIndex` 选项](/cms/migration/v4-to-v5/breaking-changes/default-index-removed) | 不 | 不 | | [服务器代理配置选项分组在 `server.proxy` 对象下](/cms/migration/v4-to-v5/breaking-changes/server-proxy) | 不 | 不 | ## Strapi 对象、方法、包和后端定制 {#strapi-objects-methods-packages-and-back-end-customization} ¥Strapi objects, methods, packages, and back-end customization | 描述 | 影响插件 | 由 codemods 处理 | | ---------------------------------------------------------------------------------------------------------- | ---- | ------------- | | [`strapi.fetch` uses the native `fetch()` API](/cms/migration/v4-to-v5/breaking-changes/fetch) | 是的 | 不 | | [strapi 工厂导入已更改](/cms/migration/v4-to-v5/breaking-changes/strapi-imports) | 是的 | 👷 部分 | | [Strapi 5 中已删除 `isSupportedImage` 方法](/cms/migration/v4-to-v5/breaking-changes/is-supported-image-removed) | 是的 | 不 | | [`strapi-utils` 已重构](/cms/migration/v4-to-v5/breaking-changes/strapi-utils-refactored) | 是的 | ✅ 是的 | | [核心服务方法使用文档服务 API](/cms/migration/v4-to-v5/breaking-changes/core-service-methods-use-document-service) | 是的 | 不 | | [i18n 现在是 strapi 核心的一部分](/cms/migration/v4-to-v5/breaking-changes/i18n-content-manager-locale) | 是的 | ✅ 是的 | ## 插件、提供商、管理面板和前端定制 {#plugins-providers-admin-panel-and-front-end-customization} ¥Plugins, providers, admin panel and front-end customization | 描述 | 影响插件 | 由 codemods 处理 | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | ------------- | | [用户和权限 `register.allowedFields` 默认为 `[]`](/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields) | 不 | ✅ 是的 | | [`helper-plugin` 已删除](/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated) | 是的 | 👷 部分 | | [`injectContentManagerComponent()` 已被删除,取而代之的是 `getPlugin('content-manager').injectComponent()`](/cms/migration/v4-to-v5/breaking-changes/inject-content-manager-component) | 是的 | 不 | | [不支持某些 Mailgun 提供商旧变量](/cms/migration/v4-to-v5/breaking-changes/mailgun-provider-variables) | 是的 | 不 | | [`lockIcon` 属性已由 `licenseOnly` 替换](/cms/migration/v4-to-v5/breaking-changes/license-only) | 是的 | 不 | | [`ContentManagerAppState` redux 已修改](/cms/migration/v4-to-v5/breaking-changes/redux-content-manager-app-state) | 是的 | 不 | | [`EditViewLayout` 和 `ListViewLayout` 已重构](/cms/migration/v4-to-v5/breaking-changes/edit-view-layout-and-list-view-layout-rewritten) | 是的 | 不 | | [管理面板 RBAC redux 存储已更新](/cms/migration/v4-to-v5/breaking-changes/admin-panel-rbac-store-updated) | 是的 | 不 | | [权限提供程序实例的 `getWhere` 方法已被删除](/cms/migration/v4-to-v5/breaking-changes/get-where-removed) | 是的 | 不 | | [设计系统已升级](/cms/migration/v4-to-v5/breaking-changes/design-system) | 是的 | 不 | ## 内容 API {#content-api} ¥Content API | 描述 | 影响插件 | 由 codemods 处理 | | ------------------------------------------------------------------------------------------------------------------------------- | ---- | ------------- | | [Strapi 5 具有一种新的扁平化 API 调用响应格式](/cms/migration/v4-to-v5/breaking-changes/new-response-format) | 是的 | 不 | | [REST API 输入在控制器中默认验证](/cms/migration/v4-to-v5/breaking-changes/default-input-validation) | 是的 | 不 | | [GraphQL API 已更新](/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated) | 是的 | 不 | | [实体服务 API 已弃用,并由文档服务 API 取代](/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated) | 是的 | 👷 部分 | | [在 API 调用中应使用 `documentId` 而不是 `id`](/cms/migration/v4-to-v5/breaking-changes/use-document-id) | 是的 | 👷 部分 | | [根据文档服务 API 方法,数据库生命周期钩子的触发方式不同](/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service) | 是的 | 不 | | [`publicationState` 参数不受支持,已由 `status` 替换](/cms/migration/v4-to-v5/breaking-changes/publication-state-removed) | 是的 | ✅ 是的 | | [禁用草稿和发布的内容类型始终将 postedAt 值设置为日期](/cms/migration/v4-to-v5/breaking-changes/publishedat-always-set-when-dandp-disabled) | 是的 | 不 | | [按 id 排序不再可能按时间顺序排序](/cms/migration/v4-to-v5/breaking-changes/sort-by-id) | 是的 | ✅ 是的 | | [Document Service API 没有 `findPage()` 方法](/cms/migration/v4-to-v5/breaking-changes/no-find-page-in-document-service) | 是的 | 不 | | [Strapi 保留了一些属性和内容类型名称](/cms/migration/v4-to-v5/breaking-changes/attributes-and-content-types-names-reserved) | 是的 | 不 | | [在创建条目时上传文件不再可能](/cms/migration/v4-to-v5/breaking-changes/no-upload-at-entry-creation) | 是的 | 不 | | [应使用详细填充策略填充组件和动态区域](/cms/migration/v4-to-v5/breaking-changes/no-shared-population-strategy-components-dynamic-zones) | 是的 | 不 | | [不建议使用文档服务 API 更新可重复组件](/cms/migration/v4-to-v5/breaking-changes/do-not-update-repeatable-components-with-document-service-api) | 是的 | 不 | # 升级到 Strapi 5 - 简介和常见问题 Source: https://docs.strapi.io/cms/migration/v4-to-v5/introduction-and-faq # 升级到 Strapi 5:简介和常见问题 {#upgrading-to-strapi-5-introduction-and-faq} ¥Upgrading to Strapi 5: Introduction and FAQ Strapi 的最新主要版本是 Strapi 5。Strapi v4 的支持将持续到 2026 年 4 月。 ¥The latest major version of Strapi is Strapi 5. Strapi v4 is still supported until April 2026. 每当你准备好升级到 Strapi 5 时,当前页面都会为你提供帮助。它列出了从 Strapi 4 升级到 Strapi 5 的所有可用资源,并回答你可能遇到的一般问题。 ¥Whenever you feel ready to upgrade to Strapi 5, the present page will help you. It lists all available resources for upgrading from Strapi 4 to Strapi 5 and answers general questions you might have. ## 可用资源 {#available-resources} ¥Available resources 以下所有可用资源将帮助你将应用和插件升级到 Strapi 5,从最常见到最具体的用例: ¥All of the following available resources will help you upgrade your application and plugins to Strapi 5, from the most common to the most specific use cases: ## 常见问题 {#frequently-asked-questions} ¥Frequently asked questions 以下问题及其答案应可帮助你涵盖最常见的用例: ¥The following questions and their answers should help you cover the most common use cases:
How can I handle the upgrade and the installation of the latest dependencies?
How can I handle the breaking changes in the code and adapt my code to Strapi 5?
Strapi 提供了 [升级工具](/cms/upgrade-tool) 来简化该过程。升级工具是一个命令行工具,带有一些命令,用于处理依赖的升级和 codemods 的执行。 ¥Strapi provides an [upgrade tool](/cms/upgrade-tool) to ease the process. The upgrade tool is a command line tool with some commands that handle the upgrade of the dependencies and the execution of **codemods** . 按照 分步指南 了解如何在升级到 Strapi 5 的背景下使用此工具。 ¥Follow the step-by-step guide to learn how to use this tool in the context of upgrading to Strapi 5. Strapi 5 文档还提供了 [完整的重大更改数据库](/cms/migration/v4-to-v5/breaking-changes) 和 [专用资源](/cms/migration/v4-to-v5/additional-resources/introduction) 来涵盖特定用例。
¥Strapi 5 docs also provide a [complete breaking changes database](/cms/migration/v4-to-v5/breaking-changes) and [dedicated resources](/cms/migration/v4-to-v5/additional-resources/introduction) to cover specific use cases.
How can I handle the data migration, ensuring that in Strapi 5 the application will still be working?

Strapi 5 integrates a series of data migration scripts that are run once the application starts for the first time in Strapi 5.

However, please always backup your database (found at .tmp/data.db by default if using a SQL database) before performing any upgrade, as instructed in the step-by-step guide.


As a Strapi Cloud customer, how can I handle the entire upgrade and deployment of my Strapi 5 application? 1. [创建备份](/cloud/projects/settings#backups) 并按照 分步指南 在本地更新你的代码。 ¥[Create a backup](/cloud/projects/settings#backups) and update your code locally, following the step-by-step guide. 2. 从 [Cloud CLI](/cloud/cli/cloud-cli) 运行 `yarn deploy` 或 `npm run deploy` 命令。
¥Run the `yarn deploy` or `npm run deploy` commands from the [Cloud CLI](/cloud/cli/cloud-cli).
Strapi Cloud 将在 Strapi 5 中部署更新的代码,并自动运行数据迁移脚本。
¥Strapi Cloud will deploy the updated code in Strapi 5 and will automatically run the data migration script.
How do I keep the legacy attributes wrapper during the migration? * 对于 REST 客户端,请在重构代码时添加 `Strapi-Response-Format: v4` 标头。[新的响应格式(重大变更)](/cms/migration/v4-to-v5/breaking-changes/new-response-format#migration) 指示在 `curl`、`fetch` 和 Axios 请求中添加标头的位置。 ¥For REST clients, add the `Strapi-Response-Format: v4` header while you refactor your code. The [new response format breaking change](/cms/migration/v4-to-v5/breaking-changes/new-response-format#migration) shows where to add the header in `curl`, `fetch`, and Axios requests. * 对于 GraphQL 客户端,请启用 `v4CompatibilityMode` 并按照 [GraphQL API 迁移文档](/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated#migration) 的步骤逐步移除 `attributes`。 ¥For GraphQL clients, enable `v4CompatibilityMode` and follow the steps of the [GraphQL API migration documentation](/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated#migration) to gradually remove `attributes`. * 启用标头后,REST 响应将继续同时公开 `id`(旧版)和 [`documentId`](/cms/migration/v4-to-v5/breaking-changes/use-document-id)。GraphQL 永远不会公开数字 `id`,因此即使在关闭兼容模式之前,也请将查询更新为使用 `documentId`。 ¥REST responses continue to expose both `id` (legacy) and [`documentId`](/cms/migration/v4-to-v5/breaking-changes/use-document-id) when the header is enabled. GraphQL never exposes numeric `id`, so update your queries to use `documentId` even before you turn compatibility mode off. 一旦所有使用者都读取扁平化格式,就移除标头,以便 Strapi 默认发出 Strapi 5 响应格式。
¥Once every consumer reads the flattened format, remove the header so Strapi emits the Strapi 5 response shape by default.
# 升级到 Strapi 5 的分步指南 Source: https://docs.strapi.io/cms/migration/v4-to-v5/step-by-step # 升级到 Strapi 5 的分步指南 {#step-by-step-guide-to-upgrade-to-strapi-5} ¥Step-by-step guide to upgrade to Strapi 5 Strapi 的最新主要版本是 Strapi 5。 ¥The latest major version of Strapi is Strapi 5. 本页面旨在用作将 Strapi v4 应用升级到 Strapi 5 的分步说明。 ¥The present page is meant to be used as step-by-step instructions for upgrading your Strapi v4 application to Strapi 5. :::prerequisites 你的 Strapi v4 应用已在最新的 v4 次要版本和补丁版本上运行。如果不是,请使用 `minor` 命令运行 [升级工具](/cms/upgrade-tool) 以访问它:`npx @strapi/upgrade minor`。 ¥Your Strapi v4 application is already running on the latest v4 minor and patch version. If it's not, run the [upgrade tool](/cms/upgrade-tool) with the `minor` command to reach it: `npx @strapi/upgrade minor`. ::: ## 步骤 1:准备升级 {#step-1-get-ready-to-upgrade} ¥Step 1: Get ready to upgrade 在进入升级过程之前,请采取以下预防措施: ¥Before getting into the upgrade process itself, take the following precautions: 1. 备份你的数据库: ¥**Backup your database**: * 如果你使用默认配置的 SQLite(Strapi 提供的默认数据库),你的数据库文件名为 `data.db`,位于 Strapi 应用根目录的 `.tmp/` 文件夹中。 ¥If you are using SQLite with the default configuration (the default database provided with Strapi), your database file is named `data.db` and is located in the `.tmp/` folder at the root of your Strapi application. * 如果你使用的是其他类型的数据库,请参阅其官方文档(参见 和 )。 ¥If you are using another type of database, please refer to their official documentation (see and ). * 如果你的项目托管在 Strapi Cloud 上,你可以手动 [创建备份](/cloud/projects/settings#creating-a-manual-backup)。 ¥If your project is hosted on Strapi Cloud, you can manually [create a backup](/cloud/projects/settings#creating-a-manual-backup). 2. 备份你的代码: ¥**Backup your code**: * 如果你的代码已使用 git 进行版本控制,请创建一个新的专用分支来运行迁移。 ¥If your code is versioned with git, create a new dedicated branch to run the migration. * 如果你的代码未使用 git 进行版本控制,请备份你的 Strapi v4 代码并将其存储在安全的地方。 ¥If your code is *not* versioned with git, create a backup of your working Strapi v4 code and store it in a safe place. 3. 确保你使用的插件与 Strapi 5 兼容。 ¥**Ensure the plugins you are using are compatible with Strapi 5**. 为此,请列出你正在使用的插件,然后通过阅读 网站上的专用文档来检查每个插件的兼容性。 ¥To do so, list the plugins you are using, then check compatibility for each of them by reading their dedicated documentation on the website. ## 第 2 步:运行自动迁移 {#step-2-run-automated-migrations} ¥Step 2: Run automated migrations Strapi 提供了一种工具来自动执行升级到 Strapi 5 的某些部分:[升级工具](/cms/upgrade-tool)。 ¥Strapi provides a tool to automate some parts of the upgrade to Strapi 5: the [upgrade tool](/cms/upgrade-tool). 1. 运行升级工具。 ¥**Run the upgrade tool**. ```sh npx @strapi/upgrade major ``` 该命令将执行 Strapi 5 依赖的更新和安装,并运行 codemods 来处理 Strapi 5 带来的一些重大更改。 ¥The command will execute the update and installation of the dependencies of Strapi 5, and run the codemods to handle some of the breaking changes that come with Strapi 5. codemods 将处理以下更改: ¥The codemods will handle the following changes: | Codemod 名称和 GitHub 代码链接 | 描述 | | ----------------------- | ------------------------------------------------------------------------------------------------- | | | 注释掉生命周期文件以支持 [文档服务中间件](/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service) | | | 删除根级配置选项(如 ),并将其替换为插件数组中的插件钩子。 | | | 升级 react 和 react-dom 依赖 | | | 升级 react-router-dom 依赖 | | | 升级 styled-components 依赖 | | | 部分处理从 `@strapi/helper-plugin` 的迁移 | | | 部分处理从实体服务 API 到新文档服务 API 的迁移 | | | 为使用 `aws-s3` 提供程序的用户将 `accessKeyId` 和 `secretAccessKey` 属性封装在 `credentials` 对象中 | | | 将 sqlite 依赖更新为 better-sqlite3 | | | 转换 `@strapi/strapi` 导入以使用新的公共接口 | | | 替换或自定义 WYSIWYG 编辑器 | | | 更新实用程序以使用新的公共接口 | :::tip 提示 如果你开发 Strapi 插件,其他 codemods 会处理辅助插件弃用的某些方面。有关更多信息,请参阅 [相关重大更改更改](/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated)。 ¥If you develop Strapi plugins, other codemods handle some aspects of the helper-plugin deprecation. See the [related breaking change](/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated) for more information. ::: 2. 查看升级工具所做的更改,以检查是否必须手动完成某些代码更新: ¥Go over the changes made by the upgrade tool to **check if you have to manually complete some code updates**: 查找 codemods 自动添加到你的代码中的 `__TODO__`。其中一些可能是在从实体服务 API 迁移到 Strapi 5 中引入的新文档服务 API 时添加的。 ¥Look for `__TODO__` automatically added to your code by the codemods. Some of them might have been added while migrating from the Entity Service API to the new Document Service API introduced in Strapi 5. :::info Document Service API Additional information about the Document Service API can be found in the [breaking change entry description](/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated), the [specific migration guide](/cms/migration/v4-to-v5/additional-resources/from-entity-service-to-document-service), and the [API reference](/cms/api/document-service). ::: ## 步骤 3:检查并处理手动升级 {#step-3-check-and-handle-manual-upgrades} ¥Step 3: Check and handle manual upgrades 以下主要更改可能会影响你的 Strapi 应用并要求你执行一些手动操作。 ¥The following main changes might affect your Strapi application and require you to do some manual actions. 对于每个日志项,请阅读指示的重大更改条目并检查升级工具运行后是否仍需要某些手动操作: ¥For each of them, read the indicated breaking change entry and check if some manual actions are still required after the upgrade tool has run: 1. 数据库迁移: ¥**Database migration**: 1. 不支持 MySQL v5 👉 参见 [重大变更](/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported) ¥MySQL v5 is not supported 👉 see [breaking change](/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported) 2. 仅支持 better-sqlite3 👉 参见 [重大变更](/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite) ¥Only better-sqlite3 is supported 👉 see [breaking change](/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite) 3. 仅支持 mysql2 👉 参见 [重大变更](/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql) ¥Only mysql2 is supported 👉 see [breaking change](/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql) 4. 生命周期钩子的触发方式不同👉参见 [重大变更](/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service) ¥Lifecycle hooks are triggered differently 👉 see [breaking change](/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service) 2. 配置: ¥**Configuration**: 1. 一些环境变量由服务器配置处理👉参见 [重大变更](/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options) ¥Some environment variables are handled by the server configuration 👉 see [breaking change](/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options) 2. 自定义配置必须满足特定要求👉参见 [重大变更](/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files) ¥Custom configuration must meet specific requirements 👉 see [breaking change](/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files) 3. 管理面板自定义: ¥**Admin panel customization**: * 辅助插件已被删除👉参见 [迁移参考](/cms/migration/v4-to-v5/additional-resources/helper-plugin) ¥The helper-plugin has been removed 👉 see [migration reference](/cms/migration/v4-to-v5/additional-resources/helper-plugin) 👉 最后,查看 [重大变更数据库](/cms/migration/v4-to-v5/breaking-changes) 的其余部分,了解你可能担心的任何边缘情况。 ¥👉 Finally, go over the rest of the [breaking changes database](/cms/migration/v4-to-v5/breaking-changes) for any edge case you might be concerned about. ## 步骤 4:迁移 API 消费方 {#step-4-migrate-the-api-consuming-side} ¥Step 4: Migrate the API consuming side Strapi 5 已更新 REST 和 GraphQL API。 ¥Strapi 5 has updated both the REST and GraphQL APIs. 请按照以下步骤操作,并利用向后兼容性标头和引导式迁移资源,逐步将你的代码更新为 Strapi 5。 ¥Follow the steps below and leverage retro-compatibility headers and guided migration resources to gradually update your code for Strapi 5. ### 迁移 REST API 调用 {#migrate-rest-api-calls} ¥Migrate REST API calls 1. 在仍然需要 `attributes` 的所有地方启用兼容性标头,方法是在 HTTP 客户端、SDK 和中间件的 REST 调用中添加 `Strapi-Response-Format: v4`(有关具体示例,请参阅 [重大变更条目](/cms/migration/v4-to-v5/breaking-changes/new-response-format#migration))。 ¥Enable the compatibility header everywhere you still expect `attributes`, by adding `Strapi-Response-Format: v4` to REST calls in HTTP clients, SDKs, and middleware (see the [breaking change entry](/cms/migration/v4-to-v5/breaking-changes/new-response-format#migration) for concrete examples). 2. 启用标头后,请审核现有有效负载。捕获代表性响应(包括已填充的关系、组件和媒体),以便验证旧版客户端在过渡期间是否仍然有效。 ¥While the header is on, audit existing payloads. Capture representative responses (including populated relations, components, and media) so you can verify that legacy consumers keep working during the transition. 3. 通过以下方式更新和测试每个客户端: ¥Update and test each client by: * 移除 `data.attributes` 访问权限 ¥removing `data.attributes` access, * 切换到扁平化有效负载后, ¥switching to the flattened payload, * 并且在 REST API 之前仅返回数字 `id` 的地方都采用 [`documentId`](/cms/migration/v4-to-v5/breaking-changes/use-document-id)。 ¥and adopting [`documentId`](/cms/migration/v4-to-v5/breaking-changes/use-document-id) wherever the REST API was previously returning numeric `id` only. 4. 按端点或使用者禁用兼容性标头:一旦给定客户端的测试通过,就从其请求中移除 `Strapi-Response-Format: v4`。重复此操作,直到没有使用者依赖于旧版封装器。 ¥Disable the compatibility header per endpoint or consumer: once tests pass for a given client, remove `Strapi-Response-Format: v4` from its requests. Repeat until no consumer depends on the legacy wrapper. ### 迁移 GraphQL API 调用 {#migrate-graphql-api-calls} ¥Migrate GraphQL API calls 1. 通过在 `graphql` 插件配置中将 `v4CompatibilityMode` 设置为 `true` 来启用兼容性标头,以便在重构客户端时客户端可以继续依赖 `data.attributes`。 ¥Enable the compatibility header by setting `v4CompatibilityMode` to `true` in the `graphql` plugin configuration, so clients can continue to rely on `data.attributes` while you refactor them. 2. 请按照 [GraphQL 的重大变更条目](/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated) 的每个步骤操作。这将指导你将 `id` 替换为 `documentId`,采用 `_connection` 查询,移除 `attributes`,最后切换到 `nodes/pageInfo`。 ¥Follow each step of the [breaking change entry for GraphQL](/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated). This will guide you to swap `id` for `documentId`, adopt `_connection` queries, remove `attributes`, and finally switch to `nodes/pageInfo`. 3. 测试 Relay 和非 Relay 查询,方法是:对于不需要 Relay 语义的客户端,移除 `_connection` 和 `data` 后,确认分页元数据是否仍然符合预期。 ¥Test Relay and non-Relay queries by confirming that pagination metadata still matches expectations when you remove `_connection` and `data` for clients that do not need Relay semantics. 4. 禁用 `v4CompatibilityMode` 兼容性标头:在每次查询和变更操作都使用扁平化模式后,将标头设置为 `false`,以便服务器默认发出 Strapi 5 格式。 ¥Disable the `v4CompatibilityMode` compatibility header: after every query and mutation works with the flattened schema, set the header to `false` so the server emits the Strapi 5 format by default. # 管理面板 API Source: https://docs.strapi.io/cms/plugins-development/admin-panel-api # 管理面板 API 插件 {#admin-panel-api-for-plugins} ¥Admin Panel API for plugins Strapi 插件可以与 Strapi 应用的 [后端](/cms/plugins-development/server-api) 和前端交互。管理面板 API 是关于前端部分的,即它允许插件自定义 Strapi 的 [管理面板](/cms/intro)。 ¥A Strapi plugin can interact with both the [back end](/cms/plugins-development/server-api) and the front end of a Strapi application. The Admin Panel API is about the front end part, i.e. it allows a plugin to customize Strapi's [admin panel](/cms/intro). 管理面板是一个 ### 设置接口 {#settings-api} ¥Settings API 设置 API 允许: ¥The Settings API allows: * [创建一个新的设置部分](#createsettingsection) ¥[creating a new setting section](#createsettingsection) * 将 [单个链接](#addsettingslink) 或 [一次多个链接](#addsettingslinks) 添加到现有设置部分 ¥adding [a single link](#addsettingslink) or [multiple links at once](#addsettingslinks) to existing settings sections :::note 注意 添加新部分发生在 [register](#register) 生命周期中,而添加链接发生在 [bootstrap](#bootstrap) 生命周期中。 ¥Adding a new section happens in the [register](#register) lifecycle while adding links happens during the [bootstrap](#bootstrap) lifecycle. ::: 所有函数都接受链接作为具有以下参数的对象: ¥All functions accept links as objects with the following parameters: | 范围 | 类型 | 描述 | | ------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | 字符串 | React ID | | `to` | 字符串 | 链接应指向的路径 | | `intlLabel` | 目的 | 链接的标签,遵循 约定,带有:
  • `id`:用于插入本地化标签的 id
  • `defaultMessage`:链接的默认标签
| | `Component` | 异步函数 | 返回插件入口点的动态导入 | | `permissions` | 对象数组 | 插件的 `permissions.js` 文件中声明的权限 | | `licenseOnly` | 布尔值 | 如果设置为 `true`,则在图标或菜单项旁边添加一个闪电⚡️图标,以指示该功能或插件需要付费许可。
(默认为 `false`) | #### createSettingSection() {#createsettingsection} 类型:`Function` ¥**Type**: `Function` 创建一个新的设置部分。 ¥Create a new settings section. 该函数有 2 个参数: ¥The function takes 2 arguments: | 争论 | 类型 | 描述 | | ----- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 第一个参数 | 目的 | 部分标签:
  • `id`(字符串):部分 ID
  • `intlLabel`(对象):该部分的本地化标签,遵循 约定,使用:
    • `id`:用于插入本地化标签的 id
    • `defaultMessage`:该部分的默认标签
| | 第二个参数 | 对象数组 | 该部分中包含的链接 | :::note 注意 `intlLabel.id` 是翻译文件中使用的 ID (`[plugin-name]/admin/src/translations/[language].json`) ¥`intlLabel.id` are ids used in translation files (`[plugin-name]/admin/src/translations/[language].json`) ::: **示例:** ¥**Example:** ```jsx title="my-plugin/admin/src/index.js" const myComponent = async () => { const component = await import( /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers' ); return component; }; register(app) { app.createSettingSection( { id: String, intlLabel: { id: String, defaultMessage: String } }, // Section to create [ // links { intlLabel: { id: String, defaultMessage: String }, id: String, to: String, Component: myComponent, permissions: Object[], }, ] ); }, }; ``` #### addSettingsLink() {#addsettingslink} 类型:`Function` ¥**Type**: `Function` 添加到现有设置部分的唯一链接。 ¥Add a unique link to an existing settings section. **示例:** ¥**Example:** ```jsx title="my-plugin/admin/src/index.js" const myComponent = async () => { const component = await import( /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers' ); return component; }; bootstrap(app) { // Adding a single link app.addSettingsLink( 'global', // id of the section to add the link to { intlLabel: { id: String, defaultMessage: String }, id: String, to: String, Component: myComponent, permissions: Object[], licenseOnly: true, // mark the feature as a paid one not available in your license } ) } } ``` #### addSettingsLinks() {#addsettingslinks} 类型:`Function` ¥**Type**: `Function` 将多个链接添加到现有设置部分。 ¥Add multiple links to an existing settings section. **示例:** ¥**Example:** ```jsx title="my-plugin/admin/src/index.js" const myComponent = async () => { const component = await import( /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers' ); return component; }; bootstrap(app) { // Adding several links at once app.addSettingsLinks( 'global', // id of the section to add the link in [{ intlLabel: { id: String, defaultMessage: String }, id: String, to: String, Component: myComponent, permissions: Object[], licenseOnly: true, // mark the feature as a paid one not available in your license }] ) } } ``` ### 注入区 API {#injection-zones-api} ¥Injection Zones API 注入区域是指视图布局的区域,其中一个插件允许另一个插件注入自定义 React 组件(例如按钮等 UI 元素)。 ¥Injection zones refer to areas of a view's layout where a plugin allows another to inject a custom React component (e.g. a UI element like a button). 插件可以使用: ¥Plugins can use: * Strapi 的 [预定义注入区](#using-predefined-injection-zones) 用于内容管理器, ¥Strapi's [predefined injection zones](#using-predefined-injection-zones) for the Content Manager, * 或由插件创建的自定义注入区域 ¥or custom injection zones, created by a plugin :::note 注意 注入区域在 [register()](#register) 生命周期中定义,但组件在 [bootstrap()](#bootstrap) 生命周期中注入。 ¥Injection zones are defined in the [register()](#register) lifecycle but components are injected in the [bootstrap()](#bootstrap) lifecycle. ::: #### 使用预定义的注入区域 {#using-predefined-injection-zones} ¥Using predefined injection zones Strapi 管理面板带有预定义的注入区域,因此可以将组件添加到 [内容管理者](/cms/intro) 的 UI 中: ¥Strapi admin panel comes with predefined injection zones so components can be added to the UI of the [Content Manager](/cms/intro): | 看法 | 注入区名称和位置 | | ---- | ----------------------------------- | | 列表显示 | `actions`:位于过滤器和齿轮图标之间 | | 编辑视图 | `right-links`:位于 "配置视图" 和 "编辑" 按钮之间 | #### 创建自定义注入区域 {#creating-a-custom-injection-zone} ¥Creating a custom injection zone 要创建自定义注入区域,请将其声明为带有 `area` prop 的 `` React 组件,该组件采用具有以下命名约定的字符串:`plugin-name.viewName.injectionZoneName`。 ¥To create a custom injection zone, declare it as a `` React component with an `area` prop that takes a string with the following naming convention: `plugin-name.viewName.injectionZoneName`. #### 注入组件 {#injecting-components} ¥Injecting components 插件有两种不同的方式来注入组件: ¥A plugin has 2 different ways of injecting a component: * 要将插件中的组件注入另一个插件的注入区域,请使用 `injectComponent()` 函数 ¥to inject a component from a plugin into another plugin's injection zones, use the `injectComponent()` function * 要专门将组件注入内容管理器的 [预定义注入区](#using-predefined-injection-zones) 之一,请改用 `getPlugin('content-manager').injectComponent()` 函数 ¥to specifically inject a component into one of the Content Manager's [predefined injection zones](#using-predefined-injection-zones), use the `getPlugin('content-manager').injectComponent()` function instead `injectComponent()` 和 `getPlugin('content-manager').injectComponent()` 方法都接受以下参数: ¥Both the `injectComponent()` and `getPlugin('content-manager').injectComponent()` methods accept the following arguments: | 争论 | 类型 | 描述 | | ----- | --- | ------------------------------------------------------------------------------------ | | 第一个参数 | 字符串 | 组件注入的视图 | | 第二个参数 | 字符串 | 注入组件的区域 | | 第三个参数 | 目的 | 具有以下键的对象:
  • `name`(字符串):组件的名称
  • `Component`(函数或类):要注入的 React 组件
|
Example: Inject a component in the informations box of the Edit View of the Content Manager: ```jsx title="my-plugin/admin/src/index.js" bootstrap(app) { app.getPlugin('content-manager').injectComponent('editView', 'informations', { name: 'my-plugin-my-compo', Component: () => 'my-compo', }); } } ```
Example: Creating a new injection zone and injecting it from a plugin to another one: ```jsx title="my-plugin/admin/src/injectionZones.js" // Use the injection zone in a view const HomePage = () => { return (

This is the homepage

); }; ``` ```jsx title="my-plugin/admin/src/index.js" // Declare this injection zone in the register lifecycle of the plugin register() { app.registerPlugin({ // ... injectionZones: { homePage: { right: [] } } }); }, } ``` ```jsx title="my-other-plugin/admin/src/index.js" // Inject the component from a plugin in another plugin register() { // ... }, bootstrap(app) { app.getPlugin('my-plugin').injectComponent('homePage', 'right', { name: 'my-other-plugin-component', Component: () => 'This component is injected', }); } }; ```
#### 使用 `useCMEditViewDataManager` React hook 访问数据 {#accessing-data-with-the-usecmeditviewdatamanager-react-hook} ¥Accessing data with the `useCMEditViewDataManager` React hook 一旦定义了注入区域,内容管理器中要注入的组件就可以通过 `useCMEditViewDataManager` React hook 访问编辑视图的所有数据。 ¥Once an injection zone is defined, the component to be injected in the Content Manager can have access to all the data of the Edit View through the `useCMEditViewDataManager` React hook.
Example of a basic component using the 'useCMEditViewDataManager' hook ```js const MyCompo = () => { const { createActionAllowedFields: [], // Array of fields that the user is allowed to edit formErrors: {}, // Object errors readActionAllowedFields: [], // Array of field that the user is allowed to edit slug: 'api::address.address', // Slug of the content-type updateActionAllowedFields: [], allLayoutData: { components: {}, // components layout contentType: {}, // content-type layout }, initialData: {}, isCreatingEntry: true, isSingleType: true, status: 'resolved', layout: {}, // Current content-type layout hasDraftAndPublish: true, modifiedData: {}, onPublish: () => {}, onUnpublish: () => {}, addComponentToDynamicZone: () => {}, addNonRepeatableComponentToField: () => {}, addRelation: () => {}, addRepeatableComponentToField: () => {}, moveComponentDown: () => {}, moveComponentField: () => {}, moveComponentUp: () => {}, moveRelation: () => {}, onChange: () => {}, onRemoveRelation: () => {}, removeComponentFromDynamicZone: () => {}, removeComponentFromField: () => {}, removeRepeatableField: () => {}, } = useCMEditViewDataManager() return null } ```
### Reducer API {#reducers-api} Reducer 是 reducer,可用于在组件之间共享状态。在以下情况下,Reducer 会很有用: ¥Reducers are reducers that can be used to share state between components. Reducers can be useful when: * 应用中的许多地方都需要大量的应用状态。 ¥Large amounts of application state are needed in many places in the application. * 应用状态经常更新。 ¥The application state is updated frequently. * 更新该状态的逻辑可能很复杂。 ¥The logic to update that state may be complex. 可以在 [`register`](#register) 生命周期期间使用 `addReducers()` 函数将 reducer 添加到插件接口。 ¥Reducers can be added to a plugin interface with the `addReducers()` function during the [`register`](#register) lifecycle. 使用以下语法将化简器声明为对象: ¥A reducer is declared as an object with this syntax: **示例:** ¥**Example:** ```js title="my-plugin/admin/src/index.js" const reducers = { // Reducer Syntax [`${pluginId}_exampleReducer`]: exampleReducer } register(app) { app.addReducers(reducers) }, bootstrap() {}, }; ``` ### 钩子 API {#hooks-api} ¥Hooks API Hooks API 允许插件创建和注册钩子,即应用中插件可以添加个性化行为的位置。 ¥The Hooks API allows a plugin to create and register hooks, i.e. places in the application where plugins can add personalized behavior. Hooks 应在插件的 [bootstrap](#bootstrap) 生命周期内注册。 ¥Hooks should be registered during the [bootstrap](#bootstrap) lifecycle of a plugin. 然后,Hook 可以串联、瀑布式或并行运行: ¥Hooks can then be run in series, in waterfall or in parallel: * `runHookSeries` 返回每个函数执行结果对应的数组,有序 ¥`runHookSeries` returns an array corresponding to the result of each function executed, ordered * `runHookParallel` 返回一个与执行函数解析的 Promise 结果相对应的数组,有序 ¥`runHookParallel` returns an array corresponding to the result of the promise resolved by the function executed, ordered * `runHookWaterfall` 返回与从初始值 `args` 开始的不同函数应用的所有转换相对应的单个值。 ¥`runHookWaterfall` returns a single value corresponding to all the transformations applied by the different functions starting with the initial value `args`.
Example: Create a hook in a plugin and use it in another plugin ```jsx title="my-plugin/admin/src/index.js" // Create a hook in a plugin register(app) { app.createHook('My-PLUGIN/MY_HOOK'); } } ``` ```jsx title="my-other-plugin/admin/src/index.js" // Use the hook in another plugin bootstrap(app) { app.registerHook('My-PLUGIN/MY_HOOK', (...args) => { console.log(args) // important: return the mutated data return args }); app.registerPlugin({...}) } } ```
#### 预定义钩子 {#predefined-hooks} ¥Predefined hooks Strapi 包含一个预定义的 `Admin/CM/pages/ListView/inject-column-in-table` 钩子,可用于添加或改变 [内容管理者](/cms/intro) 列表视图的列: ¥Strapi includes a predefined `Admin/CM/pages/ListView/inject-column-in-table` hook that can be used to add or mutate a column of the List View of the [Content Manager](/cms/intro): ```jsx runHookWaterfall(INJECT_COLUMN_IN_TABLE, { displayedHeaders: ListFieldLayout[], layout: ListFieldLayout, }); ``` ```tsx interface ListFieldLayout { /** * The attribute data from the content-type's schema for the field */ attribute: Attribute.Any | { type: 'custom' }; /** * Typically used by plugins to render a custom cell */ cellFormatter?: ( data: Document, header: Omit, { collectionType, model }: { collectionType: string; model: string } ) => React.ReactNode; label: string | MessageDescriptor; /** * the name of the attribute we use to display the actual name e.g. relations * are just ids, so we use the mainField to display something meaninginful by * looking at the target's schema */ mainField?: string; name: string; searchable?: boolean; sortable?: boolean; } interface ListLayout { layout: ListFieldLayout[]; components?: never; metadatas: { [K in keyof Contracts.ContentTypes.Metadatas]: Contracts.ContentTypes.Metadatas[K]['list']; }; options: LayoutOptions; settings: LayoutSettings; } type LayoutOptions = Schema['options'] & Schema['pluginOptions'] & object; interface LayoutSettings extends Contracts.ContentTypes.Settings { displayName?: string; icon?: never; } ``` Strapi 还包括一个 `Admin/CM/pages/EditView/mutate-edit-view-layout` 钩子,可用于改变 [内容管理者](/cms/intro) 的编辑视图: ¥Strapi also includes a `Admin/CM/pages/EditView/mutate-edit-view-layout` hook that can be used to mutate the Edit View of the [Content Manager](/cms/intro): ```tsx interface EditLayout { layout: Array>; components: { [uid: string]: { layout: Array; settings: Contracts.Components.ComponentConfiguration['settings'] & { displayName?: string; icon?: string; }; }; }; metadatas: { [K in keyof Contracts.ContentTypes.Metadatas]: Contracts.ContentTypes.Metadatas[K]['edit']; }; options: LayoutOptions; settings: LayoutSettings; } interface EditFieldSharedProps extends Omit { hint?: string; mainField?: string; size: number; unique?: boolean; visible?: boolean; } /** * Map over all the types in Attribute Types and use that to create a union of new types where the attribute type * is under the property attribute and the type is under the property type. */ type EditFieldLayout = { [K in Attribute.Kind]: EditFieldSharedProps & { attribute: Extract; type: K; }; }[Attribute.Kind]; type LayoutOptions = Schema['options'] & Schema['pluginOptions'] & object; interface LayoutSettings extends Contracts.ContentTypes.Settings { displayName?: string; icon?: never; } ``` :::note 注意 `EditViewLayout` 和 `ListViewLayout` 是 `useDocumentLayout` 钩子的一部分(参见 )。 ¥`EditViewLayout` and `ListViewLayout` are parts of the `useDocumentLayout` hook (see ). ::: # 内容管理器 API Source: https://docs.strapi.io/cms/plugins-development/content-manager-apis # 内容管理器 API {#content-manager-apis} ¥Content Manager APIs 内容管理器 API 是 [管理面板 API](/cms/plugins-development/admin-panel-api) 的一部分。它们是将内容或选项从插件添加到 [内容管理者](/cms/features/content-manager) 的一种方式,因此你可以通过从自己的插件添加功能来扩展内容管理器,就像使用 [注入区域](/cms/plugins-development/admin-panel-api#injection-zones-api) 一样。 ¥Content-Manager APIs are part of the [Admin Panel API](/cms/plugins-development/admin-panel-api). They are a way to add content or options from plugins to the [Content-Manager](/cms/features/content-manager), so you can extend the Content-Manager by adding functionality from your own plugin, just like you can do it with [Injection Zones](/cms/plugins-development/admin-panel-api#injection-zones-api). Strapi 5 提供 4 个 Content-Manager API,所有 API 都可以通过 `app.getPlugin('content-manager').apis` 访问: ¥Strapi 5 provides 4 Content-Manager APIs, all accessible through `app.getPlugin('content-manager').apis`: * [`addEditViewSidePanel`](#addeditviewsidepanel), * [`addDocumentAction`](#adddocumentaction), * [`addDocumentHeaderAction`](#adddocumentheaderaction), * 和 [`addBulkAction`](#addbulkaction)。 ¥and [`addBulkAction`](#addbulkaction). ## 一般信息 {#general-information} ¥General information 所有内容管理器 API 都共享相同的 API 形状,并且必须使用组件。 ¥All the Content Manager APIs share the same API shape and must use components. ### API 形状 {#api-shape} ¥API shape 所有内容管理器 API 的工作方式相同:要使用它们,请在插件的 [bootstrap](/cms/plugins-development/admin-panel-api#bootstrap) 函数中调用它们,有两种可能的方式。 ¥All Content Manager APIs works in the same way: to use them, call them on your plugin’s [bootstrap](/cms/plugins-development/admin-panel-api#bootstrap) function, in 2 possible ways. 使用 TypeScript 时,`app.getPlugin()` 返回的 `apis` 属性的类型为 `unknown`。在调用 API 之前将其转换为 `ContentManagerPlugin['config']['apis']`: ¥When using TypeScript, the `apis` property returned by `app.getPlugin()` is typed as `unknown`. Cast it to `ContentManagerPlugin['config']['apis']` before calling the APIs: * 传递一个包含要添加内容的数组。例如,以下代码将在当前 EditViewSidePanels 的末尾添加 ReleasesPanel: ¥Passing an array with what you want to add. For example, the following code would add the ReleasesPanel at the end of the current EditViewSidePanels: ```tsx import type { ContentManagerPlugin } from '@strapi/content-manager/strapi-admin'; const apis = app.getPlugin('content-manager').apis as ContentManagerPlugin['config']['apis']; apis.addEditViewSidePanel([ReleasesPanel]); ``` * 传递一个接收当前元素并返回新元素的函数。例如,如果你想在列表中的特定位置添加某些内容,如以下代码所示,这很有用: ¥Passing a function that receives the current elements and return the new ones. This is useful if, for example, you want to add something in a specific position in the list, like in the following code: ```tsx const apis = app.getPlugin('content-manager').apis as ContentManagerPlugin['config']['apis']; apis.addEditViewSidePanel((panels) => [SuperImportantPanel, ...panels]); ``` ### 组件 {#components} ¥Components 你需要将组件传递给 API 才能将内容添加到内容管理器。这些组件基本上是接收一些属性并返回具有某种形状的对象(取决于函数)的函数。每个组件的返回对象根据你使用的功能而不同,但它们会收到类似的属性,具体取决于你使用的是 ListView 还是 EditView API。这些属性包含有关你正在查看或编辑的文档的重要信息。 ¥You need to pass components to the API in order to add things to the Content Manager. These components are basically functions that receive some properties and return and object with some shape (depending on the function). Each component’s return object is different based on the function you’re using, but they receive similar properties, depending on whether you use a ListView or EditView API. These properties include important information about the document(s) you are viewing or editing. #### ListViewContext {#listviewcontext} ```jsx interface ListViewContext { /** * Will be either 'single-types' | 'collection-types' */ collectionType: string; /** * The current selected documents in the table */ documents: Document[]; /** * The current content-type's model. */ model: string; } ``` #### EditViewContext {#editviewcontext} ```jsx interface EditViewContext { /** * This will only be null if the content-type * does not have draft & publish enabled. */ activeTab: 'draft' | 'published' | null; /** * Will be either 'single-types' | 'collection-types' */ collectionType: string; /** * Will be undefined if someone is creating an entry. */ document?: Document; /** * Will be undefined if someone is creating an entry. */ documentId?: string; /** * Will be undefined if someone is creating an entry. */ meta?: DocumentMetadata; /** * The current content-type's model. */ model: string; } ``` :::tip 提示 有关类型和 API 的更多信息,请参阅 。 ¥More information about types and APIs can be found in . ::: **示例:** ¥**Example:** 可以这样将面板添加到侧边栏: ¥Adding a panel to the sidebar can be done this way: ```jsx title="my-plugin/components/my-panel.ts" const Panel: PanelComponent = ({ activeTab, collectionType, document, documentId, meta, model }: PanelComponentProps) => { return { title: 'My Panel', content:

I'm on {activeTab}

} } ``` ## 可用 API {#available-apis} ¥Available APIs
### `addEditViewSidePanel` {#addeditviewsidepanel} 使用此功能可将新面板添加到“编辑”视图侧边栏,就像以下示例中将某些内容添加到“发布”面板一样: ¥Use this to add new panels to the Edit view sidebar, just like in the following example where something is added to the Releases panel: ![addEditViewSidePanel](/img/assets/content-manager-apis/add-edit-view-side-panel.png) ```jsx addEditViewSidePanel(panels: DescriptionReducer | PanelComponent[]) ``` #### PanelComponent {#panelcomponent} `PanelComponent` 接收 [EditViewContext](#editviewcontext) 中列出的属性,并返回具有以下形状的对象: ¥A `PanelComponent` receives the properties listed in [EditViewContext](#editviewcontext) and returns an object with the following shape: ```tsx type PanelComponent = (props: PanelComponentProps) => { title: string; content: React.ReactNode; }; ``` `PanelComponentProps` 扩展了 [EditViewContext](#editviewcontext)。 ¥`PanelComponentProps` extends the [EditViewContext](#editviewcontext). ### `addDocumentAction` {#adddocumentaction} 使用此 API 向内容管理器的编辑视图或列表视图添加更多操作。有 3 个可用位置: ¥Use this API to add more actions to the Edit view or the List View of the Content Manager. There are 3 positions available: * 编辑视图的 `header`: ¥`header` of the Edit view: ![Header of the Edit view](/img/assets/content-manager-apis/add-document-action-header.png) * 编辑视图的 `panel`: ¥`panel` of the Edit view: ![Panel of the Edit View](/img/assets/content-manager-apis/add-document-action-panel.png) * 列表视图的 `table-row`: ¥`table-row` of the List view: ![Table-row in the List View](/img/assets/content-manager-apis/add-document-action-tablerow.png) ```jsx addDocumentAction(actions: DescriptionReducer | DocumentActionComponent[]) ``` #### DocumentActionDescription {#documentactiondescription} API 的接口和属性如下所示: ¥The interface and properties of the API look like the following: ```jsx interface DocumentActionDescription { label: string; onClick?: (event: React.SyntheticEvent) => Promise | boolean | void; icon?: React.ReactNode; /** * @default false */ disabled?: boolean; /** * @default 'panel' * @description Where the action should be rendered. */ position?: DocumentActionPosition | DocumentActionPosition[]; dialog?: DialogOptions | NotificationOptions | ModalOptions; /** * @default 'secondary' */ variant?: ButtonProps['variant']; } type DocumentActionPosition = 'panel' | 'header' | 'table-row'; interface DialogOptions { type: 'dialog'; title: string; content?: React.ReactNode; variant?: ButtonProps['variant']; onConfirm?: () => void | Promise; onCancel?: () => void | Promise; } interface NotificationOptions { type: 'notification'; title: string; link?: { label: string; url: string; target?: string; }; content?: string; onClose?: () => void; status?: NotificationConfig['type']; timeout?: number; } interface ModalOptions { type: 'modal'; title: string; content: React.ComponentType<{ onClose: () => void; }> | React.ReactNode; footer?: React.ComponentType<{ onClose: () => void; }> | React.ReactNode; onClose?: () => void; } ``` ### `addDocumentHeaderAction` {#adddocumentheaderaction} 使用此 API 向内容管理器的编辑视图的标题添加更多操作: ¥Use this API to add more actions to the header of the Edit view of the Content Manager: ![addEditViewSidePanel](/img/assets/content-manager-apis/add-document-header-action.png) ```jsx addDocumentHeaderAction(actions: DescriptionReducer | HeaderActionComponent[]) ``` #### HeaderActionDescription {#headeractiondescription} API 的接口和属性如下所示: ¥The interface and properties of the API look like the following: ```jsx interface HeaderActionDescription { disabled?: boolean; label: string; icon?: React.ReactNode; type?: 'icon' | 'default'; onClick?: (event: React.SyntheticEvent) => Promise | boolean | void; dialog?: DialogOptions; options?: Array<{ disabled?: boolean; label: string; startIcon?: React.ReactNode; textValue?: string; value: string; }>; onSelect?: (value: string) => void; value?: string; } interface DialogOptions { type: 'dialog'; title: string; content?: React.ReactNode; footer?: React.ReactNode; } ``` ### `addBulkAction` {#addbulkaction} 使用此 API 添加在内容管理器的列表视图上选择条目时显示的按钮,例如 "添加到发布" 按钮: ¥Use this API to add buttons that show up when entries are selected on the List View of the Content Manager, just like the "Add to Release" button for instance: ![addEditViewSidePanel](/img/assets/content-manager-apis/add-bulk-action.png) ```jsx addBulkAction(actions: DescriptionReducer | BulkActionComponent[]) ``` #### BulkActionDescription {#bulkactiondescription} API 的接口和属性如下所示: ¥The interface and properties of the API look like the following: ```jsx interface BulkActionDescription { dialog?: DialogOptions | NotificationOptions | ModalOptions; disabled?: boolean; icon?: React.ReactNode; label: string; onClick?: (event: React.SyntheticEvent) => void; /** * @default 'default' */ type?: 'icon' | 'default'; /** * @default 'secondary' */ variant?: ButtonProps['variant']; } ``` # 插件创建和设置 Source: https://docs.strapi.io/cms/plugins-development/create-a-plugin # 插件创建 {#plugin-creation} ¥Plugin creation 创建 Strapi 5 插件的方法有很多,但最快和推荐的方法是使用插件 SDK。 ¥There are many ways to create a Strapi 5 plugin, but the fastest and recommended way is to use the Plugin SDK. 插件 SDK 是一组命令,用于开发插件以将其用作本地插件或将它们发布在 NPM 上和/或将它们提交到 Marketplace。 ¥The Plugin SDK is a set of commands orientated around developing plugins to use them as local plugins or to publish them on NPM and/or submit them to the Marketplace. 使用插件 SDK,你无需在创建插件之前设置 Strapi 项目。 ¥With the Plugin SDK, you do not need to set up a Strapi project before creating a plugin. 本指南涵盖从头开始创建插件、将其链接到现有 Strapi 项目以及发布插件。如果你已经有现有插件,则可以改造插件设置以利用插件 SDK 命令(请参阅 [插件 SDK 参考](/cms/plugins-development/plugin-sdk) 以获取可用命令的完整列表)。 ¥The present guide covers creating a plugin from scratch, linking it to an existing Strapi project, and publishing the plugin. If you already have an existing plugin, you can instead retrofit the plugin setup to utilise the Plugin SDK commands (please refer to the [Plugin SDK reference](/cms/plugins-development/plugin-sdk) for a full list of available commands). :::note 注意 本指南假设你想要开发 Strapi 项目外部的插件。但是,如果你想在现有项目中开发插件,步骤基本上保持不变。如果你不是 [使用单一存储库](#monorepo),步骤完全相同。 ¥This guide assumes you want to develop a plugin external to your Strapi project. However, the steps largely remain the same if you want to develop a plugin within your existing project. If you are not [using a monorepo](#monorepo) the steps are exactly the same. ::: :::prerequisites 路径 `my-strapi-plugin` 可以替换为你想要调用插件的任何内容,包括应创建插件的路径(例如 `code/strapi-plugins/my-new-strapi-plugin`)。 ¥The path `my-strapi-plugin` can be replaced with whatever you want to call your plugin, including the path to where it should be created (e.g., `code/strapi-plugins/my-new-strapi-plugin`). 你将看到一系列提示来帮助你设置插件。如果你对所有选项都选择“是”,则最终结构将类似于默认的 [插件结构](/cms/plugins-development/plugin-structure)。 ¥You will be ran through a series of prompts to help you setup your plugin. If you selected yes to all options the final structure will be similar to the default [plugin structure](/cms/plugins-development/plugin-structure). ### 将插件链接到你的项目 {#linking-the-plugin-to-your-project} ¥Linking the plugin to your project 为了在开发过程中测试你的插件,建议的方法是将其链接到 Strapi 项目。 ¥In order to test your plugin during its development, the recommended approach is to link it to a Strapi project. 使用 `watch:link` 命令将你的插件链接到项目。该命令将输出有关如何将你的插件链接到 Strapi 项目的说明。 ¥Linking your plugin to a project is done with the `watch:link` command. The command will output explanations on how to link your plugin to a Strapi project. 在新的终端窗口中,运行以下命令: ¥In a new terminal window, run the following commands: :::note 注意 在上面的例子中,我们在将插件 (`my-strapi-plugin`) 链接到项目时使用其名称。这是包的名称,而不是文件夹的名称。 ¥In the above examples we use the name of the plugin (`my-strapi-plugin`) when linking it to the project. This is the name of the package, not the name of the folder. ::: 因为这个插件是通过 `node_modules` 安装的,所以你不需要明确地将它添加到你的 `plugins` [配置文件](/cms/configurations/plugins) 中,所以运行 [`develop command`](/cms/cli#strapi-develop) 来启动你的 Strapi 项目将自动获取你的插件。 ¥Because this plugin is installed via `node_modules` you won't need to explicity add it to your `plugins` [configuration file](/cms/configurations/plugins), so running the [`develop command`](/cms/cli#strapi-develop) to start your Strapi project will automatically pick up your plugin. 现在你的插件已链接到项目,请运行 `yarn develop` 或 `npm run develop` 以启动 Strapi 应用。 ¥Now that your plugin is linked to a project, run `yarn develop` or `npm run develop` to start the Strapi application. 你现在已经准备好按照你认为合适的方式开发你的插件了!如果你要进行服务器更改,则需要重新启动服务器才能使其生效。 ¥You are now ready to develop your plugin how you see fit! If you are making server changes, you will need to restart your server for them to take effect. ### 构建用于发布的插件 {#building-the-plugin-for-publishing} ¥Building the plugin for publishing 当你准备好发布插件时,你将需要构建它。为此,请运行以下命令: ¥When you are ready to publish your plugin, you will need to build it. To do this, run the following command: 上述命令不仅会构建插件,还会验证输出是否有效并准备好发布。然后,你可以像发布任何其他包一样将插件发布到 NPM。 ¥The above commands will not only build the plugin, but also verify that the output is valid and ready to be published. You can then publish your plugin to NPM as you would any other package. ## 在 monorepo 环境中使用插件 SDK {#monorepo} ¥Working with the Plugin SDK in a monorepo environment 如果你使用 monorepo 环境来开发插件,则不需要使用 `watch:link` 命令,因为 monorepo 工作区设置将处理符号链接。你可以改用 `watch` 命令。 ¥If you are working with a monorepo environment to develop your plugin, you don't need to use the `watch:link` command because the monorepo workspace setup will handle the symlink. You can use the `watch` command instead. 但是,如果你正在编写管理代码,则可以添加一个针对插件源代码的 `alias`,以便更轻松地在管理面板上下文中使用: ¥However, if you are writing admin code, you might add an `alias` that targets the source code of your plugin to make it easier to work with within the context of the admin panel: ```ts config.resolve.alias = { ...config.resolve.alias, 'my-strapi-plugin': path.resolve( __dirname, // We've assumed the plugin is local. '../plugins/my-strapi-plugin/admin/src' ), }; return config; }; ``` :::caution 提醒 因为服务器会查看 `server/src/index.ts|js` 文件来导入你的插件代码,所以你必须使用 `watch` 命令,否则代码将不会被转译,服务器将无法找到你的插件。 ¥Because the server looks at the `server/src/index.ts|js` file to import your plugin code, you must use the `watch` command otherwise the code will not be transpiled and the server will not be able to find your plugin. ::: ### 使用本地插件的配置 {#configuration-with-a-local-plugin} ¥Configuration with a local plugin 由于插件 SDK 主要用于开发插件,而不是本地开发,因此需要手动调整本地插件的配置。 ¥Since the Plugin SDK is primarily designed for developing plugins, not locally, the configuration needs to be adjusted manually for local plugins. 在本地开发插件时(使用 `@strapi/sdk-plugin`),插件配置文件如下例所示: ¥When developing your plugin locally (using `@strapi/sdk-plugin`), your plugins configuration file looks like in the following example: ```js title="/config/plugins.js|ts" myplugin: { enabled: true, resolve: `./src/plugins/local-plugin`, }, ``` 但是,此设置有时会导致以下错误: ¥However, this setup can sometimes lead to errors such as the following: ```js Error: 'X must be used within StrapiApp'; ``` 此错误通常发生在你的插件尝试导入核心 Strapi 功能时,例如使用: ¥This error often occurs when your plugin attempts to import core Strapi functionality, for example using: ```js ``` 要解决此问题,请从插件中删除 `@strapi/strapi` 作为开发依赖。这可确保你的插件使用与主应用相同的 Strapi 核心模块实例,从而防止冲突和相关错误。 ¥To resolve the issue, remove `@strapi/strapi` as a dev dependency from your plugin. This ensures that your plugin uses the same instance of Strapi’s core modules as the main application, preventing conflicts and the associated errors. ## 在没有插件 SDK 的情况下在 monorepo 环境中设置本地插件 {#setting-a-local-plugin-in-a-monorepo-environment-without-the-plugin-sdk} ¥Setting a local plugin in a monorepo environment without the Plugin SDK 在 monorepo 中,你可以通过在插件根目录添加 2 个入口点文件来配置本地插件,而无需使用插件 SDK: ¥In a monorepo, you can configure your local plugin without using the Plugin SDK by adding 2 entry point files at the root of your plugin: * 服务器入口点:`strapi-server.js|ts` ¥server entry point: `strapi-server.js|ts` * 管理员入口点:`strapi-admin.js|ts` ¥admin entry point: `strapi-admin.js|ts` ### 服务器入口点 {#server-entry-point} ¥Server entry point 服务器入口点文件初始化插件的服务器端功能。`strapi-server.js`(或其 TypeScript 变体)的预期结构是: ¥The server entry point file initializes your plugin’s server-side functionalities. The expected structure for `strapi-server.js` (or its TypeScript variant) is: ```js module.exports = () => { return { register, config, controllers, contentTypes, routes, }; }; ``` 在这里,你导出一个函数,该函数返回插件的核心组件,例如控制器、路由和配置。有关更多详细信息,请参阅 [服务器 API 参考](/cms/plugins-development/server-api)。 ¥Here, you export a function that returns your plugin's core components such as controllers, routes, and configuration. For more details, please refer to the [Server API reference](/cms/plugins-development/server-api). ### 管理入口点 {#admin-entry-point} ¥Admin entry point 管理员入口点文件在 Strapi 管理面板中设置你的插件。`strapi-admin.js`(或其 TypeScript 变体)的预期结构是: ¥The admin entry point file sets up your plugin within the Strapi admin panel. The expected structure for `strapi-admin.js` (or its TypeScript variant) is: ```js register(app) {}, bootstrap() {}, registerTrads({ locales }) {}, }; ``` 此对象包括使用管理应用注册插件、执行引导操作和处理翻译的方法。有关更多详细信息,请参阅 [管理面板 API 参考](/cms/plugins-development/admin-panel-api)。 ¥This object includes methods to register your plugin with the admin application, perform bootstrapping actions, and handle translations. For more details, please refer to the [Admin Panel API reference](/cms/plugins-development/admin-panel-api). :::tip 提示 有关如何在 monorepo 环境中构建本地插件的完整示例,请查看我们的 。 ¥For a complete example of how to structure your local plugin in a monorepo environment, please check out our . ::: # 开发插件 Source: https://docs.strapi.io/cms/plugins-development/developing-plugins # 开发 Strapi 插件 {#developing-strapi-plugins} ¥Developing Strapi plugins Strapi 允许开发与 :::strapi 自定义字段插件 插件也可用于将 [自定义字段](/cms/features/custom-fields) 添加到 Strapi。 ¥Plugins can also be used to add [custom fields](/cms/features/custom-fields) to Strapi. ::: ## 指南 {#guides} ¥Guides
:::strapi 其他资源 还可以包含在开发 Strapi 插件时有用的其他信息。 ¥The can also include additional information useful while developing a Strapi plugin. ::: # 如何从插件创建管理员权限 Source: https://docs.strapi.io/cms/plugins-development/guides/admin-permissions-for-plugins # 如何从插件创建管理员权限 {#how-to-create-admin-permissions-from-plugins} ¥How to create admin permissions from plugins 使用 [开发 Strapi 插件](/cms/plugins-development/developing-plugins) 时,你可能需要为你的插件创建管理员权限。通过这种方式,你可以接入 Strapi 的 [基于角色的访问控制 (RBAC) 系统](/cms/features/rbac),从而有选择地授予插件特定部分的权限。 ¥When [developing a Strapi plugin](/cms/plugins-development/developing-plugins), you might want to create admin permissions for your plugin. By doing that you can hook in to the [RBAC system](/cms/features/rbac) of Strapi to selectively grant permissions to certain pieces of your plugin. 要为你的 Strapi 插件创建管理员权限,你需要在服务器端注册这些权限,然后再在管理端实现它们。 ¥To create admin permissions for your Strapi plugin, you'll need to register them on the server side before implementing them on the admin side. ## 在服务器端注册权限 {#register-the-permissions-server-side} ¥Register the permissions server side 每个单独的权限都必须在插件的引导函数中注册,如下所示: ¥Each individual permission has to registered in the bootstrap function of your plugin, as follows: ## 在管理面板端实现权限 {#implement-permissions-on-the-admin-panel-side} ¥Implement permissions on the admin panel side 在管理面板端实现权限之前,我们必须在可重用的配置文件中定义它们。此文件可以存储在插件管理代码中的任何位置。你可以按如下方式操作: ¥Before we can implement our permissions on the admin panel side we have to define them in a reusable configuration file. This file can be stored anywhere in your plugin admin code. You can do that as follows: ```js title="/src/plugins/my-plugin/admin/src/permissions.js|ts" const pluginPermissions = { 'accessOverview': [{ action: 'plugin::my-plugin.overview.access', subject: null }], 'accessSidebar': [{ action: 'plugin::my-plugin.sidebar.access', subject: null }], }; ``` ### 页面权限 {#page-permissions} ¥Page permissions 创建配置文件后,即可开始实现权限设置。如果你已使用 [插件 SDK 初始化命令](/cms/plugins-development/plugin-sdk#npx-strapisdk-plugin-init) 引导插件,则会得到一个示例 `HomePage.tsx` 文件。要实现页面权限,你可以执行以下操作: ¥Once you've created the configuration file you are ready to implement your permissions. If you've bootstrapped your plugin using the [plugin SDK init command](/cms/plugins-development/plugin-sdk#npx-strapisdk-plugin-init), you will have an example `HomePage.tsx` file. To implement page permissions you can do the following: ```js title="/src/plugins/my-plugin/admin/src/pages/HomePage.jsx|tsx" {2,5,12,16} const HomePage = () => { const { formatMessage } = useIntl(); return ( ); }; ``` 你可以查看我们如何将权限配置文件与 `` 组件结合使用,以要求特定权限才能查看此页面。 ¥You can see how we use our permissions configuration file together with the `` component to require specific permissions in order to view this page. ### 菜单链接权限 {#menu-link-permissions} ¥Menu link permissions 前面的示例确保对直接访问你页面的用户的权限进行验证。你可能还需要移除指向该页面的菜单链接。为此,你需要对 `addMenuLink` 的实现进行更改。你可以按如下方式操作: ¥The previous example makes sure that the permissions of a user that visits your page directly will be validated. However, you might want to remove the menu link to that page as well. To do that, you'll have to make a change to the `addMenuLink` implementation. You can do as follows: ```js title="/src/plugins/my-plugin/admin/src/index.js|ts" {21-23,5} register(app) { app.addMenuLink({ to: `plugins/${PluginIcon}`, icon: PluginIcon, intlLabel: { id: `${PLUGIN_ID}.plugin.name`, defaultMessage: PLUGIN_ID, }, Component: async () => { const { App } = await import('./pages/App'); return App; }, permissions: [ pluginPermissions.accessOverview[0], ], }); app.registerPlugin({ id: PLUGIN_ID, initializer: Initializer, isReady: false, name: PLUGIN_ID, }); }, }; ``` ### 使用 `useRBAC` hook 自定义权限 {#custom-permissions-with-the-userbac-hook} ¥Custom permissions with the `useRBAC` hook 要更精细地控制管理员用户的权限,可以使用 `useRBAC` hook。使用此钩子,你可以像以下示例一样使用权限验证: ¥To get even more control over the permission of the admin user you can use the `useRBAC` hook. With this hook you can use the permissions validation just like you want, as in the following example: ```js title="/src/plugins/my-plugin/admin/src/components/Sidebar.jsx|tsx" const Sidebar = () => { const { allowedActions: { canAccessSidebar }, } = useRBAC(pluginPermissions); if (!canAccessSidebar) { return null; } return (
Sidebar component
); }; ``` # 如何为 Strapi 插件创建组件 Source: https://docs.strapi.io/cms/plugins-development/guides/create-components-for-plugins # 如何为 Strapi 插件创建组件 {#how-to-create-components-for-strapi-plugins} ¥How to create components for Strapi plugins 当 [开发 Strapi 插件](/cms/plugins-development/developing-plugins) 时,你可能希望为你的插件创建可重用的组件。Strapi 中的组件是可重复使用的数据结构,可用于不同的内容类型。 ¥When [developing a Strapi plugin](/cms/plugins-development/developing-plugins), you might want to create reusable components for your plugin. Components in Strapi are reusable data structures that can be used across different content-types. 要为 Strapi 插件创建组件,你需要遵循与创建内容类型类似的方法,但有一些具体的区别。 ¥To create components for your Strapi plugin, you'll need to follow a similar approach to creating content-types, but with some specific differences. ## 创建组件 {#creating-components} ¥Creating components 你可以通过两种不同的方式为你的插件创建组件:使用内容类型生成器(推荐方式)或手动。 ¥You can create components for your plugins in 2 different ways: using the Content-Type Builder (recommended way) or manually. ### 使用内容类型构建器 {#using-the-content-type-builder} ¥Using the Content-Type Builder 建议通过管理面板中的 Content-Type Builder 为插件创建组件。[内容类型生成器文档](/cms/features/content-type-builder#new-component) 提供了有关此过程的更多详细信息。 ¥The recommended way to create components for your plugin is through the Content-Type Builder in the admin panel. The [Content-Type Builder documentation](/cms/features/content-type-builder#new-component) provides more details on this process. ### 手动创建组件 {#creating-components-manually} ¥Creating components manually 如果你更喜欢手动创建组件,则需要: ¥If you prefer to create components manually, you'll need to: 1. 在插件结构中创建组件模式。 ¥Create a component schema in your plugin's structure. 2. 确保组件已正确注册。 ¥Make sure the component is properly registered. 插件的组件应放在插件结构中的相应目录中。你通常会在插件的服务器部分中创建它们(参见 [插件结构文档](/cms/plugins-development/plugin-structure))。 ¥Components for plugins should be placed in the appropriate directory within your plugin structure. You would typically create them within the server part of your plugin (see [plugin structure documentation](/cms/plugins-development/plugin-structure)). 有关 Strapi 中组件的更多详细信息,你可以参考 [模型属性文档](/cms/backend-customization/models#components-json)。 ¥For more detailed information about components in Strapi, you can refer to the [Model attributes documentation](/cms/backend-customization/models#components-json). ## 查看组件结构 {#reviewing-the-component-structure} ¥Reviewing the component structure Strapi 中的组件在定义中遵循以下格式: ¥Components in Strapi follow the following format in their definition: ```javascript title="/my-plugin/server/components/category/component-name.json" { "attributes": { "myComponent": { "type": "component", "repeatable": true, "component": "category.componentName" } } } ``` ## 使组件在管理面板中可见 {#making-components-visible-in-the-admin-panel} ¥Making components visible in the admin panel 为了确保你的插件组件在管理面板中可见,你需要在组件架构中设置适当的 `pluginOptions`: ¥To ensure your plugin's components are visible in the admin panel, you need to set the appropriate `pluginOptions` in your component schema: ```javascript {9-16} { "kind": "collectionType", "collectionName": "my_plugin_components", "info": { "singularName": "my-plugin-component", "pluralName": "my-plugin-components", "displayName": "My Plugin Component" }, "pluginOptions": { "content-manager": { "visible": true }, "content-type-builder": { "visible": true } }, "attributes": { "name": { "type": "string" } } } ``` 此配置确保你的组件在内容类型构建器和内容管理器中都可见且可编辑。 ¥This configuration ensures your components will be visible and editable in both the Content-Type Builder and Content Manager. # 如何使用 Strapi 插件将数据从服务器传递到管理面板 Source: https://docs.strapi.io/cms/plugins-development/guides/pass-data-from-server-to-admin # 如何使用 Strapi 插件将数据从服务器传递到管理面板 {#how-to-pass-data-from-server-to-admin-panel-with-a-strapi-plugin} ¥How to pass data from server to admin panel with a Strapi plugin Strapi 是无头的 。管理面板与服务器完全分开。 ¥Strapi is **headless** . The admin panel is completely separate from the server. 当 [开发 Strapi 插件](/cms/plugins-development/developing-plugins) 时,你可能希望将数据从 `/server` 传递到 `/admin` 文件夹。在 `/server` 文件夹中,你可以访问 Strapi 对象并可以执行数据库查询,而在 `/admin` 文件夹中则不能。 ¥When [developing a Strapi plugin](/cms/plugins-development/developing-plugins) you might want to pass data from the `/server` to the `/admin` folder. Within the `/server` folder you have access to the Strapi object and can do database queries whereas in the `/admin` folder you can't. 可以使用管理面板的 Axios 实例将数据从 `/server` 传递到 `/admin` 文件夹: ¥Passing data from the `/server` to the `/admin` folder can be done using the admin panel's Axios instance: ¥ 要将数据从 `/server` 传递到 `/admin` 文件夹,你需要先传递 [创建自定义管理路由](#create-a-custom-admin-route),然后传递 [获取管理面板返回的数据](#get-the-data-in-the-admin-panel)。 ¥To pass data from the `/server` to `/admin` folder you would first [create a custom admin route](#create-a-custom-admin-route) and then [get the data returned in the admin panel](#get-the-data-in-the-admin-panel). ## 创建自定义管理路由 {#create-a-custom-admin-route} ¥Create a custom admin route 管理路由类似于任何控制器的路由,除了 `type: 'admin'` 声明将它们隐藏在通用 API 路由之外,并允许你从管理面板访问它们。 ¥Admin routes are like the routes that you would have for any controller, except that the `type: 'admin'` declaration hides them from the general API router, and allows you to access them from the admin panel. 以下代码将为 `my-plugin` 插件声明自定义管理路由: ¥The following code will declare a custom admin route for the `my-plugin` plugin: ```js title="/my-plugin/server/routes/index.js" module.exports = { 'pass-data': { type: 'admin', routes: [ { method: 'GET', path: '/pass-data', handler: 'myPluginContentType.index', config: { policies: [], auth: false, }, }, ] } // ... }; ``` 当你向 `/my-plugin/pass-data` URL 端点发送 GET 请求时,此路由将调用 `myPluginContentType` 控制器的 `index` 方法。 ¥This route will call the `index` method of the `myPluginContentType` controller when you send a GET request to the `/my-plugin/pass-data` URL endpoint. 让我们创建一个基本的自定义控制器,它只返回一个简单的文本: ¥Let's create a basic custom controller that simply returns a simple text: ```js title="/my-plugin/server/controllers/my-plugin-content-type.js" 'use strict'; module.exports = { async index(ctx) { ctx.body = 'You are in the my-plugin-content-type controller!'; } } ``` 这意味着,当向 `/my-plugin/pass-data` URL 端点发送 GET 请求时,你应该获得随响应返回的 `You are in the my-plugin-content-type controller!` 文本。 ¥This means that when sending a GET request to the `/my-plugin/pass-data` URL endpoint, you should get the `You are in the my-plugin-content-type controller!` text returned with the response. ## 获取管理面板中的数据 {#get-the-data-in-the-admin-panel} ¥Get the data in the admin panel 从管理面板组件发送到我们定义自定义路由 `/my-plugin/pass-data` 的端点的任何请求现在都应该返回自定义控制器返回的文本消息。 ¥Any request sent from an admin panel component to the endpoint for which we defined the custom route `/my-plugin/pass-data` should now return the text message returned by the custom controller. 例如,如果你创建 `/admin/src/api/foobar.js` 文件并复制并粘贴以下代码示例: ¥So for instance, if you create an `/admin/src/api/foobar.js` file and copy and paste the following code example: ```js title="/my-plugin/admin/src/api/foobar.js" const foobarRequests = { getFoobar: async () => { const data = await axios.get(`/my-plugin/pass-data`); return data; }, }; ``` 你将能够在管理面板组件的代码中使用 `foobarRequests.getFoobar()` 并让它返回带有数据的 `You are in the my-plugin-content-type controller!` 文本。 ¥You will be able to use `foobarRequests.getFoobar()` in the code of an admin panel component and have it return the `You are in the my-plugin-content-type controller!` text with the data. 例如,在 React 组件中,你可以在组件初始化后使用 `useEffect` 来获取数据: ¥For instance, within a React component, you could use `useEffect` to get the data after the component initializes: ```js title="/my-plugin/admin/src/components/MyComponent/index.js" const [foobar, setFoobar] = useState([]); // … useEffect(() => { foobarRequests.getFoobar().then(res => { setSchemas(res.data); }); }, [setFoobar]); // … ``` 这将在组件状态的 `foobar` 数据中设置 `You are in the my-plugin-content-type controller!` 文本。 ¥This would set the `You are in the my-plugin-content-type controller!` text within the `foobar` data of the component's state. # 如何从 Strapi 插件存储和访问数据 Source: https://docs.strapi.io/cms/plugins-development/guides/store-and-access-data # 如何从 Strapi 插件存储和访问数据 {#how-to-store-and-access-data-from-a-strapi-plugin} ¥How to store and access data from a Strapi plugin 生成器 CLI 是交互式的,会询问一些有关内容类型及其包含的属性的问题。回答第一个问题,然后对于 `Where do you want to add this model?` 问题,选择 `Add model to existing plugin` 选项并在询问时输入相关插件的名称。 ¥The generator CLI is interactive and asks a few questions about the content-type and the attributes it will contain. Answer the first questions, then for the `Where do you want to add this model?` question, choose the `Add model to existing plugin` option and type the name of the related plugin when asked.
Generating a content-type plugin with the CLI
The strapi generate content-type CLI generator is used to create a basic content-type for a plugin.

CLI 将生成一些使用你的插件所需的代码,其中包括以下内容: ¥The CLI will generate some code required to use your plugin, which includes the following: * [内容类型模式](/cms/backend-customization/models#model-schema) 号 ¥the [content-type schema](/cms/backend-customization/models#model-schema) * 以及内容类型的基本 [controller](/cms/backend-customization/controllers)、[service](/cms/backend-customization/services) 和 [route](/cms/backend-customization/routes) ¥and a basic [controller](/cms/backend-customization/controllers), [service](/cms/backend-customization/services), and [route](/cms/backend-customization/routes) for the content-type :::tip 提示 你可能希望完全使用 CLI 生成器或直接创建和编辑 `schema.json` 文件来创建内容类型的整个结构。我们建议你首先使用 CLI 生成器创建一个简单的内容类型,然后利用管理面板中的 [内容类型生成器](/cms/features/content-type-builder) 来编辑你的内容类型。 ¥You may want to create the whole structure of your content-types either entirely with the CLI generator or by directly creating and editing `schema.json` files. We recommend you first create a simple content-type with the CLI generator and then leverage the [Content-Type Builder](/cms/features/content-type-builder) in the admin panel to edit your content-type. 如果你的内容类型在管理面板中不可见,你可能需要在内容类型架构的 `pluginOptions` 对象中将 `content-manager.visible` 和 `content-type-builder.visible` 参数设置为 `true`: ¥If your content-type is not visible in the admin panel, you might need to set the `content-manager.visible` and `content-type-builder.visible` parameters to `true` in the `pluginOptions` object of the content-type schema:
Making a plugin content-type visible in the admin panel: 示例 `schema.json` 文件中的以下高亮的行显示了如何使插件内容类型对内容类型生成器和内容管理器可见: ¥The following highlighted lines in an example `schema.json` file show how to make a plugin content-type visible to the Content-Type Builder and Content-Manager: ```json title="/server/content-types/my-plugin-content-type/schema.json" {13-20} showLineNumbers { "kind": "collectionType", "collectionName": "my_plugin_content_types", "info": { "singularName": "my-plugin-content-type", "pluralName": "my-plugin-content-types", "displayName": "My Plugin Content-Type" }, "options": { "draftAndPublish": false, "comment": "" }, "pluginOptions": { "content-manager": { "visible": true }, "content-type-builder": { "visible": true } }, "attributes": { "name": { "type": "string" } } } ```
::: ### 确保导入插件内容类型 {#ensure-plugin-content-types-are-imported} ¥Ensure plugin content-types are imported CLI 生成器可能尚未导入插件的所有相关内容类型文件,因此你可能需要在 `strapi generate content-type` CLI 命令完成运行后进行以下调整: ¥The CLI generator might not have imported all the related content-type files for your plugin, so you might have to make the following adjustments after the `strapi generate content-type` CLI command has finished running: 1. 在 `/server/index.js` 文件中,导入内容类型: ¥In the `/server/index.js` file, import the content-types: ```js {7,22} showLineNumbers title="/server/index.js" 'use strict'; const register = require('./register'); const bootstrap = require('./bootstrap'); const destroy = require('./destroy'); const config = require('./config'); const contentTypes = require('./content-types'); const controllers = require('./controllers'); const routes = require('./routes'); const middlewares = require('./middlewares'); const policies = require('./policies'); const services = require('./services'); module.exports = { register, bootstrap, destroy, config, controllers, routes, services, contentTypes, policies, middlewares, }; ``` 2. 在 `/server/content-types/index.js` 文件中,导入内容类型文件夹: ¥In the `/server/content-types/index.js` file, import the content-type folder: ```js title="/server/content-types/index.js" 'use strict'; module.exports = { // In the line below, replace my-plugin-content-type // with the actual name and folder path of your content type "my-plugin-content-type": require('./my-plugin-content-type'), }; ``` 3. 确保 `/server/content-types/[your-content-type-name]` 文件夹不仅包含 CLI 生成的 `schema.json` 文件,还包含导出内容类型的 `index.js` 文件,代码如下: ¥Ensure that the `/server/content-types/[your-content-type-name]` folder contains not only the `schema.json` file generated by the CLI, but also an `index.js` file that exports the content-type with the following code: ```js title="/server/content-types/my-plugin-content-type/index.js 'use strict'; const schema = require('./schema'); module.exports = { schema, }; ``` ## 与插件中的数据交互 {#interact-with-data-from-the-plugin} ¥Interact with data from the plugin 为插件创建内容类型后,你可以创建、读取、更新和删除数据。 ¥Once you have created a content-type for your plugin, you can create, read, update, and delete data. :::note 注意 插件只能与 `/server` 文件夹中的数据交互。如果你需要从管理面板更新数据,请参阅 [传递数据指南](/cms/plugins-development/guides/pass-data-from-server-to-admin)。 ¥A plugin can only interact with data from the `/server` folder. If you need to update data from the admin panel, please refer to the [passing data guide](/cms/plugins-development/guides/pass-data-from-server-to-admin). ::: 要创建、读取、更新和删除数据,你可以使用 [实体服务 API](/cms/api/entity-service) 或 [查询引擎 API](/cms/api/query-engine)。虽然建议使用实体服务 API,特别是当你需要访问组件或动态区域时,但如果你需要不受限制地访问底层数据库,则查询引擎 API 会很有用。 ¥To create, read, update, and delete data, you can use either the [Entity Service API](/cms/api/entity-service) or the [Query Engine API](/cms/api/query-engine). While it's recommended to use the Entity Service API, especially if you need access to components or dynamic zones, the Query Engine API is useful if you need unrestricted access to the underlying database. 在实体服务和查询引擎 API 查询中使用 `plugin::your-plugin-slug.the-plugin-content-type-name` 语法作为内容类型标识符。 ¥Use the `plugin::your-plugin-slug.the-plugin-content-type-name` syntax for content-type identifiers in Entity Service and Query Engine API queries. **示例:** ¥**Example:** 以下是如何查找为名为 `my-plugin` 的插件创建的 `my-plugin-content-type` 集合类型的所有条目: ¥Here is how to find all the entries for the `my-plugin-content-type` collection type created for a plugin called `my-plugin`: ```js // Using the Document Service API let data = await strapi.documents('plugin::my-plugin.my-plugin-content-type').findMany(); // Using the Query Engine API let data = await strapi.db.query('plugin::my-plugin.my-plugin-content-type').findMany(); ``` ` :::tip 提示 你可以通过 `strapi` 对象访问数据库,该对象可以在 `middlewares`、`policies`、`controllers`、`services` 以及 `register`、`boostrap`、`destroy` 生命周期函数中找到。 ¥You can access the database via the `strapi` object which can be found in `middlewares`, `policies`, `controllers`, `services`, as well as from the `register`, `boostrap`, `destroy` lifecycle functions. ::: # 插件 SDK Source: https://docs.strapi.io/cms/plugins-development/plugin-sdk # 插件 SDK 参考 {#plugin-sdk-reference} ¥Plugin SDK reference 插件 SDK 是包 提供的一组命令,旨在开发插件以将其用作本地插件或将其发布在 NPM 上和/或将其提交到市场。 ¥The Plugin SDK is set of commands provided by the package orientated around developing plugins to use them as local plugins or to publish them on NPM and/or submit them to the Marketplace. 本文档列出了可用的插件 SDK 命令。[相关指南](/cms/plugins-development/create-a-plugin) 说明了如何使用这些命令从头开始创建插件、将其链接到现有项目并发布它。 ¥The present documentation lists the available Plugin SDK commands. The [associated guide](/cms/plugins-development/create-a-plugin) illustrates how to use these commands to create a plugin from scratch, link it to an existing project, and publish it. ## npx @strapi/sdk-plugin init {#npx-strapisdk-plugin-init} 在给定路径创建一个新插件。 ¥Create a new plugin at a given path. ```bash npx @strapi/sdk-plugin init ``` | 参数 | 类型 | 描述 | 默认 | | ------ | :----: | ---- | ------------------------- | | `path` | string | 插件路径 | `./src/plugins/my-plugin` | | 选项 | 类型 | 描述 | 默认 | | ------------- | :-: | ------------- | ----- | | `-d, --debug` | * | 启用带有详细日志的调试模式 | false | | `--silent` | * | 不记录任何内容 | false | ## strapi-plugin build {#strapi-plugin-build} 打包 Strapi 插件以进行发布。 ¥Bundle the Strapi plugin for publishing. ```bash strapi-plugin build ``` | 选项 | 类型 | 描述 | 默认 | | -------------- | :----: | ------------------------------------- | ----- | | `--force` | string | 自动回答 "yes" 所有提示,包括潜在的破坏性请求,并以非交互方式运行。 | * | | `-d, --debug` | * | 启用带有详细日志的调试模式 | false | | `--silent` | * | 不记录任何内容 | false | | `--minify` | * | 缩小输出 | true | | `--sourcemaps` | * | 生成源映射 | false | ## strapi-plugin watch:link {#strapi-plugin-watchlink} 在更改时自动重新编译插件并运行 `yalc push --publish`。 ¥Recompiles the plugin automatically on changes and runs `yalc push --publish`. 出于测试目的,将你的插件链接到现有应用以在真实条件下进行试验非常方便。此命令旨在帮助你简化此过程。 ¥For testing purposes, it is very convenient to link your plugin to an existing application to experiment with it in real condition. This command is made to help you streamline this process. ```bash strapi-plugin watch:link ``` | 选项 | 类型 | 描述 | 默认 | | ------------- | :-: | ------------- | ----- | | `-d, --debug` | * | 启用带有详细日志的调试模式 | false | | `--silent` | * | 不记录任何内容 | false | ## strapi-plugin watch {#strapi-plugin-watch} 观察插件源代码是否有任何更改,并每次都重建它。在实现插件并在应用中测试它时很有用。 ¥Watch the plugin source code for any change and rebuild it everytime. Useful when implementing your plugin and testing it in an application. ```bash strapi-plugin watch ``` | 选项 | 类型 | 描述 | 默认 | | ------------- | :-: | ------------- | ----- | | `-d, --debug` | * | 启用带有详细日志的调试模式 | false | | `--silent` | * | 不记录任何内容 | false | ## strapi-plugin verify {#strapi-plugin-verify} 在发布插件之前验证插件的输出。 ¥Verify the output of the plugin before publishing it. ```bash strapi-plugin verify ``` | 选项 | 类型 | 描述 | 默认 | | ------------- | :-: | ------------- | ----- | | `-d, --debug` | * | 启用带有详细日志的调试模式 | false | | `--silent` | * | 不记录任何内容 | false | # 插件结构 Source: https://docs.strapi.io/cms/plugins-development/plugin-structure # 插件结构 {#plugin-structure} ¥Plugin structure 当 [使用插件 SDK 创建插件](/cms/plugins-development/create-a-plugin) 时,Strapi 会在 `/src/plugins/my-plugin` 文件夹中为你生成以下样板结构: ¥When [creating a plugin with Plugin SDK](/cms/plugins-development/create-a-plugin), Strapi generates the following boilerplate structure for you in the `/src/plugins/my-plugin` folder: Strapi 插件分为 2 部分,每个部分位于不同的文件夹中并提供不同的 API: ¥A Strapi plugin is divided into 2 parts, each living in a different folder and offering a different API: | 插件部分 | 描述 | 文件夹 | API | | ----- | ------------------------------------------------------------ | --------- | ---------------------------------------------------- | | 管理面板 | 包括 [管理面板](/cms/intro) 中可见的内容(组件、导航、设置等) | `admin/` | [管理面板 API](/cms/plugins-development/admin-panel-api) | | 后端服务器 | 包括与 [后端服务器](/cms/backend-customization) 相关的内容(内容类型、控制器、中间件等) | `server/` | [服务器 API](/cms/plugins-development/server-api) |
:::note 关于不同部分对于你的特定用例的有用性的说明 * 仅服务器插件:你可以创建一个仅使用服务器部分的插件来增强应用的 API。例如,这个插件可以有自己的可见或不可见的内容类型、控制器操作和对特定用例有用的路由。在这种情况下,你不需要插件在管理面板中具有界面。 ¥**Server-only plugin**: You can create a plugin that will just use the server part to enhance the API of your application. For instance, this plugin could have its own visible or invisible content-types, controller actions, and routes that are useful for a specific use case. In such a scenario, you don't need your plugin to have an interface in the admin panel. * 管理面板插件与特定于应用的定制:你可以创建一个插件来将一些组件注入管理面板。但是,你也可以通过创建 `/src/admin/index.js` 文件并调用 `bootstrap` 生命周期函数来注入组件来实现此目的。在这种情况下,决定是否创建插件取决于你是否计划重用和分发代码,或者它是否仅对独特的 Strapi 应用有用。 ¥**Admin panel plugin vs. application-specific customization**: You can create a plugin to inject some components into the admin panel. However, you can also achieve this by creating a `/src/admin/index.js` file and invoking the `bootstrap` lifecycle function to inject your components. In this case, deciding whether to create a plugin depends on whether you plan to reuse and distribute the code or if it's only useful for a unique Strapi application. :::
:::strapi 接下来读什么? Strapi 插件开发之旅的下一步将要求你使用任何 Strapi 插件 API。 ¥The next steps of your Strapi plugin development journey will require you to use any of the Strapi plugins APIs. 2 种不同类型的资源可帮助你了解如何使用插件 API: ¥2 different types of resources help you understand how to use the plugin APIs: * [管理面板 API](/cms/plugins-development/admin-panel-api) 和 [服务器 API](/cms/plugins-development/server-api) 的参考文档概述了 Strapi 插件的功能。 ¥The reference documentation for the [Admin Panel API](/cms/plugins-development/admin-panel-api) and [Server API](/cms/plugins-development/server-api) give an overview of what is possible to do with a Strapi plugin. * [指南](/cms/plugins-development/developing-plugins#guides) 涵盖了一些特定的、基于用例的示例。 ¥[Guides](/cms/plugins-development/developing-plugins#guides) cover some specific, use-case based examples. ::: # 插件扩展 Source: https://docs.strapi.io/cms/plugins-development/plugins-extension # 插件扩展 {#plugins-extension} ¥Plugins extension Strapi 附带可以从 [市场](/cms/plugins/installing-plugins-via-marketplace#installing-marketplace-plugins-and-providers) 或作为 npm 包安装的插件。你还可以创建自己的插件(参见 [插件开发](/cms/plugins-development/developing-plugins))或扩展现有插件。 ¥Strapi comes with plugins that can be installed from the [Marketplace](/cms/plugins/installing-plugins-via-marketplace#installing-marketplace-plugins-and-providers) or as npm packages. You can also create your own plugins (see [plugins development](/cms/plugins-development/developing-plugins)) or extend the existing ones. :::warning 警告 * 任何插件更新都可能会破坏该插件的扩展。 ¥Any plugin update could break this plugin's extensions. * Strapi 的新版本将在需要时发布迁移指南,但这些指南从不涵盖插件扩展。如果需要大量自定义,请考虑分叉插件。 ¥New versions of Strapi will be released with migration guides when required, but these guides never cover plugin extensions. Consider forking a plugin if extensive customizations are required. * 目前,插件的管理面板部分只能使用 进行扩展,但请考虑这样做可能会在 Strapi 的未来版本中破坏你的插件。 ¥Currently, the admin panel part of a plugin can only be extended using , but please consider that doing so might break your plugin in future versions of Strapi. ::: 插件扩展代码位于 `./src/extensions` 文件夹中(请参阅 [项目结构](/cms/project-structure))。有些插件会自动在那里创建文件以供修改。 ¥Plugin extensions code is located in the `./src/extensions` folder (see [project structure](/cms/project-structure)). Some plugins automatically create files there, ready to be modified.
Example of extensions folder structure ```bash /extensions /some-plugin-to-extend strapi-server.js|ts /content-types /some-content-type-to-extend model.json /another-content-type-to-extend model.json /another-plugin-to-extend strapi-server.js|ts ```
插件可以通过两种方式扩展: ¥Plugins can be extended in 2 ways: * [扩展插件的内容类型](#extending-a-plugins-content-types) ¥[extending the plugin's content-types](#extending-a-plugins-content-types) * [扩展插件的接口](#extending-a-plugins-interface)(例如添加控制器、服务、策略、中间件等) ¥[extending the plugin's interface](#extending-a-plugins-interface) (e.g. to add controllers, services, policies, middlewares and more) ## 扩展插件的内容类型 {#extending-a-plugins-content-types} ¥Extending a plugin's content-types 插件的内容类型可以通过两种方式扩展:使用 `strapi-server.js|ts` 内的编程接口并覆盖内容类型模式。 ¥A plugin's Content-Types can be extended in 2 ways: using the programmatic interface within `strapi-server.js|ts` and by overriding the content-types schemas. 内容类型的最终架构取决于以下加载顺序: ¥The final schema of the content-types depends on the following loading order: 1. 原始插件的内容类型, ¥the content-types of the original plugin, 2. 被 `./src/extensions/plugin-name/content-types/content-type-name/schema.json` 中定义的 [schema](/cms/backend-customization/models#model-schema) 中的声明覆盖的内容类型 ¥the content-types overridden by the declarations in the [schema](/cms/backend-customization/models#model-schema) defined in `./src/extensions/plugin-name/content-types/content-type-name/schema.json` 3. [从 `strapi-server.js|ts` 导出的 `content-types` 密钥](/cms/plugins-development/server-api#content-types) 中的内容类型声明 ¥the content-types declarations in the [`content-types` key exported from `strapi-server.js|ts`](/cms/plugins-development/server-api#content-types) 4. Strapi 应用 [`register()` 功能](/cms/configurations/functions#register) 中的内容类型声明 ¥the content-types declarations in the [`register()` function](/cms/configurations/functions#register) of the Strapi application 要覆盖插件的 [content-types](/cms/backend-customization/models): ¥To overwrite a plugin's [content-types](/cms/backend-customization/models): 1. (可选)如果该文件夹尚不存在,请在应用的根目录中创建 `./src/extensions` 文件夹。 ¥*(optional)* Create the `./src/extensions` folder at the root of the app, if the folder does not already exist. 2. 创建一个与要扩展的插件同名的子文件夹。 ¥Create a subfolder with the same name as the plugin to be extended. 3. 创建 `content-types` 子文件夹。 ¥Create a `content-types` subfolder. 4. 在 `content-types` 子文件夹内,创建另一个与 [singularName](/cms/backend-customization/models#model-information) 相同的子文件夹作为要覆盖的内容类型。 ¥Inside the `content-types` subfolder, create another subfolder with the same [singularName](/cms/backend-customization/models#model-information) as the content-type to overwrite. 5. 在此 `content-types/name-of-content-type` 子文件夹内,为 `schema.json` 文件中的内容类型定义新架构(请参阅 [schema](/cms/backend-customization/models#model-schema) 文档)。 ¥Inside this `content-types/name-of-content-type` subfolder, define the new schema for the content-type in a `schema.json` file (see [schema](/cms/backend-customization/models#model-schema) documentation). 6. (可选)对每个要覆盖的内容类型重复步骤 4 和 5。 ¥*(optional)* Repeat steps 4 and 5 for each content-type to overwrite. ## 扩展插件的接口 {#extending-a-plugins-interface} ¥Extending a plugin's interface 当 Strapi 应用初始化时,插件、扩展和全局生命周期函数事件按以下顺序发生: ¥When a Strapi application is initializing, plugins, extensions and global lifecycle functions events happen in the following order: 1. 插件已加载并公开其接口。 ¥Plugins are loaded and their interfaces are exposed. 2. 加载 `./src/extensions` 中的文件。 ¥Files in `./src/extensions` are loaded. 3. 调用 `./src/index.js|ts` 中的 `register()` 和 `bootstrap()` 函数。 ¥The `register()` and `bootstrap()` functions in `./src/index.js|ts` are called. 插件的接口可以在步骤 2(即在 `./src/extensions` 内)或步骤 3(即在 `./src/index.js|ts` 内)进行扩展。 ¥A plugin's interface can be extended at step 2 (i.e. within `./src/extensions`) or step 3 (i.e. inside `./src/index.js|ts`). :::note 注意 如果你的 Strapi 项目是基于 TypeScript 的,请确保 `index` 文件具有 TypeScript 扩展名(即 `src/index.ts`),否则将无法编译。 ¥If your Strapi project is TypeScript-based, please ensure that the `index` file has a TypeScript extension (i.e., `src/index.ts`) otherwise it will not be compiled. ::: ### 在扩展文件夹内 {#within-the-extensions-folder} ¥Within the extensions folder 要使用 `./src/extensions` 文件夹扩展插件的服务器接口: ¥To extend a plugin's server interface using the `./src/extensions` folder: 1. (可选)如果该文件夹尚不存在,请在应用的根目录中创建 `./src/extensions` 文件夹。 ¥*(optional)* Create the `./src/extensions` folder at the root of the app, if the folder does not already exist. 2. 创建一个与要扩展的插件同名的子文件夹。 ¥Create a subfolder with the same name as the plugin to be extended. 3. 创建 `strapi-server.js|ts` 文件以使用 [服务器 API](/cms/plugins-development/server-api) 扩展插件的后端。 ¥Create a `strapi-server.js|ts` file to extend a plugin's back end using the [Server API](/cms/plugins-development/server-api). 4. 在此文件中,定义并导出一个函数。该函数接收 `plugin` 接口作为参数,以便可以对其进行扩展。 ¥Within this file, define and export a function. The function receives the `plugin` interface as an argument so it can be extended.
Example of backend extension ```js title="./src/extensions/some-plugin-to-extend/strapi-server.js|ts" module.exports = (plugin) => { plugin.controllers.controllerA.find = (ctx) => {}; plugin.policies[newPolicy] = (ctx) => {}; plugin.routes['content-api'].routes.push({ method: 'GET', path: '/route-path', handler: 'controller.action', }); return plugin; }; ```
:::note 注意 你还可以在 `strapi-server.js|ts` 文件中覆盖图片函数,方法是替换上传插件的 `generateFileName()` 函数,使其生成自定义图片名称。 ¥The `strapi-server.js|ts` file is also where you can override the image function, by replacing the Upload plugin's `generateFileName()` function so that it generates custom image names.
Example of custom file-naming logic ```js title="./src/extensions/upload/strapi-server.js|ts" module.exports = (plugin) => { plugin.services.upload.image.generateFileName = (file) => { // Example: prefix a timestamp before the original name return `${Date.now()}_${file.hash}${file.ext}`; }; return plugin; }; ```
::: ### 在注册和引导函数内 {#within-the-register-and-bootstrap-functions} ¥Within the register and bootstrap functions 要在 `./src/index.js|ts` 内扩展插件的接口,请使用整个项目的 `bootstrap()` 和 `register()` [functions](/cms/configurations/functions),并使用 [getters](/cms/plugins-development/server-api#usage) 以编程方式访问该接口。 ¥To extend a plugin's interface within `./src/index.js|ts`, use the `bootstrap()` and `register()` [functions](/cms/configurations/functions) of the whole project, and access the interface programmatically with [getters](/cms/plugins-development/server-api#usage).
Example of extending a plugin's content-type within ./src/index.js|ts ```js title="./src/index.js|ts" module.exports = { register({ strapi }) { const contentTypeName = strapi.contentType('plugin::my-plugin.content-type-name') contentTypeName.attributes = { // Spread previous defined attributes ...contentTypeName.attributes, // Add new, or override attributes 'toto': { type: 'string', } } }, bootstrap({ strapi }) {}, }; ```
# 插件的服务器 API Source: https://docs.strapi.io/cms/plugins-development/server-api # 插件的服务器 API {#server-api-for-plugins} ¥Server API for plugins Strapi 插件可以与 Strapi 应用的后端和 [前端](/cms/plugins-development/admin-panel-api) 交互。服务器 API 与后端部分有关,即插件如何与 Strapi 应用的服务器部分交互。 ¥A Strapi plugin can interact with both the back end and the [front end](/cms/plugins-development/admin-panel-api) of a Strapi application. The Server API is about the back-end part, i.e. how the plugin interacts with the server part of a Strapi application. :::prerequisites 你有 [创建了一个 Strapi 插件](/cms/plugins-development/create-a-plugin)。 ¥You have [created a Strapi plugin](/cms/plugins-development/create-a-plugin). ::: 服务器 API 包括: ¥The Server API includes: * 导出所需接口的 [入口文件](#entry-file), ¥an [entry file](#entry-file) which export the required interface, * [生命周期函数](#lifecycle-functions), ¥[lifecycle functions](#lifecycle-functions), * [configuration](#configuration) API, * 和 [自定义后端服务器的所有元素](#backend-customization) 的能力。 ¥and the ability to [customize all elements of the back-end server](#backend-customization). 一旦你声明并导出了插件接口,你将能够 [使用插件接口](#usage)。 ¥Once you have declared and exported the plugin interface, you will be able to [use the plugin interface](#usage). :::note 注意 插件服务器部分的整个代码可以存在于 `/server/src/index.ts|js` 文件中。但是,建议将代码拆分到不同的文件夹中,就像插件 SDK 创建的 [structure](/cms/plugins-development/plugin-structure) 一样。 ¥The whole code for the server part of your plugin could live in the `/server/src/index.ts|js` file. However, it's recommended to split the code into different folders, just like the [structure](/cms/plugins-development/plugin-structure) created by the Plugin SDK. ::: ## 录入文件 {#entry-file} ¥Entry file 插件文件夹根目录下的 `/src/server/index.js` 文件导出所需的接口,并提供以下参数: ¥The `/src/server/index.js` file at the root of the plugin folder exports the required interface, with the following parameters available: | 参数类型 | 可用参数 | | ------ | ---- | | 生命周期函数 | | | 配置 | | | 后端定制 | | ## 生命周期函数 {#lifecycle-functions} ¥Lifecycle functions
### register() {#register} 在应用为 [bootstrapped](#bootstrap) 之前调用此函数来加载插件,以便注册 [permissions](/cms/features/users-permissions)、[自定义字段](/cms/features/custom-fields#registering-a-custom-field-on-the-server) 的服务器部分或数据库迁移。 ¥This function is called to load the plugin, before the application is [bootstrapped](#bootstrap), in order to register [permissions](/cms/features/users-permissions), the server part of [custom fields](/cms/features/custom-fields#registering-a-custom-field-on-the-server), or database migrations. 类型:`Function` ¥**Type**: `Function` **示例:** ¥**Example:** ### bootstrap() {#bootstrap} [bootstrap](/cms/configurations/functions#bootstrap) 函数在插件有 [registered](#register) 之后立即调用。 ¥The [bootstrap](/cms/configurations/functions#bootstrap) function is called right after the plugin has [registered](#register). 类型:`Function` ¥**Type**: `Function` **示例:** ¥**Example:** ### destroy() {#destroy} 当 Strapi 实例被销毁时,会调用 [destroy](/cms/configurations/functions#destroy) 生命周期函数来清理插件(关闭连接、删除监听器等)。 ¥The [destroy](/cms/configurations/functions#destroy) lifecycle function is called to cleanup the plugin (close connections, remove listeners, etc.) when the Strapi instance is destroyed. 类型:`Function` ¥**Type**: `Function` **示例:** ¥**Example:** ## 配置 {#configuration} ¥Configuration `config` 存储默认的插件配置。它加载并验证用户在 [`./config/plugins.js` 配置文件](/cms/configurations/plugins) 中输入的配置。 ¥`config` stores the default plugin configuration. It loads and validates the configuration inputted from the user within the [`./config/plugins.js` configuration file](/cms/configurations/plugins). 类型:`Object` ¥**Type**: `Object` | 范围 | 类型 | 描述 | | ----------- | ---------- | -------------- | | `default` | 对象或返回对象的函数 | 默认插件配置,与用户配置合并 | | `validator` | 函数 | | **示例:** ¥**Example:** 定义后,可以访问配置: ¥Once defined, the configuration can be accessed: * `strapi.plugin('plugin-name').config('some-key')` 表示特定配置属性, ¥with `strapi.plugin('plugin-name').config('some-key')` for a specific configuration property, * 或使用 `strapi.config.get('plugin::plugin-name')` 表示整个配置对象。 ¥or with `strapi.config.get('plugin::plugin-name')` for the whole configuration object. :::tip 提示 运行 `yarn strapi console` 或 `npm run strapi console` 以访问实时控制台中的 Strapi 对象。 ¥Run `yarn strapi console` or `npm run strapi console` to access the strapi object in a live console. ::: ## 后端定制 {#backend-customization} ¥Backend customization Strapi 后端服务器的所有元素都可以使用服务器 API 通过插件进行自定义。 ¥All elements of the back-end server of Strapi can be customized through a plugin using the Server API. :::prerequisites 为了更好地理解本节,请确保你已阅读 Strapi 应用的 [后端定制](/cms/backend-customization) 文档。 ¥To better understand this section, ensure you have read through the [back-end customization](/cms/backend-customization) documentation of a Strapi application. ::: ### 内容类型 {#content-types} ¥Content-types 插件提供的具有 [content-types](/cms/backend-customization/models) 的对象。 ¥An object with the [content-types](/cms/backend-customization/models) the plugin provides. 类型:`Object` ¥**Type**: `Object` :::note 注意 `contentTypes` 对象中的 Content-Types 键应重新使用架构的 [`info`](/cms/backend-customization/models#model-information) 键中定义的 `singularName`。 ¥Content-Types keys in the `contentTypes` object should re-use the `singularName` defined in the [`info`](/cms/backend-customization/models#model-information) key of the schema. ::: **示例:** ¥**Example:** ### 路由 {#routes} ¥Routes [routes](/cms/backend-customization/routes) 配置的数组。 ¥An array of [routes](/cms/backend-customization/routes) configuration. 类型:`Object[]` ¥**Type**: `Object[]` **示例:** ¥**Examples:** ### 控制器 {#controllers} ¥Controllers 插件提供的具有 [controllers](/cms/backend-customization/controllers) 的对象。 ¥An object with the [controllers](/cms/backend-customization/controllers) the plugin provides. 类型:`Object` ¥**Type**: `Object` **示例:** ¥**Example:** ### 服务 {#services} ¥Services 插件提供的具有 [services](/cms/backend-customization/services) 的对象。 ¥An object with the [services](/cms/backend-customization/services) the plugin provides. 服务应该是以 `strapi` 作为参数的函数。 ¥Services should be functions taking `strapi` as a parameter. 类型:`Object` ¥**Type**: `Object` **示例:** ¥**Example:** ### 政策 {#policies} ¥Policies 插件提供的具有 [policies](/cms/backend-customization/policies) 的对象。 ¥An object with the [policies](/cms/backend-customization/policies) the plugin provides. 类型:`Object` ¥**Type**: `Object` **示例:** ¥**Example:** ### 中间件 {#middlewares} ¥Middlewares 插件提供的具有 [middlewares](/cms/configurations/middlewares) 的对象。 ¥An object with the [middlewares](/cms/configurations/middlewares) the plugin provides. 类型:`Object` ¥**Type**: `Object` **示例:** ¥**Example:** ## 用法 {#usage} ¥Usage 一旦插件导出并加载到 Strapi 中,就可以通过 getter 在代码中访问其功能。Strapi 实例 (`strapi`) 公开顶层 getter 和全局 getter: ¥Once a plugin is exported and loaded into Strapi, its features are accessible in the code through getters. The Strapi instance (`strapi`) exposes both top-level getters and global getters: * 顶层获取器意味着链接函数
(例如,`strapi.plugin('the-plugin-name').controller('the-controller-name'`), ¥top-level getters imply chaining functions
(e.g., `strapi.plugin('the-plugin-name').controller('the-controller-name'`), * 全局 getter 是语法糖,允许使用功能的 uid
(例如 `strapi.controller('plugin::plugin-name.controller-name')`)直接访问。 ¥global getters are syntactic sugar that allows direct access using a feature's uid
(e.g., `strapi.controller('plugin::plugin-name.controller-name')`). ```js // Access an API or a plugin controller using a top-level getter strapi.api['api-name'].controller('controller-name') strapi.plugin('plugin-name').controller('controller-name') // Access an API or a plugin controller using a global getter strapi.controller('api::api-name.controller-name') strapi.controller('plugin::plugin-name.controller-name') ```
Top-level getter syntax examples ```js strapi.plugin('plugin-name').config strapi.plugin('plugin-name').routes strapi.plugin('plugin-name').controller('controller-name') strapi.plugin('plugin-name').service('service-name') strapi.plugin('plugin-name').contentType('content-type-name') strapi.plugin('plugin-name').policy('policy-name') strapi.plugin('plugin-name').middleware('middleware-name') ```
Global getter syntax examples ```js strapi.controller('plugin::plugin-name.controller-name'); strapi.service('plugin::plugin-name.service-name'); strapi.contentType('plugin::plugin-name.content-type-name'); strapi.policy('plugin::plugin-name.policy-name'); strapi.middleware('plugin::plugin-name.middleware-name'); ```
:::strapi 文档服务 API 要与内容类型交互,请使用 [文档服务 API](/cms/api/document-service)。 ¥To interact with the content-types, use the [Document Service API](/cms/api/document-service). ::: # 文档插件 Source: https://docs.strapi.io/cms/plugins/documentation # 文档插件 {#documentation-plugin} ¥Documentation plugin 文档插件可自动创建你的 API 文档。它基本上会生成一个 swagger 文件。它遵循 :::caution 未维护的插件 文档插件未主动维护,可能无法与 Strapi 5 兼容。 ¥The Documentation plugin is not actively maintained and may not work with Strapi 5. ::: 安装插件后,启动 Strapi 会生成 API 文档。 ¥Once the plugin is installed, starting Strapi generates the API documentation. ## 配置 {#configuration} ¥Configuration 文档插件的大多数配置选项都通过你的 Strapi 项目的代码处理。管理面板中提供了一些设置。 ¥Most configuration options for the Documentation plugin are handled via your Strapi project's code. A few settings are available in the admin panel. ### 管理面板设置 {#admin-panel-settings} ¥Admin panel settings 文档插件会影响管理面板的多个部分。下表列出了安装插件后添加到 Strapi 应用的所有附加选项和设置: ¥The Documentation plugin affects multiple parts of the admin panel. The following table lists all the additional options and settings that are added to a Strapi application once the plugin has been installed: | Section impacted | Options and settings | |------------------|-------------------------------------------------------------| | Documentation |
    Addition of a new Documentation option in the main navigation which shows a panel with buttons to open and regenerate the documentation.
| | Settings |
  • Addition of a "Documentation plugin" setting section, which controls whether the documentation endpoint is private or not (see [restricting access](#restrict-access)).
    👉 Path reminder: *Settings > Documentation plugin*

  • Activation of role based access control for accessing, updating, deleting, and regenerating the documentation. Administrators can authorize different access levels to different types of users in the *Plugins* tab and the *Settings* tab (see [Users & Permissions documentation](/cms/features/users-permissions)).
    👉 Path reminder: *Settings > Administration Panel > Roles*
| #### 限制对你的 API 文档的访问 {#restrict-access} ¥Restricting access to your API documentation 默认情况下,任何人都可以访问你的 API 文档。 ¥By default, your API documentation will be accessible by anyone. 要限制 API 文档访问,请从管理面板启用“受限访问”选项: ¥To restrict API documentation access, enable the **Restricted Access** option from the admin panel: 1. 在管理面板的主导航中导航到 设置。 ¥Navigate to *Settings* in the main navigation of the admin panel. 2. 选择文档。 ¥Choose **Documentation**. 3. 切换对 `ON` 的受限访问。 ¥Toggle **Restricted Access** to `ON`. 4. 在 `password` 输入中定义密码。 ¥Define a password in the `password` input. 5. 保存设置。 ¥Save the settings. ### 基于代码的配置 {#code-based-configuration} ¥Code-based configuration 要配置文档插件,请在 `src/extensions/documentation/config` 文件夹中创建一个 `settings.json` 文件。在此文件中,你可以指定所有环境变量、许可证、外部文档链接以及 中列出的所有条目。 ¥To configure the Documentation plugin, create a `settings.json` file in the `src/extensions/documentation/config` folder. In this file, you can specify all your environment variables, licenses, external documentation links, and all the entries listed in the . 以下是配置示例: ¥The following is an example configuration: ```json title="src/extensions/documentation/config/settings.json" { "openapi": "3.0.0", "info": { "version": "1.0.0", "title": "DOCUMENTATION", "description": "", "termsOfService": "YOUR_TERMS_OF_SERVICE_URL", "contact": { "name": "TEAM", "email": "contact-email@something.io", "url": "mywebsite.io" }, "license": { "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } }, "x-strapi-config": { "plugins": ["upload", "users-permissions"], "path": "/documentation" }, "servers": [ { "url": "http://localhost:1337/api", "description": "Development server" } ], "externalDocs": { "description": "Find out more", "url": "https://strapi.nodejs.cn/developer-docs/latest/getting-started/introduction.html" }, "security": [ { "bearerAuth": [] } ] } ``` :::tip 提示 如果你需要添加自定义密钥,请在其前面加上 `x-`(例如 `x-strapi-something`)。 ¥If you need to add a custom key, prefix it by `x-` (e.g., `x-strapi-something`). ::: #### 创建新版本的文档 {#create-a-new-version-of-the-documentation} ¥Creating a new version of the documentation 要创建新版本,请更改 `settings.json` 文件中的 `info.version` 键: ¥To create a new version, change the `info.version` key in the `settings.json` file: ```json title="src/extensions/documentation/config/settings.json" { "info": { "version": "2.0.0" } } ``` 这将自动创建一个新版本。 ¥This will automatically create a new version. #### 定义哪些插件需要生成文档 {#define-which-plugins} ¥Defining which plugins need documentation generated 如果你希望插件包含在文档生成中,则应将它们包含在 `x-strapi-config` 对象中的 `plugins` 数组中。默认情况下,数组使用 `["upload", "users-permissions"]` 初始化: ¥If you want plugins to be included in documentation generation, they should be included in the `plugins` array in the `x-strapi-config` object. By default, the array is initialized with `["upload", "users-permissions"]`: ```json title="src/extensions/documentation/config/settings.json" { "x-strapi-config": { "plugins": ["upload", "users-permissions"] } } ``` 要添加更多插件(例如你的自定义插件),请将其名称添加到数组中。 ¥To add more plugins, such as your custom plugins, add their name to the array. 如果你不希望插件包含在文档生成中,请提供一个空数组(即 `plugins: []`)。 ¥If you do not want plugins to be included in documentation generation, provide an empty array (i.e., `plugins: []`). #### 覆盖生成的文档 {#overriding-the-generated-documentation} ¥Overriding the generated documentation 文档插件有 3 种方法来覆盖生成的文档:[`excludeFromGeneration`](#excluding-from-generation)、[`registerOverride`](#register-override) 和 [`mutateDocumentation`](#mutate-documentation)。 ¥The Documentation plugins comes with 3 methods to override the generated documentation: [`excludeFromGeneration`](#excluding-from-generation), [`registerOverride`](#register-override), and [`mutateDocumentation`](#mutate-documentation). ##### excludeFromGeneration() {#excluding-from-generation} 要排除生成某些 API 或插件,请使用在应用或插件的 [`register` 生命周期](/cms/plugins-development/admin-panel-api#register) 中的文档插件的 `override` 服务中找到的 `excludeFromGeneration`。 ¥To exclude certain APIs or plugins from being generated, use the `excludeFromGeneration` found on the documentation plugin’s `override` service in your application or plugin's [`register` lifecycle](/cms/plugins-development/admin-panel-api#register). :::note 注意 `excludeFromGeneration` 对生成的内容提供了更细粒度的控制。 ¥`excludeFromGeneration` gives more fine-grained control over what is generated. 例如,pluginA 可能会创建几个新的 API,而 pluginB 可能只想为其中一些 API 生成文档。在这种情况下,pluginB 仍然可以通过仅排除不需要的内容来从它确实需要的生成文档中受益。 ¥For example, pluginA might create several new APIs while pluginB may only want to generate documentation for some of those APIs. In that case, pluginB could still benefit from the generated documentation it does need by excluding only what it does not need. ::: *** | 范围 | 类型 | 描述 | | ----- | --------- | ------------------- | | `api` | 字符串或字符串数组 | 要排除的 API/插件的名称或名称列表 | ```js title="Application or plugin register lifecycle" module.exports = { register({ strapi }) { strapi .plugin("documentation") .service("override") .excludeFromGeneration("restaurant"); // or several strapi .plugin("documentation") .service("override") .excludeFromGeneration(["address", "upload"]); } } ``` ##### registerOverride() {#register-override} 如果文档插件无法生成你期望的内容,则可以替换已生成的内容。 ¥If the Documentation plugin fails to generate what you expect, it is possible to replace what has been generated. 文档插件公开了一个 API,允许你替换为以下 OpenAPI 根级别密钥生成的内容:`paths`、`tags`、`components`。 ¥The Documentation plugin exposes an API that allows you to replace what was generated for the following OpenAPI root level keys: `paths`, `tags`, `components` . 要提供覆盖,请使用应用或插件的 [`register` 生命周期](/cms/plugins-development/admin-panel-api#register) 中文档插件的 `override` 服务上找到的 `registerOverride` 函数。 ¥To provide an override, use the `registerOverride` function found on the Documentation plugin’s `override` service in your application or plugin's [`register` lifecycle](/cms/plugins-development/admin-panel-api#register). | 范围 | 类型 | 描述 | | ------------------------------- | --------- | --------------------------------------------------- | | `override` | 目的 | OpenAPI 对象包括以下任意键路径、标签、组件。接受 JavaScript、JSON 或 yaml | | `options` | 目的 | 接受 `pluginOrigin` 和 `excludeFromGeneration` | | `options.pluginOrigin` | 字符串 | 正在注册覆盖的插件 | | `options.excludeFromGeneration` | 字符串或字符串数组 | 要排除的 API/插件的名称或名称列表 | :::caution 提醒 提供覆盖的插件开发者应始终指定 `pluginOrigin` 选项键。否则,无论用户的配置如何,覆盖都会运行。 ¥Plugin developers providing an override should always specify the `pluginOrigin` options key. Otherwise the override will run regardless of the user’s configuration. ::: 文档插件将使用注册的覆盖将生成的文档上的公共键值替换为覆盖提供的值。如果没有找到通用密钥,插件会将新密钥添加到生成的文档中。 ¥The Documentation plugin will use the registered overrides to replace the value of common keys on the generated documentation with what the override provides. If no common keys are found, the plugin will add new keys to the generated documentation. 如果覆盖完全替换了文档生成的内容,你可以通过提供要在选项键数组 `excludeFromGeneration` 中排除的 API 或插件的名称来指定不再需要生成。 ¥If the override completely replaces what the documentation generates, you can specify that generation is no longer necessary by providing the names of the APIs or plugins to exclude in the options key array `excludeFromGeneration`. 如果覆盖仅应用于特定版本,则覆盖必须包含 `info.version` 的值。否则,覆盖将在所有文档版本上运行。 ¥If the override should only be applied to a specific version, the override must include a value for `info.version`. Otherwise, the override will run on all documentation versions. ```js title="Application or plugin register lifecycle" module.exports = { register({ strapi }) { if (strapi.plugin('documentation')) { const override = { // Only run this override for version 1.0.0 info: { version: '1.0.0' }, paths: { '/answer-to-everything': { get: { responses: { 200: { description: "*" }} } } } } strapi .plugin('documentation') .service('override') .registerOverride(override, { // Specify the origin in case the user does not want this plugin documented pluginOrigin: 'upload', // The override provides everything don't generate anything excludeFromGeneration: ['upload'], }); } }, } ``` 提供覆盖系统是为了尝试并简化对生成的文档的修改。这是插件添加或修改生成的文档的唯一方法。 ¥The overrides system is provided to try and simplify amending the generated documentation. It is the only way a plugin can add or modify the generated documentation. ##### mutateDocumentation() {#mutate-documentation} 文档插件的配置还接受 `info['x-strapi-config']` 上的 `mutateDocumentation` 函数。此函数接收生成的文档的草稿状态,该文档可以进行更改。它只能从应用应用,并且在 OpenAPI 架构中拥有最终决定权。 ¥The Documentation plugin’s configuration also accepts a `mutateDocumentation` function on `info['x-strapi-config']`. This function receives a draft state of the generated documentation that be can be mutated. It should only be applied from an application and has the final say in the OpenAPI schema. | 范围 | 类型 | 描述 | | ----------------------------- | -- | ----------------- | | `generatedDocumentationDraft` | 目的 | 生成的文档应用了作为可变对象的覆盖 | ```js title="config/plugins.js" module.exports = { documentation: { config: { "x-strapi-config": { mutateDocumentation: (generatedDocumentationDraft) => { generatedDocumentationDraft.paths[ "/answer-to-everything" // must be an existing path ].get.responses["200"].description = "*"; }, }, }, }, }; ``` ## 用法 {#usage} ¥Usage 文档插件使用 可视化你的 API。要访问 UI,请在管理面板的主导航中选择 。然后单击“打开文档”以打开 Swagger UI。使用 Swagger UI,你可以查看 API 上可用的所有端点并触发 API 调用。 ¥The Documentation plugin visualizes your API using . To access the UI, select in the main navigation of the admin panel. Then click **Open documentation** to open the Swagger UI. Using the Swagger UI you can view all of the endpoints available on your API and trigger API calls. :::tip 提示 安装插件后,可以通过以下 URL 访问插件用户界面:`:/documentation/`(例如,)。 ¥Once the plugin is installed, the plugin user interface can be accessed at the following URL: `:/documentation/` (e.g., ). ::: ### 重新生成文档 {#regenerate-documentation} ¥Regenerating documentation 更改 API 后,有 2 种方法可以更新文档: ¥There are 2 ways to update the documentation after making changes to your API: * 重新启动你的应用以重新生成文档插件配置中指定的文档版本, ¥restart your application to regenerate the version of the documentation specified in the Documentation plugin's configuration, * 或者转到文档插件页面,然后单击你要重新生成的文档版本的重新生成按钮。 ¥or go to the Documentation plugin page and click the **regenerate** button for the documentation version you want to regenerate. ### 验证请求 {#authenticating-requests} ¥Authenticating requests Strapi 默认是安全的,这意味着你的大多数端点都需要用户获得授权。如果 [用户和权限功能](/cms/features/users-permissions#roles) 中的 CRUD 操作未设置为 Public,则必须提供 JSON Web 令牌 (JWT)。为此,在查看 API 文档时,单击授权按钮并将你的 JWT 粘贴到 bearerAuth 值字段中。 ¥Strapi is secured by default, which means that most of your endpoints require the user to be authorized. If the CRUD action has not been set to Public in the [Users & Permissions feature](/cms/features/users-permissions#roles) then you must provide your JSON web token (JWT). To do this, while viewing the API Documentation, click the **Authorize** button and paste your JWT in the *bearerAuth* *value* field. # GraphQL 插件 Source: https://docs.strapi.io/cms/plugins/graphql # GraphQL 插件 {#graphql-plugin} ¥GraphQL plugin 默认情况下,Strapi 为你的每种内容类型创建 [REST 端点](/cms/api/rest#endpoints)。GraphQL 插件添加了一个 GraphQL 端点来获取和修改你的内容。安装 GraphQL 插件后,你可以使用基于 Apollo Server 的 GraphQL Sandbox 以交互方式构建查询和修改,并阅读针对你的内容类型量身定制的文档。 ¥By default Strapi create [REST endpoints](/cms/api/rest#endpoints) for each of your content-types. The GraphQL plugin adds a GraphQL endpoint to fetch and mutate your content. With the GraphQL plugin installed, you can use the Apollo Server-based GraphQL Sandbox to interactively build your queries and mutations and read documentation tailored to your content types. 安装后,GraphQL 沙箱可通过 `/graphql` URL 访问,并可用于以交互方式构建查询和修改并阅读针对你的内容类型量身定制的文档。 ¥Once installed, the GraphQL sandbox 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. 安装插件后,当你的 Strapi 应用服务器运行时,可以通过 `/graphql` 路由(例如 #### 动态启用 Apollo Sandbox {#dynamically-enable-apollo-sandbox} ¥Dynamically enable Apollo Sandbox 你可以使用一个函数根据环境动态启用 Apollo Sandbox: ¥You can use a function to dynamically enable Apollo Sandbox depending on the environment: #### 着陆页的 CORS 例外 {#cors-exceptions-for-landing-page} ¥CORS exceptions for Landing Page 如果在生产环境中启用了登录页面(不推荐),则必须手动添加 Apollo Server 登录页面的 CORS 标头。 ¥If the landing page is enabled in production environments (which is not recommended), CORS headers for the Apollo Server landing page must be added manually. 要全局添加它们,你可以将以下内容合并到中间件配置中: ¥To add them globally, you can merge the following into your middleware configuration: ```javascript title="/config/middlewares" { name: "strapi::security", config: { contentSecurityPolicy: { useDefaults: true, directives: { "connect-src": ["'self'", "https:", "apollo-server-landing-page.cdn.apollographql.com"], "img-src": ["'self'", "data:", "blob:", "apollo-server-landing-page.cdn.apollographql.com"], "script-src": ["'self'", "'unsafe-inline'", "apollo-server-landing-page.cdn.apollographql.com"], "style-src": ["'self'", "'unsafe-inline'", "apollo-server-landing-page.cdn.apollographql.com"], "frame-src": ["sandbox.embed.apollographql.com"] } } } } ``` 要仅为 `/graphql` 路径添加这些例外(推荐),你可以创建一个新的中间件来处理它。例如: ¥To add these exceptions only for the `/graphql` path (recommended), you can create a new middleware to handle it. For example: #### 影子增删改查 {#shadow-crud} ¥Shadow CRUD 为了简化和自动化 GraphQL 模式的构建,我们引入了 Shadow CRUD 功能。它根据你的模型自动生成类型定义、查询、突变和解析器。 ¥To simplify and automate the build of the GraphQL schema, we introduced the Shadow CRUD feature. It automatically generates the type definitions, queries, mutations and resolvers based on your models. **示例:** ¥**Example:** 如果你使用 [交互式 `strapi generate` CLI](/cms/cli#strapi-generate) 或管理面板生成了名为 `Document` 的 API,则你的模型如下所示: ¥If you've generated an API called `Document` using [the interactive `strapi generate` CLI](/cms/cli#strapi-generate) or the administration panel, your model looks like this: ```json title="/src/api/[api-name]/content-types/document/schema.json" { "kind": "collectionType", "collectionName": "documents", "info": { "singularName": "document", "pluralName": "documents", "displayName": "document", "name": "document" }, "options": { "draftAndPublish": true }, "pluginOptions": {}, "attributes": { "name": { "type": "string" }, "description": { "type": "richtext" }, "locked": { "type": "boolean" } } } ```
Generated GraphQL type and queries ```graphql # Document's Type definition input DocumentFiltersInput { name: StringFilterInput description: StringFilterInput locked: BooleanFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput publishedAt: DateTimeFilterInput and: [DocumentFiltersInput] or: [DocumentFiltersInput] not: DocumentFiltersInput } input DocumentInput { name: String description: String locked: Boolean createdAt: DateTime updatedAt: DateTime publishedAt: DateTime } type Document { name: String description: String locked: Boolean createdAt: DateTime updatedAt: DateTime publishedAt: DateTime } type DocumentEntity { id: ID attributes: Document } type DocumentEntityResponse { data: DocumentEntity } type DocumentEntityResponseCollection { data: [DocumentEntity!]! meta: ResponseCollectionMeta! } type DocumentRelationResponseCollection { data: [DocumentEntity!]! } # Queries to retrieve one or multiple restaurants. type Query { document(id: ID): DocumentEntityResponse documents( filters: DocumentFiltersInput pagination: PaginationArg = {} sort: [String] = [] publicationState: PublicationState = LIVE ):DocumentEntityResponseCollection } # Mutations to create, update or delete a restaurant. type Mutation { createDocument(data: DocumentInput!): DocumentEntityResponse updateDocument(id: ID!, data: DocumentInput!): DocumentEntityResponse deleteDocument(id: ID!): DocumentEntityResponse } ```
#### 定制化 {#customization} ¥Customization Strapi 提供了一个编程 API 来自定义 GraphQL,它允许: ¥Strapi provides a programmatic API to customize GraphQL, which allows: * 禁用 [影子增删改查](#shadow-crud) 的某些操作 ¥disabling some operations for the [Shadow CRUD](#shadow-crud) * [使用获取器](#using-getters) 返回有关允许操作的信息 ¥[using getters](#using-getters) to return information about allowed operations * 向 [扩展现有架构](#extending-the-schema) 注册并使用 `extension` 对象(例如扩展类型或定义自定义解析器、策略和中间件) ¥registering and using an `extension` object to [extend the existing schema](#extending-the-schema) (e.g. extend types or define custom resolvers, policies and middlewares)
Example of GraphQL customizations
##### 禁用 Shadow CRUD 中的操作 {#disabling-operations-in-the-shadow-crud} ¥Disabling operations in the Shadow CRUD GraphQL 插件提供的 `extension` 服务公开了可用于禁用 Content-Types 操作的函数: ¥The `extension` service provided with the GraphQL plugin exposes functions that can be used to disable operations on Content-Types: | 内容类型功能 | 描述 | 参数类型 | 可能的参数值 | | -------------------- | --------------------- | ----- | ----------------------------------------------------------------------------------------------------- | | `disable()` | 完全禁用内容类型 | * | * | | `disableQueries()` | 仅禁用 Content-Type 的查询 | * | * | | `disableMutations()` | 仅禁用 Content-Type 的突变 | * | * | | `disableAction()` | 禁用 Content-Type 的特定操作 | 字符串 | 列表中的一个值:
  • `create`
  • `find`
  • `findOne`
  • `update`
  • `delete`
| | `disableActions()` | 禁用 Content-Type 的特定操作 | 字符串数组 | 列表中的多个值:
  • `create`
  • `find`
  • `findOne`
  • `update`
  • `delete`
| 还可以在字段级别禁用操作,具有以下功能: ¥Actions can also be disabled at the field level, with the following functions: | 字段函数 | 描述 | | ------------------ | ----------- | | `disable()` | 完全禁用该字段 | | `disableOutput()` | 禁用字段上的输出 | | `disableInput()` | 禁用字段上的输入 | | `disableFilters()` | 禁用字段上的过滤器输入 | **示例:** ¥**Examples:** ```js // Disable the 'find' operation on the 'restaurant' content-type in the 'restaurant' API strapi .plugin('graphql') .service('extension') .shadowCRUD('api::restaurant.restaurant') .disableAction('find') // Disable the 'name' field on the 'document' content-type in the 'document' API strapi .plugin('graphql') .service('extension') .shadowCRUD('api::document.document') .field('name') .disable() ``` ##### 使用获取器 {#using-getters} ¥Using getters 以下 getter 可用于检索有关内容类型上允许的操作的信息: ¥The following getters can be used to retrieve information about operations allowed on content-types: | 内容类型 getter | 描述 | 参数类型 | 可能的参数值 | | -------------------------- | ------------------------- | ---- | ----------------------------------------------------------------------------------------------------- | | `isEnabled()` | 返回是否启用内容类型 | * | * | | `isDisabled()` | 返回内容类型是否被禁用 | * | * | | `areQueriesEnabled()` | 返回是否在内容类型上启用查询 | * | * | | `areQueriesDisabled()` | 返回是否在内容类型上禁用查询 | * | * | | `areMutationsEnabled()` | 返回是否在内容类型上启用突变 | * | * | | `areMutationsDisabled()` | 返回是否在内容类型上禁用突变 | * | * | | `isActionEnabled(action)` | 返回传递的 `action` 是否在内容类型上启用 | 字符串 | 列表中的一个值:
  • `create`
  • `find`
  • `findOne`
  • `update`
  • `delete`
| | `isActionDisabled(action)` | 返回传递的 `action` 是否在内容类型上禁用 | 字符串 | 列表中的一个值:
  • `create`
  • `find`
  • `findOne`
  • `update`
  • `delete`
| 以下 getter 可用于检索有关字段上允许的操作的信息: ¥The following getters can be used to retrieve information about operations allowed on fields: | 字段获取器 | 描述 | | --------------------- | ---------- | | `isEnabled()` | 返回字段是否启用 | | `isDisabled()` | 返回字段是否被禁用 | | `hasInputEnabled()` | 返回字段是否启用输入 | | `hasOutputEnabled()` | 返回字段是否启用输出 | | `hasFiltersEnabled()` | 返回字段是否启用过滤 | ###### 扩展架构 {#extending-the-schema} ¥Extending the schema 可以通过注册扩展来扩展 Content API 生成的架构。 ¥The schema generated by the Content API can be extended by registering an extension. 此扩展定义为对象或返回对象的函数,将由 GraphQL 插件提供的 `extension` [service](/cms/backend-customization/services) 公开的 `use()` 函数使用。 ¥This extension, defined either as an object or a function returning an object, will be used by the `use()` function exposed by the `extension` [service](/cms/backend-customization/services) provided with the GraphQL plugin. 描述扩展的对象接受以下参数: ¥The object describing the extension accepts the following parameters: | 范围 | 类型 | 描述 | | ----------------- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `types` | 数组 | 允许使用基于
::: ###### 解析器的自定义配置 {#custom-configuration-for-resolvers} ¥Custom configuration for resolvers 解析器是 GraphQL 查询或突变处理程序(即为 GraphQL 查询或突变生成响应的函数或函数集合)。每个字段都有一个默认解析器。 ¥A resolver is a GraphQL query or mutation handler (i.e. a function, or a collection of functions, that generate(s) a response for a GraphQL query or mutation). Each field has a default resolver. 当 [扩展 GraphQL 架构](#extending-the-schema) 时,`resolversConfig` 键可用于定义解析器的自定义配置,其中可以包括: ¥When [extending the GraphQL schema](#extending-the-schema), the `resolversConfig` key can be used to define a custom configuration for a resolver, which can include: * [授权配置](#authorization-configuration) 与 `auth` 键 ¥[authorization configuration](#authorization-configuration) with the `auth` key * [与 `policies` 的政策](#policies) 键 ¥[policies with the `policies`](#policies) key * 和 [带有 `middlewares` 的中间件](#middlewares) 键 ¥and [middlewares with the `middlewares`](#middlewares) key :::tip 提示 [高级查询](/cms/api/graphql/advanced-queries) 指南可能包含适合你用例的附加信息,包括多级查询和自定义解析器示例。 ¥The [advanced queries](/cms/api/graphql/advanced-queries) guide might contain additional information suitable for your use case, including multi-level queries and custom resolvers examples. ::: ###### 授权配置 {#authorization-configuration} ¥Authorization configuration 默认情况下,GraphQL 请求的授权由注册的授权策略处理,可以是 [API 令牌](/cms/features/api-tokens) 或通过 [用户和权限插件](#usage-with-the-users--permissions-plugin)。用户和权限插件提供了更精细的控制。 ¥By default, the authorization of a GraphQL request is handled by the registered authorization strategy that can be either [API token](/cms/features/api-tokens) or through the [Users & Permissions plugin](#usage-with-the-users--permissions-plugin). The Users & Permissions plugin offers a more granular control.
Authorization with the Users & Permissions plugin 使用用户和权限插件,如果授予适当的权限,则允许 GraphQL 请求。 ¥With the Users & Permissions plugin, a GraphQL request is allowed if the appropriate permissions are given. 例如,如果 '类别' 内容类型存在,并且通过 GraphQL 使用 `Query.categories` 处理程序进行查询,则如果为 '类别' 内容类型提供了适当的 `find` 权限,则允许该请求。 ¥For instance, if a 'Category' content-type exists and is queried through GraphQL with the `Query.categories` handler, the request is allowed if the appropriate `find` permission for the 'Categories' content-type is given. 要查询单个类别(使用 `Query.category` 处理程序完成),如果给出 `findOne` 权限,则允许该请求。 ¥To query a single category, which is done with the `Query.category` handler, the request is allowed if the the `findOne` permission is given. 请参阅用户指南了解如何 [使用用户和权限插件定义权限](/cms/features/rbac#editing-a-role)。 ¥Please refer to the user guide on how to [define permissions with the Users & Permissions plugin](/cms/features/rbac#editing-a-role).
要更改授权的配置方式,请使用 `resolversConfig.[MyResolverName]` 处定义的解析器配置。授权可以配置: ¥To change how the authorization is configured, use the resolver configuration defined at `resolversConfig.[MyResolverName]`. The authorization can be configured: * 要么使用 `auth: false` 完全绕过授权系统并允许所有请求, ¥either with `auth: false` to fully bypass the authorization system and allow all requests, * 或者使用接受字符串数组的 `scope` 属性来定义授权请求所需的权限。 ¥or with a `scope` attribute that accepts an array of strings to define the permissions required to authorize the request.
Examples of authorization configuration
###### 政策 {#policies} ¥Policies [政策](/cms/backend-customization/policies) 可以通过 `resolversConfig.[MyResolverName].policies` 键应用于 GraphQL 解析器。 ¥[Policies](/cms/backend-customization/policies) can be applied to a GraphQL resolver through the `resolversConfig.[MyResolverName].policies` key. `policies` 键是一个接受策略列表的数组,该列表中的每一项要么是对已注册策略的引用,要么是直接传递的实现(请参阅 [策略配置文档](/cms/backend-customization/routes#policies))。 ¥The `policies` key is an array accepting a list of policies, each item in this list being either a reference to an already registered policy or an implementation that is passed directly (see [policies configuration documentation](/cms/backend-customization/routes#policies)). `resolversConfig` 中直接实现的策略是以 `context` 对象和 `strapi` 实例作为参数的函数。`context` 对象可以访问: ¥Policies directly implemented in `resolversConfig` are functions that take a `context` object and the `strapi` instance as arguments. The `context` object gives access to: * GraphQL 解析器的 `parent`、`args`、`context` 和 `info` 参数, ¥the `parent`, `args`, `context` and `info` arguments of the GraphQL resolver, * Koa 的
:::tip 提示 [高级策略](/cms/api/graphql/advanced-policies) 指南可能包含适合你用例的附加信息。 ¥The [advanced policies](/cms/api/graphql/advanced-policies) guide might contain additional information suitable for your use case. ::: ###### 中间件 {#middlewares} ¥Middlewares [中间件](/cms/backend-customization/middlewares) 可以通过 `resolversConfig.[MyResolverName].middlewares` 键应用于 GraphQL 解析器。GraphQL 和 REST 实现之间的唯一区别是 `config` 键变为 `options`。 ¥[Middlewares](/cms/backend-customization/middlewares) can be applied to a GraphQL resolver through the `resolversConfig.[MyResolverName].middlewares` key. The only difference between the GraphQL and REST implementations is that the `config` key becomes `options`. `middlewares` 键是一个接受中间件列表的数组,该列表中的每个项目要么是对已注册中间件的引用,要么是直接传递的实现(请参阅 [中间件配置文档](/cms/backend-customization/routes#middlewares))。 ¥The `middlewares` key is an array accepting a list of middlewares, each item in this list being either a reference to an already registered middleware or an implementation that is passed directly (see [middlewares configuration documentation](/cms/backend-customization/routes#middlewares)). 直接在 `resolversConfig` 中实现的中间件可以将 GraphQL 解析器的 ##### 安全 {#security} ¥Security GraphQL 是一种查询语言,允许用户使用比传统 REST API 更广泛的输入面板。GraphQL API 本质上容易出现安全风险,例如凭证泄露和拒绝服务攻击,可以通过采取适当的预防措施来减少这些风险。 ¥GraphQL is a query language allowing users to use a broader panel of inputs than traditional REST APIs. GraphQL APIs are inherently prone to security risks, such as credential leakage and denial of service attacks, that can be reduced by taking appropriate precautions. ### 在生产中禁用自省和沙盒 {#disable-introspection-and-sandbox-in-production} ¥Disable introspection and Sandbox in production 在生产环境中,强烈建议禁用 GraphQL Sandbox 和自省查询。如果你尚未编辑 [配置文件](#available-options),则默认情况下它已在生产中禁用。 ¥In production environments, disabling the GraphQL Sandbox and the introspection query is strongly recommended. If you haven't edited the [configuration file](#available-options), it is already disabled in production by default. ###### 限制最大深度和复杂性 {#limit-max-depth-and-complexity} ¥Limit max depth and complexity 恶意用户可能会发送深度非常高的查询,这可能会使你的服务器过载。使用 `depthLimit` [配置参数](/cms/plugins/graphql#code-based-configuration) 来限制单个请求中可以查询的嵌套字段的最大数量。默认情况下,`depthLimit` 设置为 10,但在测试和开发期间可以设置为更高的值。 ¥A malicious user could send a query with a very high depth, which could overload your server. Use the `depthLimit` [configuration parameter](/cms/plugins/graphql#code-based-configuration) to limit the maximum number of nested fields that can be queried in a single request. By default, `depthLimit` is set to 10 but can be set to a higher value during testing and development. :::tip 提示 为了进一步提高 GraphQL 安全性,可以使用第三方工具。查看有关 你应该会看到在 Strapi 管理面板的 `Users` 集合类型中创建了一个新用户。 ¥You should see a new user is created in the `Users` collection type in your Strapi admin panel. #### 验证 {#authentication} ¥Authentication 要执行授权请求,你必须首先获取 JWT: ¥To perform authorized requests, you must first get a JWT: 然后,在每个请求中,以 `{ "Authorization": "Bearer YOUR_JWT_GOES_HERE" }` 的形式发送 `Authorization` 标头。这可以在 GraphQL Sandbox 的 HTTP Headers 部分中设置。 ¥Then on each request, send along an `Authorization` header in the form of `{ "Authorization": "Bearer YOUR_JWT_GOES_HERE" }`. This can be set in the HTTP Headers section of your GraphQL Sandbox. #### 使用 API 令牌 {#api-tokens} ¥Usage with API tokens 要使用 API 令牌进行身份验证,请使用 `Bearer your-api-token` 格式在 `Authorization` 标头中传递令牌。 ¥To use API tokens for authentication, pass the token in the `Authorization` header using the format `Bearer your-api-token`. :::note 注意 在 GraphQL Sandbox 中使用 API 令牌需要在 `HTTP HEADERS` 选项卡中添加带有令牌的授权标头: ¥Using API tokens in the the GraphQL Sandbox requires adding the authorization header with your token in the `HTTP HEADERS` tab: ```http { "Authorization" : "Bearer # 通过市场安装插件 Source: https://docs.strapi.io/cms/plugins/installing-plugins-via-marketplace # 使用市场 {#using-the-marketplace} ¥Using the Marketplace Strapi 附带内置插件,例如 [文档](/cms/plugins/documentation)、[GraphQL](/cms/plugins/graphql) 和 [Sentry](/cms/plugins/sentry)。用户可以在 Marketplace 中找到其他插件来定制 Strapi 应用,以及其他提供程序来扩展插件。市场位于管理面板中,由 市场表示。在市场中,用户可以浏览或搜索插件和提供者,链接到每个插件和提供者的详细描述,并提交新的插件和提供者。 ¥Strapi comes with built-in plugins such as [Documentation](/cms/plugins/documentation), [GraphQL](/cms/plugins/graphql), and [Sentry](/cms/plugins/sentry). The Marketplace is where users can find additional plugins to customize Strapi applications, and additional providers to extend plugins. The Marketplace is located in the admin panel, indicated by *Marketplace*. In the Marketplace, users can browse or search for plugins and providers, link to detailed descriptions for each, and submit new plugins and providers. :::note Strapi 应用内市场与市场网站 管理面板中的 Marketplace 显示所有现有插件,无论它们适用于哪个版本的 Strapi。所有插件也可以通过 网站发现。 ¥The Marketplace in the admin panel displays all existing plugins, regardless of the version of Strapi they are for. All plugins can also be discoverable through the website. 但请记住,v4 和 v5 插件不相互兼容,但提供商与 v4 和 v5 插件都兼容。 ¥Keep in mind however that v4 and v5 plugins are not cross-compatible, but that providers are compatible both with v4 and v5 plugins. ::: 插件和提供程序选项卡在各个卡上显示每个插件/提供程序,其中包含: ¥The Plugins and Providers tabs display each plugin/provider on individual cards containing: - their name, sometimes followed by either of the following badges: - maintained by Strapi icon to indicate it is made by Strapi, - to indicate it was verified by Strapi. - the number of times the plugin/provider was starred on GitHub and downloaded - the description - a **More** button to be redirected to the Market website for additional information, including about the version of Strapi the plugin is for, and implementation instructions 在 Marketplace 的右上角,提交插件按钮会重定向到 Strapi Market,你可以在其中提交自己的插件和提供商。 ¥In the top right corner of the Marketplace, the **Submit plugin** button redirects to the Strapi Market where it is possible to submit your own plugin and provider. :::tip 提示 * 搜索栏根据插件/提供者名称和描述显示增量搜索结果。 ¥The search bar displays incremental search results based on the plugin/provider name and description. * 使用 "排序方式" 按钮或设置过滤器可以更轻松地查找插件。 ¥Use the "Sort by" button or set filters to find plugins more easily. ::: ## 安装 Marketplace 插件和提供程序 {#installing-marketplace-plugins-and-providers} ¥Installing Marketplace plugins and providers 要通过 Marketplace 安装新插件或提供程序: ¥To install a new plugin or provider via the Marketplace: 1. 转到 市场。 ¥Go to the *Marketplace*. 2. 选择插件选项卡以浏览可用插件,或选择提供程序选项卡以浏览可用提供程序。 ¥Choose the **Plugins** tab to browse available plugins or the **Providers** tab to browse available providers. 3. 选择一个可用的插件/提供程序,然后单击更多 按钮。 ¥Choose an available plugin/provider and click on the **More** button. 4. 重定向到 Strapi 市场网站后,请按照插件/提供商特定的实现说明进行操作。 ¥Once redirected to the Strapi Market website, follow the plugin/provider-specific implementation instructions. :::strapi 开发 Strapi 插件 找不到适合你用例的插件?欢迎使用 [创建你自己的](/cms/plugins-development/developing-plugins)! ¥Can't find a plugin that suits your use case? Feel free to [create your own](/cms/plugins-development/developing-plugins)! ::: # Sentry 插件 Source: https://docs.strapi.io/cms/plugins/sentry # Sentry 插件 {#sentry-plugin} ¥Sentry plugin 此插件使你能够使用 Sentry 跟踪 Strapi 应用中的错误。 ¥This plugin enables you to track errors in your Strapi application using Sentry. 通过使用 Sentry 插件,你可以: ¥By using the Sentry plugin you can: * 在 Strapi 应用启动时初始化 Sentry 实例 ¥Initialize a Sentry instance upon startup of a Strapi application * 将 Strapi 应用错误作为事件发送到 Sentry ¥Send Strapi application errors as events to Sentry * 在 Sentry 事件中包含其他元数据以协助调试 ¥Include additional metadata in Sentry events to assist in debugging * 公开 Strapi 服务器可用的全局 Sentry 服务 ¥Expose a global Sentry service usable by the Strapi server ## 安装 {#installation} ¥Installation 通过将依赖添加到 Strapi 应用来安装 Sentry 插件,如下所示: ¥Install the Sentry plugin by adding the dependency to your Strapi application as follows: ## 配置 {#configuration} ¥Configuration 创建或编辑 `/config/plugins` 文件以配置 Sentry 插件。可以使用以下属性: ¥Create or edit your `/config/plugins` file to configure the Sentry plugin. The following properties are available: | 属性 | 类型 | 默认值 | 描述 | | -------------- | ------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dsn` | string | `null` | 你的 Sentry ### 在非生产环境中禁用 {#disabling-for-non-production-environments} ¥Disabling for non-production environments 如果 `dsn` 属性设置为零值(`null` 或 `undefined`),而 `sentry.enabled` 为真,则 Sentry 插件将可用于正在运行的 Strapi 实例,但服务实际上不会向 Sentry 发送错误。这允许你编写在每个环境上运行的代码而无需额外检查,但只会在生产中向 Sentry 发送错误。 ¥If the `dsn` property is set to a nil value (`null` or `undefined`) while `sentry.enabled` is true, the Sentry plugin will be available to use in the running Strapi instance, but the service will not actually send errors to Sentry. That allows you to write code that runs on every environment without additional checks, but only send errors to Sentry in production. 当你使用 nil `dsn` 配置属性启动 Strapi 时,插件将打印以下警告:
`info: @strapi/plugin-sentry is disabled because no Sentry DSN was provided` ¥When you start Strapi with a nil `dsn` config property, the plugin will print the following warning:
`info: @strapi/plugin-sentry is disabled because no Sentry DSN was provided` 你可以利用 [`env` 实用程序](/cms/configurations/guides/access-cast-environment-variables) 根据环境设置 `dsn` 配置属性来利用它。 ¥You can make use of that by using the [`env` utility](/cms/configurations/guides/access-cast-environment-variables) to set the `dsn` configuration property depending on the environment. ### 完全禁用插件 {#disabling-the-plugin-completely} ¥Disabling the plugin completely 与其他所有 Strapi 插件一样,你也可以在插件配置文件中禁用此插件。这将导致 `strapi.plugins('sentry')` 返回 `undefined`: ¥Like every other Strapi plugin, you can also disable this plugin in the plugins configuration file. This will cause `strapi.plugins('sentry')` to return `undefined`: ## 用法 {#usage} ¥Usage 安装并配置插件后,你可以在 Strapi 应用中访问 Sentry 服务,如下所示: ¥After installing and configuring the plugin, you can access a Sentry service in your Strapi application as follows: ```js const sentryService = strapi.plugin('sentry').service('sentry'); ``` 该服务公开了以下方法: ¥This service exposes the following methods: | 方法 | 描述 | 参数 | | --------------- | ----------------- | -- | | `sendError()` | 手动将错误发送到 Sentry。 | | | `getInstance()` | 用于直接访问 Sentry 实例。 | * | `sendError()` 方法可以按如下方式使用: ¥The `sendError()` method can be used as follows: ```js try { // Your code here } catch (error) { // Either send a simple error strapi .plugin('sentry') .service('sentry') .sendError(error); // Or send an error with a customized Sentry scope strapi .plugin('sentry') .service('sentry') .sendError(error, (scope, sentryInstance) => { // Customize the scope here scope.setTag('my_custom_tag', 'Tag value'); }); throw error; } ``` `getInstance()` 方法可按如下方式访问: ¥The `getInstance()` method is accessible as follows: ```js const sentryInstance = strapi .plugin('sentry') .service('sentry') .getInstance(); ``` # 项目结构 Source: https://docs.strapi.io/cms/project-structure # 项目结构 {#project-structure} ¥Project structure Strapi 项目的结构取决于项目是使用 [TypeScript](/cms/typescript)(如果你在创建项目时使用了 `--quickstart` 选项,则这是默认设置)还是使用原始 JavaScript 创建的,如下所示: ¥The structure of a Strapi project depends on whether the project was created with [TypeScript](/cms/typescript) (which is the default if you used the `--quickstart` option while creating the project) or with vanilla JavaScript, and looks like the following: # 快速入门指南 - Strapi 开发者文档 Source: https://docs.strapi.io/cms/quick-start # 快速入门指南 {#quick-start-guide} ¥Quick Start Guide Strapi 提供了很大的灵活性。无论你是想快速查看最终结果,还是想更深入地了解产品,我们都能满足你的需求。对于本教程,我们将采用 DIY 方法,从头开始构建项目和内容结构,然后将项目部署到 Strapi Cloud 以从那里添加数据。 ¥Strapi offers a lot of flexibility. Whether you want to go fast and quickly see the final result, or would rather dive deeper into the product, we got you covered. For this tutorial, we'll go for the DIY approach and build a project and content structure from scratch, then deploy your project to Strapi Cloud to add data from there. 预计完成时间:5-10 分钟 ¥*Estimated completion time: 5-10 minutes* :::prerequisites 2. 终端将提示你登录或注册。完成后, 3. 在终端中回答问题,为你的项目命名(你可以按 Enter 保留默认名称),选择推荐的 NodeJS 版本,并选择更接近你当前位置的区域: ¥Answer questions in the terminal, giving your project a name (you can press Enter to keep the default name), choosing the recommended NodeJS version, and selecting the region closer to your current place: ![Strapi Cloud terminal questions and answers](/img/assets/quick-start-guide/qsg-strapi-cloud-terminal-questions.png) 几分钟后,你的本地项目将托管在 Strapi Cloud 上。🚀 ¥Within a few moments, your local project will be hosted on Strapi Cloud. 🚀 完成后,终端将为你提供一个以 `https://cloud.strapi.io/projects` 开头的可点击链接。单击链接,或将其复制并粘贴到浏览器地址栏中,以访问该页面。 ¥Once it's done, the terminal will provide you a clickable link that starts with `https://cloud.strapi.io/projects`. Click on the link, or copy and paste it in your browser address bar, to visit the page. 你将在 Strapi Cloud 仪表板中看到我们刚刚创建的 Strapi Cloud 项目 `my-strapi-project`。单击右上角的访问应用按钮以访问你已部署的 Strapi 项目。 ¥You will see the Strapi Cloud project we've just created, `my-strapi-project`, visible in the Strapi Cloud dashboard. Click the **Visit app** button in the top right corner to access your deployed Strapi project. :::callout Congratulations! 现在,你的项目托管在 Strapi Cloud 上并可在线访问。你可以通过阅读 [其专用文档](/cloud/intro) 了解有关 Strapi Cloud 的更多信息,或继续阅读 D 部分,登录你的在线 Strapi 项目并从那里添加你的第一个数据。 ¥Now your project is hosted on Strapi Cloud and accessible online. You can learn more about Strapi Cloud by reading [its dedicated documentation](/cloud/intro) or proceed to part D to log in into your online Strapi project and add your first data from there. ::: :::tip 提示 请随意使用内容类型构建器,并进一步向你的内容类型添加更多字段或创建新的内容类型。每当你进行此类更改时,请通过运行适当的 `deploy` 命令将其再次部署到 Strapi Cloud 上,并在几分钟内查看托管项目的更新。很神奇,不是吗?🪄 ¥Feel free to play with the Content-Type Builder even further and add more fields to your content-types or create new content-types. Anytime you make such changes, deploy them again on Strapi Cloud, by running the appropriate `deploy` command, and see your hosted project updated within a few minutes. Magical, isn't it? 🪄 ::: ## D 部分:使用内容管理器将内容添加到你的 Strapi Cloud 项目 {#icon-namenote-pencil--part-d-add-content-to-your-strapi-cloud-project-with-the-content-manager} ¥ Part D: Add content to your Strapi Cloud project with the Content Manager 现在我们已经创建了一个包含 2 个集合类型 "餐厅" 和 "类别" 的基本内容结构,并将你的项目部署到 Strapi Cloud,让我们使用 Cloud 通过创建新条目来实际添加内容。 ¥Now that we have created a basic content structure with 2 collection types, "Restaurant" and "Category", and deployed your project to Strapi Cloud, let's use the Cloud to actually add content by creating new entries.
Step 1: Log in to the admin panel of your new Strapi Cloud project ### 步骤 1:登录到新 Strapi Cloud 项目的管理面板 {#step-1-log-in-to-the-admin-panel-of-your-new-strapi-cloud-project} ¥Step 1: Log in to the admin panel of your new Strapi Cloud project 现在你的 Strapi Cloud 项目已创建,让我们登录该项目: ¥Now that your Strapi Cloud project is created, let's log in into the project: 1. 从你的 ,单击 `my-strapi-project` 项目。 ¥From your , click the `my-strapi-project` project. 2. 单击访问应用按钮。 ¥Click the **Visit app** button. 3. 在打开的新页面中,填写表单以创建此 Strapi Cloud 项目的第一个管理员用户。 ¥In the new page that opens, complete the form to create the first administrator user of this Strapi Cloud project. 登录到我们的第一个 Strapi Cloud 项目,我们现在将从那里添加数据。 ¥Logged in into our first Strapi Cloud project, we will now add data from there.
Additional information and tips about users and Strapi Cloud projects: :::note 注意:本地用户和 Strapi Cloud 用户不同 Strapi Cloud 项目和本地项目的数据库不同。这意味着数据不会自动从本地项目传输到 Strapi Cloud。这包括你之前在本地创建的用户。这就是为什么你在首次登录 Strapi Cloud 项目时会被邀请创建一个新的管理员账户。 ¥The databases for your Strapi Cloud project and your local project are different. This means that data is not automatically transferred from your local project to Strapi Cloud. This includes users that you previously created locally. That's why you are invited to create a new administrator account when logging in to your Strapi Cloud project for the first time. ::: :::tip 提示:直接访问 Strapi Cloud 项目的管理面板 Strapi Cloud 上托管的任何项目都可以通过其自己的 URL 访问,例如 `https://my-strapi-project-name.strapiapp.com`。要访问在线项目的管理面板,只需将 `/admin` 添加到 URL,例如 `https://my-strapi-project-name.strapiapp.com/admin`。URL 可以在你的 Strapi Cloud 仪表板中找到,你还可以通过单击项目名称然后单击“访问应用”按钮从那里直接访问你的 Strapi Cloud 项目。 ¥Any project hosted on Strapi Cloud is accessible from its own URL, something like `https://my-strapi-project-name.strapiapp.com`. To access the admin panel of your online project, simply add `/admin` to the URL, for instance as in `https://my-strapi-project-name.strapiapp.com/admin`. URLs can be found in your Strapi Cloud dashboard and you can also directly access your Strapi Cloud projects from there by clicking on the name of your project then on the **Visit app** button. :::
Step 2: Create an entry for the "Restaurant" collection type ### 第 2 步:为 "餐厅" 集合类型创建条目 {#step-2-create-an-entry-for-the-restaurant-collection-type} ¥Step 2: Create an entry for the "Restaurant" collection type 1. 转到 内容管理器 > 集合类型 - 导航中的餐厅。 ¥Go to *Content Manager > Collection types - Restaurant* in the navigation. 2. 单击创建新条目。 ¥Click on **Create new entry**. 3. 在名称字段中输入你最喜欢的当地餐馆的名称。假设它是 `Biscotte Restaurant`。 ¥Type the name of your favorite local restaurant in the *Name* field. Let's say it's `Biscotte Restaurant`. 4. 在描述字段中,写几句话。如果你缺乏一些灵感,你可以使用 `Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.` ¥In the *Description* field, write a few words about it. If you're lacking some inspiration, you can use `Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.` 5. 单击“保存”。 ¥Click **Save**. 该餐厅现已列入集合类型 - 内容管理器的餐厅视图。 ¥The restaurant is now listed in the *Collection types - Restaurant* view of the *Content Manager*.
Step 3: Add Categories #### 步骤 3:添加类别 {#step-3-add-categories} ¥Step 3: Add Categories 让我们转到 内容管理器 > 集合类型 - 分类并创建 2 个类别: ¥Let's go to *Content Manager > Collection types - Category* and create 2 categories: 1. 单击创建新条目。 ¥Click on **Create new entry**. 2. 在名称字段中输入 `French Food`。 ¥Type `French Food` in the *Name* field. 3. 单击“保存”。 ¥Click **Save**. 4. 返回集合类型 - 类别,然后再次单击“创建新条目”。 ¥Go back to *Collection types - Category*, then click again on **Create new entry**. 5. 在“名称”字段中键入 `Brunch`,然后单击“保存”。 ¥Type `Brunch` in the *Name* field, then click **Save**. "法国食物" 和 "早午餐" 类别现在列在集合类型中 - 内容管理器的类别视图。 ¥The "French Food" and "Brunch" categories are now listed in the *Collection types - Category* view of the *Content Manager*. 现在,我们将为餐厅添加一个类别: ¥Now, we will add a category to a restaurant: 1. 转到 内容管理器 > 集合类型 - 在导航中的餐厅,然后点击 "比斯科特餐厅"。 ¥Go to *Content Manager > Collection types - Restaurant* in the navigation, and click on "Biscotte Restaurant". 2. 在页面底部的类别下拉列表中,选择 "法国食物"。滚动回到页面顶部,然后单击“保存”。 ¥In the **Categories** drop-down list at the bottom of the page, select "French Food". Scroll back to the top of the page and click **Save**.
Step 4: Set Roles & Permissions ### 步骤 4:设置角色和权限 {#step-4-set-roles--permissions} ¥Step 4: Set Roles & Permissions 我们刚刚添加了一家餐厅和 2 个类别。我们现在有足够的内容可供消费(双关语)。但首先,我们需要确保内容可以通过 API 公开访问: ¥We have just added a restaurant and 2 categories. We now have enough content to consume (pun intended). But first, we need to make sure that the content is publicly accessible through the API: 1. 单击主导航底部的 设置。 ¥Click on * Settings* at the bottom of the main navigation. 2. 在用户和权限插件下,选择角色。 ¥Under *Users & Permissions Plugin*, choose *Roles*. 3. 单击公共角色。 ¥Click the **Public** role. 4. 在“权限”下向下滚动。 ¥Scroll down under *Permissions*. 5. 在“权限”选项卡中,找到“餐厅”并单击它。 ¥In the *Permissions* tab, find *Restaurant* and click on it. 6. 单击“查找”和“findOne”旁边的复选框。 ¥Click the checkboxes next to **find** and **findOne**. 7. 重复类别:单击“查找”和“findOne”旁边的复选框。 ¥Repeat with *Category*: click the checkboxes next to **find** and **findOne**. 8. 最后,单击“保存”。 ¥Finally, click **Save**.
Step 5: Publish the content ### 第 5 步:发布内容 {#step-5-publish-the-content} ¥Step 5: Publish the content 默认情况下,你创建的任何内容都会保存为草稿。让我们发布我们的类别和餐厅。 ¥By default, any content you create is saved as a draft. Let's publish our categories and restaurant. 首先,导航到 内容管理器 > 集合类型 - 类别。从那里: ¥First, navigate to *Content Manager > Collection types - Category*. From there: 1. 单击 "早午餐" 条目。 ¥Click the "Brunch" entry. 2. 在下一个屏幕上,单击“发布”。 ¥On the next screen, click **Publish**. 3. 在确认窗口中,单击是,发布。 ¥In the *Confirmation* window, click **Yes, publish**. 然后,返回类别列表并对 "法国食物" 类别重复此操作。 ¥Then, go back to the Categories list and repeat for the "French Food" category. 最后,要发布你最喜欢的餐厅,请转到 内容管理器 > 集合类型 - 餐厅,单击 "比斯科特餐厅" 条目,然后发布它。 ¥Finally, to publish your favorite restaurant, go to *Content Manager > Collection types - Restaurant*, click the "Biscotte Restaurant" entry, and **Publish** it.
Step 6: Use the API ### 第 6 步:使用 API {#step-6-use-the-api} ¥Step 6: Use the API 好的,亲爱的美食家,我们刚刚完成了内容的创建并使其可以通过 API 进行访问。你可以拍拍自己的背 - 但你还没有看到你努力工作的最终结果。 ¥OK dear gourmet, we have just finished creating our content and making it accessible through the API. You can give yourself a pat on the back — but you have yet to see the final result of your hard work. 你在这:应可通过访问 Strapi Cloud 项目 URL 的 `/api/restaurants` 路径(例如 `https://beautiful-first-strapi-project.strapiapp.com/api/restaurants`)来访问餐厅列表。 ¥There you are: the list of restaurants should be accessible by visting the `/api/restaurants` path of your Strapi Cloud project URL (e.g., `https://beautiful-first-strapi-project.strapiapp.com/api/restaurants`). 现在就试试!结果应该与下面的示例响应类似👇。 ¥Try it now! The result should be similar to the example response below 👇.
Click me to view an example of API response: ```json { "data": [ { "id": 3, "documentId": "wf7m1n3g8g22yr5k50hsryhk", "Name": "Biscotte Restaurant", "Description": [ { "type": "paragraph", "children": [ { "type": "text", "text": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers." } ] } ], "createdAt": "2024-09-10T12:49:32.350Z", "updatedAt": "2024-09-10T13:14:18.275Z", "publishedAt": "2024-09-10T13:14:18.280Z", "locale": null } ], "meta": { "pagination": { "page": 1, "pageSize": 25, "pageCount": 1, "total": 1 } } } ```
:::callout Congratulations! 现在你的内容已创建、发布,并且你有权通过 API 请求它。继续创造精彩的内容! ¥Now your content is created, published, and you have permissions to request it through the API. Keep on creating amazing content! ::: :::tip 提示:在本地和 Strapi Cloud 项目之间传输数据 Strapi Cloud 项目和本地项目的数据库不同。这意味着数据不会在你的 Strapi Cloud 和本地项目之间自动同步。你可以使用 [数据管理系统](/cms/features/data-management) 在项目之间传输数据。 ¥The databases for your Strapi Cloud project and your local project are different. This means that data is not automatically synchronized between your Strapi Cloud and local projects. You can use the [data management system](/cms/features/data-management) to transfer data between projects. ::: ## 下一步做什么? {#icon-namefast-forward-what-to-do-next} ¥ What to do next? 现在你已经了解了使用 Strapi 创建和发布内容的基础知识,我们鼓励你更深入地探索和挖掘 Strapi 的一些功能: ¥Now that you know the basics of creating and publishing content with Strapi, we encourage you to explore and dig deeper into some Strapi features: 了解如何使用 Strapi 的 [REST](/cms/api/rest) API 查询内容,
通过浏览 功能类别了解有关 Strapi 功能的更多信息,
通过阅读 [Cloud 文档](/cloud/intro) 了解有关 Strapi Cloud 项目的更多信息,
和 [定制你的 Strapi 后端](/cms/backend-customization) 和 [管理面板](/cms/admin-panel-customization) 了解高级用例。
¥ learn how to use Strapi's [REST](/cms/api/rest) API to query the content,
learn more about Strapi features by browsing the **Features** category,
learn more about Strapi Cloud projects by reading the [Cloud Documentation](/cloud/intro),
and [customize your Strapi back end](/cms/backend-customization) and [admin panel](/cms/admin-panel-customization) for advanced use cases.
# 模板 Source: https://docs.strapi.io/cms/templates # 模板 {#templates} ¥Templates Strapi 5 中的模板是独立的、预制的 Strapi 应用,专为特定用例而设计。 ¥Templates in Strapi 5 are standalone, pre-made Strapi applications designed for specific use cases. Strapi 5 模板是包含你在典型的 Strapi 应用中找到的所有文件和文件夹的文件夹(参见 [项目结构](/cms/project-structure))。 ¥Strapi 5 templates are folders that include all files and folders that you would find in a typical Strapi application (see [project structure](/cms/project-structure)). ## 使用模板 {#using-a-template} ¥Using a template 要基于模板创建新的 Strapi 项目,请运行以下命令: ¥To create a new Strapi project based on a template, run the following command: 除了必需的 `--template` 参数之外,你还可以传递可选的 `--template-path` 和 `--template-branch` 选项以更精确地定义要使用的模板。 ¥In addition to the mandatory `--template` parameter, you can pass the optional `--template-path` and `--template-branch` options to more precisely define the template to use. 下表列出了定义要使用哪个模板的所有可能方法: ¥The following table lists all the possible ways to define which template to use: | 语法 | 描述 | | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--template website` | 使用其中一个 通过其(文件夹)名称调用它。 | | `--template strapi/strapi` | 使用模板的 GitHub 存储库简写。
这将使用默认存储库分支。 | | `--template strapi/strapi/some/sub/path` | 使用模板的 GitHub 存储库简写并指定子路径。
这将使用默认存储库分支。 | | `--template strapi/strapi`
`--template-branch=xxx`
`--template-path=some/sub/path` | 最冗长的方式,明确定义模板分支和子路径。 | | `--template https://github.com/owner/some-template-repo` | 使用完整的存储库 URL。
这将使用默认存储库分支。 | | `--template https://github.com/owner/some-template-repo --template-branch=xxx --template-path=sub/path` | 使用完整的存储库 URL,并指定模板的分支和子路径。 | | `--template https://github.com/strapi/strapi/tree/branch/sub/path` | 直接使用存储库、分支和子路径。

⚠️ 警告:这不适用于包含 `/` 的分支名称。在这种情况下,最好明确定义 `--template-branch` 和 `--template-path`。 | ## 创建模板 {#creating-a-template} ¥Creating a template 创建 Strapi 5 模板与创建 Strapi 应用一样简单。创建应用(参见 [CLI 安装](/cms/installation/cli)),生成的包含 Strapi 5 应用的文件夹可用作模板。然后,你可以在创建新的 Strapi 5 应用以将其用作模板时将其传递给 `--template` 标志。 ¥Creating a Strapi 5 template is as simple as creating a Strapi application. Create the application (see [CLI installation](/cms/installation/cli)) and the generated folder containing your Strapi 5 application can serve as a template. You can then pass it to the `--template` flag when creating a new Strapi 5 application to use it as a template. 模板的示例是 。 ¥An example of what a template could look like is the . # 测试 Source: https://docs.strapi.io/cms/testing # 单元和集成测试指南 {#unit-and-integration-testing-guide} ¥Unit and integration testing guide 本指南提供了在 Strapi 5 应用中配置 ``` * `Jest` provides the test runner and assertion utilities. * `Supertest` allows you to test all the `api` routes as they were instances of 用于重新创建 Strapi 对象的各个部分以及代码所依赖的任何请求上下文的实用程序。 ¥utilities to recreate just the parts of the Strapi object and any request context that your code relies on. ### 控制器示例 {#controller-example} ¥Controller example 创建一个测试文件,例如 `./tests/todo-controller.test.js`,使用模拟的 Strapi 对象实例化你的控制器,并验证控制器执行的每个调用: ¥Create a test file such as `./tests/todo-controller.test.js` that instantiates your controller with a mocked Strapi object and verifies every call the controller performs: ```js title="./tests/todo-controller.test.js" const todoController = require('./todo-controller'); describe('Todo controller', () => { let strapi; beforeEach(() => { strapi = { plugin: jest.fn().mockReturnValue({ service: jest.fn().mockReturnValue({ create: jest.fn().mockReturnValue({ data: { name: 'test', status: false, }, }), complete: jest.fn().mockReturnValue({ data: { id: 1, status: true, }, }), }), }), }; }); it('creates a todo item', async () => { const ctx = { request: { body: { name: 'test', }, }, body: null, }; await todoController({ strapi }).index(ctx); expect(ctx.body).toBe('created'); expect(strapi.plugin('todo').service('create').create).toHaveBeenCalledTimes(1); }); it('completes a todo item', async () => { const ctx = { request: { body: { id: 1, }, }, body: null, }; await todoController({ strapi }).complete(ctx); expect(ctx.body).toBe('todo completed'); expect(strapi.plugin('todo').service('complete').complete).toHaveBeenCalledTimes(1); }); }); ``` `beforeEach` 钩子会重建模拟,因此每个测试都从一个干净的 Strapi 实例开始。每个测试都会准备控制器期望的 `ctx` 请求对象,调用控制器函数,并断言响应和与 Strapi 服务的交互。 ¥The `beforeEach` hook rebuilds the mock so every test starts with a clean Strapi instance. Each test prepares the `ctx` request object that the controller expects, calls the controller function, and asserts both the response and the interactions with Strapi services. ### 服务示例 {#service-example} ¥Service example 服务可以在同一个测试套件中进行测试,也可以在专用文件中通过仅模拟它们调用的 Strapi 查询层进行测试。 ¥Services can be tested in the same test suite or in a dedicated file by mocking only the Strapi query layer they call into. ```js title="./tests/create-service.test.js" const createService = require('./create-service'); describe('Create service', () => { let strapi; beforeEach(() => { strapi = { query: jest.fn().mockReturnValue({ create: jest.fn().mockReturnValue({ data: { name: 'test', status: false, }, }), }), }; }); it('persists a todo item', async () => { const todo = await createService({ strapi }).create({ name: 'test' }); expect(strapi.query('plugin::todo.todo').create).toHaveBeenCalledTimes(1); expect(todo.data.name).toBe('test'); }); }); ``` 通过专注于 mocking 代码接触到的特定 Strapi API,你可以扩展这些测试以覆盖更多分支、错误情况和服务,同时保持它们的快速和隔离。 ¥By focusing on mocking the specific Strapi APIs your code touches, you can grow these tests to cover additional branches, error cases, and services while keeping them fast and isolated. ## 设置测试环境 {#set-up-a-testing-environment} ¥Set up a testing environment 对于使用 用于设置和拆除 Strapi 实例以进行测试 ¥that sets up and tears down Strapi instances for tests ### TypeScript 编译器配置 {#typescript-compiler-configuration} ¥TypeScript compiler configuration 创建包含以下内容的 `tests/ts-compiler-options.js`: ¥Create `tests/ts-compiler-options.js` with the following content: ```js title="./tests/ts-compiler-options.js" const fs = require('fs'); const path = require('path'); const ts = require('typescript'); const projectRoot = path.resolve(__dirname, '..'); const tsconfigPath = path.join(projectRoot, 'tsconfig.json'); const baseCompilerOptions = { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019, moduleResolution: ts.ModuleResolutionKind.NodeJs, esModuleInterop: true, jsx: ts.JsxEmit.React, }; const loadCompilerOptions = () => { let options = { ...baseCompilerOptions }; if (!fs.existsSync(tsconfigPath)) { return options; } try { const tsconfigContent = fs.readFileSync(tsconfigPath, 'utf8'); const parsed = ts.parseConfigFileTextToJson(tsconfigPath, tsconfigContent); if (!parsed.error && parsed.config && parsed.config.compilerOptions) { options = { ...options, ...parsed.config.compilerOptions, }; } } catch (error) { // Ignore tsconfig parsing errors and fallback to defaults } return options; }; module.exports = { compilerOptions: loadCompilerOptions(), loadCompilerOptions, }; ``` 此文件加载项目的 TypeScript 配置,并在配置文件不存在时提供合理的默认值。 ¥This file loads your project's TypeScript configuration and provides sensible defaults if the config file doesn't exist. ### TypeScript 运行时加载器 {#typescript-runtime-loader} ¥TypeScript runtime loader 创建包含以下内容的 `tests/ts-runtime.js`: ¥Create `tests/ts-runtime.js` with the following content: ```js title="./tests/ts-runtime.js" const Module = require('module'); const { compilerOptions } = require('./ts-compiler-options'); const fs = require('fs'); const ts = require('typescript'); const extensions = Module._extensions; if (!extensions['.ts']) { extensions['.ts'] = function compileTS(module, filename) { const source = fs.readFileSync(filename, 'utf8'); const output = ts.transpileModule(source, { compilerOptions, fileName: filename, reportDiagnostics: false, }); return module._compile(output.outputText, filename); }; } if (!extensions['.tsx']) { extensions['.tsx'] = extensions['.ts']; } module.exports = { compilerOptions, }; ``` 此文件指导 Node.js 如何通过动态将 `.ts` 和 `.tsx` 文件转换为 JavaScript 来加载它们。 ¥This file teaches Node.js how to load `.ts` and `.tsx` files by transpiling them to JavaScript on the fly. ### 主要测试工具 {#main-test-harness} ¥Main test harness 创建包含以下内容的 `tests/strapi.js`: ¥Create `tests/strapi.js` with the following content: 测试工具的作用: ¥What the test harness does: 1. TypeScript 支持:修补 Strapi 的配置加载器,使其能够理解配置目录中的 TypeScript 文件(`.ts`、`.cts`、`.mts`)。 ¥**TypeScript Support**: Patches Strapi's configuration loader to understand TypeScript files (`.ts`, `.cts`, `.mts`) in your config directory 2. 配置验证:确保仅加载有效的配置文件,并警告常见错误(例如将文件命名为 `middleware.js` 而不是 `middlewares.js`)。 ¥**Configuration Validation**: Ensures only valid config files are loaded and warns about common mistakes (like naming a file `middleware.js` instead of `middlewares.js`) 3. 数据库规范化:将数据库客户端名称映射到其实际驱动程序名称(例如,`sqlite` → `sqlite3`)并处理连接池 ¥**Database Normalization**: Maps database client names to their actual driver names (e.g., `sqlite` → `sqlite3`) and handles connection pooling 4. 环境设置:设置测试所需的所有环境变量,包括 JWT 密钥和数据库配置 ¥**Environment Setup**: Sets all required environment variables for testing, including JWT secrets and database configuration 5. 自动路由注册:自动注册一个 `/api/hello` 测试端点,你可以在测试中使用。 ¥**Automatic Route Registration**: Automatically registers a `/api/hello` test endpoint that you can use in your tests 6. 用户权限助手:修补用户服务,使其自动将 "authenticated" 角色分配给新创建的用户,从而简化身份验证测试。 ¥**User Permission Helper**: Patches the user service to automatically assign the "authenticated" role to newly created users, simplifying authentication tests 7. 清理:测试完成后,正确关闭连接并删除临时数据库文件。 ¥**Cleanup**: Properly closes connections and removes temporary database files after tests complete :::note 注意 `tests/strapi.js` 工具链的代码示例高亮了 313-321 行,因为这些行是可选的,用于 [植入可预测的测试数据](#optional-seed-predictable-test-data) 测试。 ¥The code example for the `tests/strapi.js` harness highlights lines 313-321 because these are optional, to be used if you [seed predictable test data](#optional-seed-predictable-test-data). ::: 这些文件到位后,线束会自动处理 Strapi 5 的多项需求,让你专注于编写实际测试逻辑,而不是配置样板。 ¥Once these files are in place, the harness handles several Strapi 5 requirements automatically, letting you focus on writing actual test logic rather than configuration boilerplate. ## (可选)植入可预测的测试数据 {#optional-seed-predictable-test-data} ¥(optional) Seed predictable test data 某些 API 测试受益于预加载一组已知文档。你可以将项目种子公开为可重用函数,并在环境标志后面从测试工具中调用它: ¥Some API tests benefit from having a known set of documents preloaded. You can expose your project seeding as a reusable function and call it from the harness behind an environment flag: 1. 从项目脚本中导出种子函数(例如 `./scripts/seed.js`): ¥Export a seeding function from your project script (e.g. `./scripts/seed.js`): ```js title="./scripts/seed.js" async function seedExampleApp() { // In test environment, skip complex seeding and just log if (process.env.NODE_ENV === 'test') { console.log('Test seeding: Skipping complex data import (not needed for basic tests)'); return; } const shouldImportSeedData = await isFirstRun(); if (shouldImportSeedData) { try { console.log('Setting up the template...'); await importSeedData(); console.log('Ready to go'); } catch (error) { console.log('Could not import seed data'); console.error(error); } } } // Allow usage both as a CLI and as a library from tests if (require.main === module) { main().catch((error) => { console.error(error); process.exit(1); }); } module.exports = { seedExampleApp }; ``` 2. 在测试工具中,在 `TEST_SEED=true` 时调用该函数(参见 [主要测试工具](#main-test-harness) 代码示例中高亮的第 313-321 行)。 ¥In the test harness, call the function when `TEST_SEED=true` (see lines 313-321 highlighted in the code example from the [main test harness](#main-test-harness)). 3. 启用种子功能运行测试: ¥Run your tests with seeding enabled: 种子功能在 Strapi 启动后运行,因此服务、权限和上传功能均可用。 ¥Seeding runs after Strapi starts, so services, permissions, and uploads are available. 建议保持种子的确定性以确保断言的稳定性。如果你发布条目,请优先使用固定时间戳或对结构属性进行断言,而不是临时日期。 ¥It's recommended to keep seeds deterministic to ensure stable assertions. If you publish entries, prefer fixed timestamps or assert on structural properties rather than transient dates. ## 创建冒烟测试 {#create-smoke-tests} ¥Create smoke tests 安装好测试工具后,你可以通过添加一个包含以下冒烟测试的最小 Jest 套件来确认 Strapi 是否正确启动。 ¥With the harness in place you can confirm Strapi boots correctly by adding a minimal Jest suite with the following **smoke tests** 在 `tests/app.test.js` 中如下所示: ¥in a `tests/app.test.js` as follows: ```js title="./tests/app.test.js" const { setupStrapi, cleanupStrapi } = require('./strapi'); /** this code is called once before any test is called */ beforeAll(async () => { await setupStrapi(); // Singleton so it can be called many times }); /** this code is called once before all the tests are finished */ afterAll(async () => { await cleanupStrapi(); }); it('strapi is defined', () => { expect(strapi).toBeDefined(); }); require('./hello'); require('./user'); ``` 运行 `yarn test` 或 `npm run test` 应该会得到: ¥Running `yarn test` or `npm run test` should now yield: ```bash PASS tests/create-service.test.js PASS tests/todo-controller.test.js Test Suites: 6 passed, 6 total Tests: 7 passed, 7 total Snapshots: 0 total Time: 7.952 s Ran all test suites. ✨ Done in 8.63s. ``` :::caution 提醒 如果你收到 Jest 的超时错误,请在 `tests/strapi.js` 中或在测试文件顶部调用 `jest.setTimeout(30000)` 来增加超时时间。 ¥If you receive a timeout error for Jest, increase the timeout by calling `jest.setTimeout(30000)` in `tests/strapi.js` or at the top of your test file. ::: ## 测试基本 API 端点 {#test-a-basic-api-endpoint} ¥Test a basic API endpoint 创建包含以下内容的 `tests/hello.test.js`: ¥Create `tests/hello.test.js` with the following: ```js title="./tests/hello.test.js" const { setupStrapi, cleanupStrapi } = require('./strapi'); const request = require('supertest'); beforeAll(async () => { await setupStrapi(); }); afterAll(async () => { await cleanupStrapi(); }); it('should return hello world', async () => { await request(strapi.server.httpServer) .get('/api/hello') .expect(200) .then((data) => { expect(data.text).toBe('Hello World!'); }); }); ``` 工具链会自动注册 `/api/hello` 路由,因此测试只需发出请求即可。 ¥The harness registers the `/api/hello` route automatically, so the test only has to make the request. ## 测试 API 身份验证 {#test-api-authentication} ¥Test API authentication Strapi 使用 JWT 令牌来处理身份验证。我们将创建一个具有已知用户名和密码的用户,并使用这些凭据进行身份验证并获取 JWT 令牌。工具链中已修补的 `user.add` 助手程序可确保自动应用经过身份验证的角色。 ¥Strapi uses a JWT token to handle authentication. We will create one user with a known username and password, and use these credentials to authenticate and get a JWT token. The patched `user.add` helper in the harness ensures the authenticated role is applied automatically. 创建 `tests/auth.test.js`: ¥Create `tests/auth.test.js`: ```js title="./tests/auth.test.js" const { setupStrapi, cleanupStrapi } = require('./strapi'); const request = require('supertest'); beforeAll(async () => { await setupStrapi(); }); afterAll(async () => { await cleanupStrapi(); }); // User mock data const mockUserData = { username: 'tester', email: 'tester@strapi.com', provider: 'local', password: '1234abc', confirmed: true, blocked: null, }; it('should login user and return JWT token', async () => { await strapi.plugins['users-permissions'].services.user.add({ ...mockUserData, }); await request(strapi.server.httpServer) .post('/api/auth/local') .set('accept', 'application/json') .set('Content-Type', 'application/json') .send({ identifier: mockUserData.email, password: mockUserData.password, }) .expect('Content-Type', /json/) .expect(200) .then((data) => { expect(data.body.jwt).toBeDefined(); }); }); ``` 你可以使用返回的 JWT 令牌向 API 发出经过身份验证的请求。使用此示例,你可以添加更多测试来验证身份验证和授权是否按预期工作。 ¥You can use the JWT token returned to make authenticated requests to the API. Using this example, you can add more tests to validate that the authentication and authorization are working as expected. ## 使用用户权限进行高级 API 测试 {#advanced-api-testing-with-user-permissions} ¥Advanced API testing with user permissions 创建 API 测试时,你很可能需要测试需要身份验证的端点。在下面的示例中,我们将实现一个辅助函数来获取和使用 JWT 令牌。 ¥When you create API tests, you will most likely need to test endpoints that require authentication. In the following example we will implement a helper to get and use the JWT token. 创建 `tests/user.test.js`: ¥Create `tests/user.test.js`: ```js title="./tests/user.test.js" const { setupStrapi, cleanupStrapi } = require('./strapi'); const request = require('supertest'); beforeAll(async () => { await setupStrapi(); }); afterAll(async () => { await cleanupStrapi(); }); let authenticatedUser = {}; // User mock data const mockUserData = { username: 'tester', email: 'tester@strapi.com', provider: 'local', password: '1234abc', confirmed: true, blocked: null, }; describe('User API', () => { beforeAll(async () => { await strapi.plugins['users-permissions'].services.user.add({ ...mockUserData, }); const response = await request(strapi.server.httpServer) .post('/api/auth/local') .set('accept', 'application/json') .set('Content-Type', 'application/json') .send({ identifier: mockUserData.email, password: mockUserData.password, }); authenticatedUser.jwt = response.body.jwt; authenticatedUser.user = response.body.user; }); it('should return users data for authenticated user', async () => { await request(strapi.server.httpServer) .get('/api/users/me') .set('accept', 'application/json') .set('Content-Type', 'application/json') .set('Authorization', 'Bearer ' + authenticatedUser.jwt) .expect('Content-Type', /json/) .expect(200) .then((data) => { expect(data.body).toBeDefined(); expect(data.body.id).toBe(authenticatedUser.user.id); expect(data.body.username).toBe(authenticatedUser.user.username); expect(data.body.email).toBe(authenticatedUser.user.email); }); }); }); ``` ## 使用 GitHub Actions 自动化测试 {#automate-tests-with-github-actions} ¥Automate tests with GitHub Actions 更进一步,你可以使用 在每个推送和拉取请求上自动运行 Jest 测试套件。在你的项目中创建一个 `.github/workflows/test.yaml` 文件,并添加如下工作流: ¥To go further, you can run your Jest test suite automatically on every push and pull request with . Create a `.github/workflows/test.yaml` file in your project and add the workflow as follows: ```yaml title="./.github/workflows/test.yaml" name: 'Tests' on: pull_request: push: jobs: run-tests: name: Run Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install modules run: npm ci - name: Run Tests run: npm run test ``` 将持续集成与单元测试和 API 测试相结合,有助于在回归测试进入生产环境之前防止其发生。 ¥Pairing continuous integration with your unit and API tests helps prevent regressions before they reach production. # TypeScript Source: https://docs.strapi.io/cms/typescript # TypeScript {#typescript} * 使用提供的 [conversion](/cms/typescript/adding-support-to-existing-project) 步骤向现有 Strapi 项目添加 TypeScript 支持。 ¥Add TypeScript support to an existing Strapi project using the provided [conversion](/cms/typescript/adding-support-to-existing-project) steps.
:::strapi 接下来做什么? * 了解基于 TypeScript 的 Strapi 项目的 [structure](/cms/project-structure) ¥Understand the [structure](/cms/project-structure) of a TypeScript-based Strapi project * 了解与 TypeScript 相关的 [配置选项](/cms/configurations/typescript) 选项 ¥Learn about the [configuration options](/cms/configurations/typescript) options related to TypeScript * 深入研究与 TypeScript 相关的开发 [选项和功能](/cms/typescript/development) ¥Deep dive into TypeScript-related development [options and features](/cms/typescript/development) * 阅读 [guides](/cms/typescript/guides) 了解具体用例 ¥Read the [guides](/cms/typescript/guides) for specific use cases ::: # TypeScript 开发 Source: https://docs.strapi.io/cms/typescript/development # 使用 Strapi 进行 TypeScript 开发 {#typescript-development-with-strapi} ¥TypeScript development with Strapi 在使用 Strapi 开发基于 [TypeScript](/cms/typescript) 的应用时,你可以: ¥While developing a [TypeScript](/cms/typescript)-based application with Strapi, you can: * 使用自动补齐功能访问 [`Strapi` 的类型](#use-strapi-typescript-typings) 类, ¥access [typings for the `Strapi`](#use-strapi-typescript-typings) class with autocompletion, * [生成类型](#generate-typings-for-content-types-schemas) 适用于你的项目内容类型, ¥[generate typings](#generate-typings-for-content-types-schemas) for your project's content-types, * [以编程方式启动 Strapi](#start-strapi-programmatically), ¥[start Strapi programmatically](#start-strapi-programmatically), * 并遵循一些针对 [插件开发](#develop-a-plugin-using-typescript) 的 TypeScript 特定说明。 ¥and follow some TypeScript-specific instructions for [plugins development](#develop-a-plugin-using-typescript). :::strapi 文档和条目 有关如何使用基于 TypeScript 的项目操作文档和条目的更多信息和最佳实践,请参阅 [专用指南](/cms/typescript/documents-and-entries)。 ¥More information and best practices on how to manipulate documents and entries with a TypeScript-based project can be found in the [dedicated guide](/cms/typescript/documents-and-entries). ::: ## 使用 `Strapi` TypeScript 类型 {#use-strapi-typescript-typings} ¥Use `Strapi` TypeScript typings Strapi 提供了 `Strapi` 类上的类型以增强 TypeScript 开发体验。这些类型具有自动补齐功能,可以在开发时自动提供建议。 ¥Strapi provides typings on the `Strapi` class to enhance the TypeScript development experience. These typings come with an autocomplete feature that automatically offers suggestions while developing. 要在开发 Strapi 应用时体验基于 TypeScript 的自动补齐功能,你可以尝试以下操作: ¥To experience TypeScript-based autocomplete while developing Strapi applications, you could try the following: 1. 从你的代码编辑器打开 `./src/index.ts` 文件。 ¥Open the `./src/index.ts` file from your code editor. 2. 从 `@strapi/strapi` 导入 `Core` 类型,并在全局 `register` 方法中将 `strapi` 参数声明为类型 `Core.Strapi`: ¥Import the `Core` types from `@strapi/strapi` and declare the `strapi` argument as type `Core.Strapi` within the global `register` method: ```typescript title="./src/index.ts" import type { Core } from '@strapi/strapi'; export default { register({ strapi }: { strapi: Core.Strapi }) { // ... }, }; ``` 3. 在 `register` 方法的主体中,开始键入 `strapi.` 并使用键盘箭头浏览可用属性。 ¥Within the body of the `register` method, start typing `strapi.` and use keyboard arrows to browse the available properties. 4. 从列表中选择 `runLifecyclesFunctions`。 ¥Choose `runLifecyclesFunctions` from the list. 5. 添加 `strapi.runLifecyclesFunctions` 方法后,代码编辑器将返回可用生命周期类型(即 `register`、`bootstrap` 和 `destroy`)的列表。使用键盘箭头选择生命周期之一,代码将自动补齐。 ¥When the `strapi.runLifecyclesFunctions` method is added, a list of available lifecycle types (i.e. `register`, `bootstrap` and `destroy`) are returned by the code editor. Use keyboard arrows to choose one of the lifecycles and the code will autocomplete. ## 为内容类型模式生成类型 {#generate-typings-for-content-types-schemas} ¥Generate typings for content-types schemas 要为你的项目模式生成类型,请使用 [`ts:generate-types` CLI 命令](/cms/cli#strapi-ts)。`ts:generate-types` 命令在项目根目录中创建文件夹 `types`,其中存储项目的类型。可选的 `--debug` 标志返回生成的模式的详细表。 ¥To generate typings for your project schemas use the [`ts:generate-types` CLI command](/cms/cli#strapi-ts). The `ts:generate-types` command creates the folder `types`, at the project root, which stores the typings for your project. The optional `--debug` flag returns a detailed table of the generated schemas. 要使用 `ts:generate-types`,请在项目根目录的终端中运行以下代码: ¥To use `ts:generate-types`run the following code in a terminal at the project root: :::tip 提示:自动生成类型 通过将 `autogenerate: true` 添加到 [`config/typescript.js|ts` 配置文件](/cms/configurations/typescript#strapi-specific-configuration-for-typescript),可以在服务器重启时自动生成类型。 ¥Types can be automatically generated on server restart by adding `autogenerate: true` to [the `config/typescript.js|ts` configuration file](/cms/configurations/typescript#strapi-specific-configuration-for-typescript). ::: :::tip 提示:在前端应用中使用类型 要在前端应用中使用 Strapi 类型,你可以 ,直到 Strapi 实现官方解决方案。 ¥To use Strapi types in your front-end application, you can until Strapi implements an official solution. ::: ### 修复生成类型的构建问题 {#fix-build-issues-with-the-generated-types} ¥Fix build issues with the generated types 可以排除生成的类型,以便实体服务不使用它们,而是使用不检查内容类型中可用的实际属性的宽松类型。 ¥The generated types can be excluded so that the Entity Service doesn't use them and falls back on looser types that don't check the actual properties available in the content types. 为此,请编辑 Strapi 项目的 `tsconfig.json` 并将 `types/generated/**` 添加到 `exclude` 数组: ¥To do that, edit the `tsconfig.json` of the Strapi project and add `types/generated/**` to the `exclude` array: ```json title="./tsconfig.json" // ... "exclude": [ "node_modules/", "build/", "dist/", ".cache/", ".tmp/", "src/admin/", "**/*.test.ts", "src/plugins/**", "types/generated/**" ] // ... ``` 但是,如果你仍想在项目中使用生成的类型,但又不想让 Strapi 使用它们,则一种解决方法是复制这些生成的类型并将它们粘贴到 `generated` 目录之外(以便在重新生成类型时不会覆盖它们)并从文件底部删除 `declare module '@strapi/types'`。 ¥However, if you still want to use the generated types on your project, but don't want Strapi to use them, a workaround could be to copy those generated types and paste them outside of the `generated` directory (so that they aren't overwritten when the types are regenerated) and remove the `declare module '@strapi/types'` from the bottom of the file. :::warning 警告 类型只能从 `@strapi/strapi` 导入,以避免重大更改。`@strapi/types` 中的类型仅供内部使用,可能会更改,恕不另行通知。 ¥Types should only be imported from `@strapi/strapi` to avoid breaking changes. The types in `@strapi/types` are for internal use only and may change without notice. ::: ## 以编程方式启动 Strapi {#start-strapi-programmatically} ¥Start Strapi programmatically 要在 TypeScript 项目中以编程方式启动 Strapi,Strapi 实例需要已编译的代码位置。本节介绍如何设置和指示编译后的代码目录。 ¥To start Strapi programmatically in a TypeScript project the Strapi instance requires the compiled code location. This section describes how to set and indicate the compiled code directory. ### 使用 `strapi()` 工厂 {#use-the-createstrapi-factory} ¥Use the `strapi()` factory Strapi 可以使用 `strapi()` 工厂以编程方式运行。由于 TypeScript 项目的代码是在特定目录中编译的,因此应将参数 `distDir` 传递给工厂以指示应在何处读取编译后的代码: ¥Strapi can be run programmatically by using the `strapi()` factory. Since the code of TypeScript projects is compiled in a specific directory, the parameter `distDir` should be passed to the factory to indicate where the compiled code should be read: ```js title="./server.js" const strapi = require('@strapi/strapi'); const app = strapi.createStrapi({ distDir: './dist' }); app.start(); ``` ### 使用 `strapi.compile()` 功能 {#use-the-strapicompile-function} ¥Use the `strapi.compile()` function `strapi.compile()` 函数应该主要用于开发需要启动 Strapi 实例并检测项目是否包含 TypeScript 代码的工具。`strapi.compile()` 自动检测项目语言。如果项目代码包含任何 TypeScript 代码,`strapi.compile()` 会编译该代码并返回一个上下文,其中包含 Strapi 所需目录的特定值: ¥The `strapi.compile()` function should be mostly used for developing tools that need to start a Strapi instance and detect whether the project includes TypeScript code. `strapi.compile()` automatically detects the project language. If the project code contains any TypeScript code, `strapi.compile()` compiles the code and returns a context with specific values for the directories that Strapi requires: ```js const strapi = require('@strapi/strapi'); strapi.compile().then(appContext => strapi(appContext).start()); ``` ## 使用 TypeScript 开发插件 {#develop-a-plugin-using-typescript} ¥Develop a plugin using TypeScript 可以在 [插件开发文档](/cms/plugins-development/developing-plugins) 之后生成新插件,确保在 CLI 工具提示时选择 "TypeScript"。 ¥New plugins can be generated following the [plugins development documentation](/cms/plugins-development/developing-plugins), ensuring you select "TypeScript" when prompted by the CLI tool. TypeScript 应用有两个重要的区别: ¥There are 2 important distinctions for TypeScript applications: * 创建插件后,在插件目录 `src/admin/plugins/[my-plugin-name]` 中运行 `yarn` 或 `npm install` 来安装插件的依赖。 ¥After creating the plugin, run `yarn` or `npm install` in the plugin directory `src/admin/plugins/[my-plugin-name]` to install the dependencies for the plugin. * 在插件目录 `src/admin/plugins/[my-plugin-name]` 中运行 `yarn build` 或 `npm run build` 以构建包含插件的管理面板。 ¥Run `yarn build` or `npm run build` in the plugin directory `src/admin/plugins/[my-plugin-name]` to build the admin panel including the plugin. :::note 注意 初次安装后无需重复执行 `yarn` 或 `npm install` 命令。`yarn build` 或 `npm run build` 命令是实现影响管理面板的任何插件开发所必需的。 ¥It is not necessary to repeat the `yarn` or `npm install` command after the initial installation. The `yarn build` or `npm run build` command is necessary to implement any plugin development that affects the admin panel. ::: # TypeScript 指南 Source: https://docs.strapi.io/cms/typescript/guides # TypeScript 指南 {#typescript-guides} ¥TypeScript guides 以下指南将帮助你了解 [基于 Typescript](/cms/typescript) Strapi 项目的具体方面。 ¥The following guides will help you on specific aspects of a [Typescript-based](/cms/typescript) Strapi project. # 升级工具 Source: https://docs.strapi.io/cms/upgrade-tool # 升级工具 {#upgrade-tool} ¥Upgrade tool 升级工具帮助 Strapi 用户将其 Strapi 应用依赖和代码升级到特定版本。 ¥The upgrade tool assists Strapi users in upgrading their Strapi application dependencies and code to a specific version. 运行升级工具会触发应用依赖的更新、它们的安装以及一系列代码修改