strapi/docs/3.0.0-beta.x/concepts/controllers.md

267 lines
6.1 KiB
Markdown
Raw Normal View History

# Controllers
## Concept
Controllers are JavaScript files which contain a set of methods called **actions** reached by the client according to the requested route. It means that every time a client requests the route, the action performs the business logic coded and sends back the response. They represent the _C_ in the _MVC_ pattern. In most cases, the controllers will contain the bulk of a project's business logic.
```js
module.exports = {
// GET /hello
index: async ctx => {
ctx.send('Hello World!');
},
};
```
In this example, any time a web browser is pointed to the `/hello` URL on your app, the page will display the text: `Hello World!`.
### Where are the controllers defined?
The controllers are defined in each `./api/**/controllers/` folders. Every JavaScript file put in these folders will be loaded as a controller. They are also available through the `strapi.controllers` and `strapi.api.**.controllers` global variables. By convention, controllers' names should be Pascal-cased, so that every word in the file (include the first one) is capitalized `User.js`, `LegalEntity.js`.
2019-05-16 11:14:32 +02:00
## Core controllers
2019-05-16 15:00:55 +02:00
When you create a new Content type or a new model. You will see a new empty controller has been created. It is because Strapi builds a generic controller for your models by default and allows you to override and extend it in the generated files.
2019-05-16 11:14:32 +02:00
### Extending a Model Controller
2019-05-16 15:00:55 +02:00
Here are the core methods (and their current implementation).
2019-05-16 11:14:32 +02:00
You can simply copy and paste this code in your own controller file to customize the methods.
2019-05-16 11:35:19 +02:00
::: warning
In the following example we will consider your controller, service and model is named `restaurant`
2019-05-16 11:35:19 +02:00
:::
#### Utils
First require the utility functions
```js
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
```
- `parseMultipartData`: This function parses strapi's formData format.
- `sanitizeEntity`: This function removes all private fields from the model and its relations.
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
::: tab "find" id="find"
2019-05-16 11:14:32 +02:00
#### `find`
```js
2019-10-23 11:19:38 +02:00
const { sanitizeEntity } = require('strapi-utils');
2019-05-16 11:14:32 +02:00
module.exports = {
/**
* Retrieve records.
*
2019-05-16 11:35:19 +02:00
* @return {Array}
2019-05-16 11:14:32 +02:00
*/
async find(ctx) {
let entities;
2019-05-16 11:14:32 +02:00
if (ctx.query._q) {
2019-10-23 11:19:38 +02:00
entities = await strapi.services.restaurant.search(ctx.query);
} else {
2019-10-23 11:19:38 +02:00
entities = await strapi.services.restaurant.find(ctx.query);
2019-05-16 11:14:32 +02:00
}
return entities.map(entity => sanitizeEntity(entity, { model }));
2019-05-16 11:35:19 +02:00
},
};
```
:::
::: tab "findOne" id="findone"
2019-05-16 11:35:19 +02:00
#### `findOne`
```js
2019-10-23 11:19:38 +02:00
const { sanitizeEntity } = require('strapi-utils');
2019-05-16 11:35:19 +02:00
module.exports = {
/**
* Retrieve a record.
*
* @return {Object}
*/
async findOne(ctx) {
2019-10-23 11:19:38 +02:00
const entity = await strapi.services.restaurant.findOne(ctx.params);
return sanitizeEntity(entity, { model });
2019-05-16 11:35:19 +02:00
},
};
```
:::
::: tab "count" id="count"
2019-05-16 11:35:19 +02:00
#### `count`
```js
module.exports = {
/**
* Count records.
*
* @return {Number}
*/
count(ctx) {
if (ctx.query._q) {
2019-10-23 11:19:38 +02:00
return strapi.services.restaurant.countSearch(ctx.query);
2019-05-16 11:35:19 +02:00
}
2019-10-23 11:19:38 +02:00
return strapi.services.restaurant.count(ctx.query);
2019-05-16 11:35:19 +02:00
},
};
```
:::
::: tab "create" id="create"
2019-05-16 11:35:19 +02:00
#### `create`
```js
2019-10-23 11:19:38 +02:00
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
2019-05-16 11:35:19 +02:00
module.exports = {
/**
* Create a record.
*
* @return {Object}
*/
async create(ctx) {
let entity;
2019-08-12 16:58:18 +02:00
if (ctx.is('multipart')) {
const { data, files } = parseMultipartData(ctx);
2019-10-23 11:19:38 +02:00
entity = await strapi.services.restaurant.create(data, { files });
} else {
2019-10-23 11:19:38 +02:00
entity = await strapi.services.restaurant.create(ctx.request.body);
2019-08-12 16:58:18 +02:00
}
return sanitizeEntity(entity, { model });
2019-05-16 11:35:19 +02:00
},
};
```
:::
::: tab "update" id="update"
2019-05-16 11:35:19 +02:00
#### `update`
```js
2019-10-23 11:19:38 +02:00
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
2019-05-16 11:35:19 +02:00
module.exports = {
/**
* Update a record.
*
* @return {Object}
*/
async update(ctx) {
let entity;
2019-08-12 16:58:18 +02:00
if (ctx.is('multipart')) {
const { data, files } = parseMultipartData(ctx);
2019-10-23 11:19:38 +02:00
entity = await strapi.services.restaurant.update(ctx.params, data, {
files,
});
} else {
2019-10-23 11:19:38 +02:00
entity = await strapi.services.restaurant.update(
ctx.params,
ctx.request.body
);
2019-08-12 16:58:18 +02:00
}
return sanitizeEntity(entity, { model });
2019-05-16 11:35:19 +02:00
},
};
```
:::
::: tab "delete" id="delete"
2019-05-16 11:35:19 +02:00
#### `delete`
```js
2019-10-23 11:19:38 +02:00
const { sanitizeEntity } = require('strapi-utils');
2019-05-16 11:35:19 +02:00
module.exports = {
/**
* delete a record.
*
* @return {Object}
*/
async delete(ctx) {
2019-10-23 11:19:38 +02:00
const entity = await strapi.services.restaurant.delete(ctx.params);
return sanitizeEntity(entity, { model });
2019-05-16 11:14:32 +02:00
},
};
```
:::
::::
2019-05-16 11:14:32 +02:00
## Custom controllers
2019-05-16 11:35:19 +02:00
You can also create custom controllers to build your own business logic and API endpoints.
2019-05-16 11:14:32 +02:00
2019-05-16 15:00:55 +02:00
### How to create a custom controller
There are two ways to create a controller:
- Using the CLI `strapi generate:controller restaurant`. Read the [CLI documentation](../cli/CLI.md#strapi-generatecontroller) for more information.
2019-05-16 11:14:32 +02:00
- Manually create a JavaScript file in `./api/**/controllers`.
### Adding Endpoints
Each controllers action must be an `async` function.
Every action receives a `context` (`ctx`) object as first parameter containing the [request context](./requests-responses.md) and the [response context](./requests-responses.md).
2019-05-16 11:14:32 +02:00
::: note
Every action must be referenced by a route.
:::
### Example
2019-05-16 11:14:32 +02:00
In this example, we are defining a specific route in `./api/hello/config/routes.json` that takes `Hello.index` as handler.
2019-05-16 11:14:32 +02:00
It means that every time a request `GET /hello` is sent to the server, Strapi will call the `index` action in the `Hello.js` controller.
Our `index` action will return `Hello World!`. You can also return a JSON object.
**Path —** `./api/hello/config/routes.json`.
2019-05-16 11:14:32 +02:00
```json
{
"routes": [
{
"method": "GET",
"path": "/hello",
"handler": "Hello.index"
}
]
}
```
**Path —** `./api/hello/controllers/Hello.js`.
2019-05-16 11:14:32 +02:00
```js
module.exports = {
// GET /hello
2019-05-16 11:14:32 +02:00
index: async ctx => {
ctx.send('Hello World!');
2019-05-16 11:14:32 +02:00
},
};
```
::: note
A route handler can only access the controllers defined in the `./api/**/controllers` folders.
:::