控制器
¥Controllers
Page summary:
Controllers bundle actions that handle business logic for each route within Strapi’s MVC pattern. This documentation demonstrates generating controllers, extending core ones with
createCoreController, and delegating heavy logic to services.
控制器是 JavaScript 文件,其中包含一组称为操作的方法,客户端根据请求的 route。每当客户端请求路由时,该操作都会执行业务逻辑代码并发回 response。控制器代表模型-视图-控制器 (MVC) 模式中的 C。
¥Controllers are JavaScript files that contain a set of methods, called actions, reached by the client according to the requested route. Whenever a client requests the route, the action performs the business logic code and sends back the response. Controllers represent the C in the model-view-controller (MVC) pattern.
在大多数情况下,控制器将包含项目的大部分业务逻辑。但随着控制器的逻辑变得越来越复杂,使用 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 to organize the code into re-usable parts.

执行
¥Implementation
控制器可以是 手动生成或添加。Strapi 提供了 createCoreController 工厂功能,可自动生成核心控制器并允许构建自定义控制器或 扩展或替换生成的控制器。
¥Controllers can be generated or added manually. Strapi provides a createCoreController factory function that automatically generates core controllers and allows building custom ones or extend or replace the generated controllers.
添加新控制器
¥Adding a new controller
可以实现一个新的控制器:
¥A new controller can be implemented:
-
¥with the interactive CLI command
strapi generate -
或通过创建 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 文档),它们就可以在其他地方创建¥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 thestrapi-server.jsfile (see Server API for Plugins documentation)
-
- JavaScript
- TypeScript
const { createCoreController } = require('@strapi/strapi').factories;
module.exports = createCoreController('api::restaurant.restaurant', ({ strapi }) => ({
// Method 1: Creating an entirely custom action
async exampleAction(ctx) {
try {
ctx.body = 'ok';
} catch (err) {
ctx.body = err;
}
},
// Method 2: Wrapping a core action (leaves core logic in place)
async find(ctx) {
// some custom logic here
ctx.query = { ...ctx.query, local: 'en' }
// Calling the default core action
const { data, meta } = await super.find(ctx);
// some more custom logic
meta.date = Date.now()
return { data, meta };
},
// Method 3: Replacing a core action with proper sanitization
async find(ctx) {
// validateQuery (optional)
// to throw an error on query params that are invalid or the user does not have access to
await this.validateQuery(ctx);
// sanitizeQuery to remove any query params that are invalid or the user does not have access to
// It is strongly recommended to use sanitizeQuery even if validateQuery is used
const sanitizedQueryParams = await this.sanitizeQuery(ctx);
const { results, pagination } = await strapi.service('api::restaurant.restaurant').find(sanitizedQueryParams);
const sanitizedResults = await this.sanitizeOutput(results, ctx);
return this.transformResponse(sanitizedResults, { pagination });
}
}));
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::restaurant.restaurant', ({ strapi }) => ({
// Method 1: Creating an entirely custom action
async exampleAction(ctx) {
try {
ctx.body = 'ok';
} catch (err) {
ctx.body = err;
}
},
// Method 2: Wrapping a core action (leaves core logic in place)
async find(ctx) {
// some custom logic here
ctx.query = { ...ctx.query, local: 'en' }
// Calling the default core action
const { data, meta } = await super.find(ctx);
// some more custom logic
meta.date = Date.now()
return { data, meta };
},
// Method 3: Replacing a core action with proper sanitization
async find(ctx) {
// validateQuery (optional)
// to throw an error on query params that are invalid or the user does not have access to
await this.validateQuery(ctx);
// sanitizeQuery to remove any query params that are invalid or the user does not have access to
// It is strongly recommended to use sanitizeQuery even if validateQuery is used
const sanitizedQueryParams = await this.sanitizeQuery(ctx);
const { results, pagination } = await strapi.service('api::restaurant.restaurant').find(sanitizedQueryParams);
// sanitizeOutput to ensure the user does not receive any data they do not have access to
const sanitizedResults = await this.sanitizeOutput(results, ctx);
return this.transformResponse(sanitizedResults, { pagination });
}
}));
每个控制器操作可以是 async 或 sync 功能。每个操作都会接收一个上下文对象 (ctx) 作为参数。ctx 包含 请求上下文 和 响应上下文。
¥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 and the response context.
Example: GET /hello route calling a basic controller
定义了具体的 GET /hello route,路由文件的名称(即 index)用于调用控制器处理程序(即 index)。每次向服务器发送 GET /hello 请求时,Strapi 都会调用 hello.js 控制器中的 index 操作,该操作返回 Hello World!:
¥A specific GET /hello route 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!:
- JavaScript
- TypeScript
module.exports = {
routes: [
{
method: 'GET',
path: '/hello',
handler: 'hello.index',
}
]
}
module.exports = {
async index(ctx, next) { // called by GET /hello
ctx.body = 'Hello World!'; // we could also send a JSON
},
};
export default {
routes: [
{
method: 'GET',
path: '/hello',
handler: 'hello.index',
}
]
}
export default {
async index(ctx, next) { // called by GET /hello
ctx.body = 'Hello World!'; // we could also send a JSON
},
};
当创建新的 content-type 时,Strapi 会使用占位符代码构建通用控制器,以供自定义。
¥When a new content-type is created, Strapi builds a generic controller with placeholder code, ready to be customized.
要了解自定义控制器可能的高级用法,请阅读后端自定义示例说明书的 服务和控制器 页。
¥To see a possible advanced usage for custom controllers, read the services and controllers page of the backend customization examples cookbook.