控制器
¥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.js
file (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.