Skip to content

Commit 692b7cb

Browse files
meganelachenyactions-user
authored andcommitted
Add information on controllers & routes + Fix some examples (#2797)
1 parent b1b705d commit 692b7cb

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

docusaurus/docs/cms/backend-customization/controllers.md

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ module.exports = {
164164
{
165165
method: 'GET',
166166
path: '/hello',
167-
handler: 'hello.index',
167+
handler: 'api::hello.hello.index',
168168
}
169169
]
170170
}
171171
```
172172

173-
```js "title="./src/api/hello/controllers/hello.js"
173+
```js title="./src/api/hello/controllers/hello.js"
174174

175175
module.exports = {
176176
async index(ctx, next) { // called by GET /hello
@@ -183,14 +183,14 @@ module.exports = {
183183

184184
<TabItem value="ts" label="TypeScript">
185185

186-
```js "title="./src/api/hello/routes/hello.ts"
186+
```js title="./src/api/hello/routes/hello.ts"
187187

188188
export default {
189189
routes: [
190190
{
191191
method: 'GET',
192192
path: '/hello',
193-
handler: 'hello.index',
193+
handler: 'api::hello.hello.index',
194194
}
195195
]
196196
}
@@ -219,6 +219,37 @@ When a new [content-type](/cms/backend-customization/models#content-types) is cr
219219
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.
220220
:::
221221

222+
### Controllers & Routes: How routes reach controller actions
223+
224+
- 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.
225+
- 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 `<scope>::<api-or-plugin-name>.<controllerName>.<actionName>` (e.g. `api::restaurant.restaurant.exampleAction` for an API controller or `plugin::menus.menu.exampleAction` for a plugin controller).
226+
- 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.
227+
228+
The example below adds a new controller action and exposes it through a custom route without duplicating the existing CRUD route definitions:
229+
230+
```js title="./src/api/restaurant/controllers/restaurant.js"
231+
const { createCoreController } = require('@strapi/strapi').factories;
232+
233+
module.exports = createCoreController('api::restaurant.restaurant', ({ strapi }) => ({
234+
async exampleAction(ctx) {
235+
const specials = await strapi.service('api::restaurant.restaurant').find({ filters: { isSpecial: true } });
236+
return this.transformResponse(specials.results);
237+
},
238+
}));
239+
```
240+
241+
```js title="./src/api/restaurant/routes/01-custom-restaurant.js"
242+
module.exports = {
243+
routes: [
244+
{
245+
method: 'GET',
246+
path: '/restaurants/specials',
247+
handler: 'api::restaurant.restaurant.exampleAction',
248+
},
249+
],
250+
};
251+
```
252+
222253
### Sanitization and Validation in controllers {#sanitization-and-validation-in-controllers}
223254

224255
:::warning

docusaurus/docs/cms/backend-customization/routes.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ Requests sent to Strapi on any URL are handled by routes. By default, Strapi gen
2929

3030
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)).
3131

32+
:::tip
33+
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.
34+
:::
35+
3236
<figure style={{width: '100%', margin: '0'}}>
3337
<img src="/img/assets/backend-customization/diagram-routes.png" alt="Simplified Strapi backend diagram with routes highlighted" />
3438
<em><figcaption style={{fontSize: '12px'}}>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, <a href="/cms/backend-customization#interactive-diagram">interactive diagram</a>.</figcaption></em>
@@ -174,7 +178,7 @@ Creating custom routers consists in creating a file that exports an array of obj
174178
| -------------------------- | -------------------------------------------------------------------------------- | -------- |
175179
| `method` | Method associated to the route (i.e. `GET`, `POST`, `PUT`, `DELETE` or `PATCH`) | `String` |
176180
| `path` | Path to reach, starting with a forward-leading slash (e.g. `/articles`)| `String` |
177-
| `handler` | Function to execute when the route is reached.<br/>Should follow this syntax: `<controllerName>.<actionName>` | `String` |
181+
| `handler` | Function to execute when the route is reached.<br/>Use the fully-qualified syntax `api::api-name.controllerName.actionName` (or `plugin::plugin-name.controllerName.actionName`). The short `<controllerName>.<actionName>` form for legacy projects also works. | `String` |
178182
| `config`<br /><br />_Optional_ | Configuration to handle [policies](#policies), [middlewares](#middlewares) and [public availability](#public-routes) for the route<br/><br/> | `Object` |
179183

180184
<br/>
@@ -185,6 +189,15 @@ Dynamic routes can be created using parameters and regular expressions. These pa
185189
Routes files are loaded in alphabetical order. To load custom routes before core routes, make sure to name custom routes appropriately (e.g. `01-custom-routes.js` and `02-core-routes.js`).
186190
:::
187191

192+
:::info Controller handler naming reference
193+
The `handler` string acts as a pointer to the controller action that should run for the route. Strapi supports the following formats:
194+
195+
- API controllers: `api::<api-name>.<controllerName>.<actionName>` (e.g. `api::restaurant.restaurant.exampleAction`). The `<controllerName>` comes from the controller filename inside `./src/api/<api-name>/controllers/`.
196+
- Plugin controllers: `plugin::<plugin-name>.<controllerName>.<actionName>` when the controller lives in a plugin.
197+
198+
For backwards compatibility, Strapi also accepts a short `<controllerName>.<actionName>` string for API controllers, but using the fully-qualified form makes the route more explicit and avoids naming collisions across APIs and plugins.
199+
:::
200+
188201
<details>
189202

190203
<summary>Example of a custom router using URL parameters and regular expressions for routes</summary>
@@ -202,12 +215,12 @@ module.exports = {
202215
{ // Path defined with an URL parameter
203216
method: 'POST',
204217
path: '/restaurants/:id/review',
205-
handler: 'restaurant.review',
218+
handler: 'api::restaurant.restaurant.review',
206219
},
207220
{ // Path defined with a regular expression
208221
method: 'GET',
209222
path: '/restaurants/:category([a-z]+)', // Only match when the URL parameter is composed of lowercase letters
210-
handler: 'restaurant.findByCategory',
223+
handler: 'api::restaurant.restaurant.findByCategory',
211224
}
212225
]
213226
}
@@ -224,12 +237,12 @@ export default {
224237
{ // Path defined with a URL parameter
225238
method: 'GET',
226239
path: '/restaurants/:category/:id',
227-
handler: 'Restaurant.findOneByCategory',
240+
handler: 'api::restaurant.restaurant.findOneByCategory',
228241
},
229242
{ // Path defined with a regular expression
230243
method: 'GET',
231244
path: '/restaurants/:region(\\d{2}|\\d{3})/:id', // Only match when the first parameter contains 2 or 3 digits.
232-
handler: 'Restaurant.findOneByRegion',
245+
handler: 'api::restaurant.restaurant.findOneByRegion',
233246
}
234247
]
235248
}

0 commit comments

Comments
 (0)