diff --git a/docs/en/controllers.md b/docs/en/controllers.md
index 01976a3892..da901077f3 100644
--- a/docs/en/controllers.md
+++ b/docs/en/controllers.md
@@ -7,32 +7,47 @@ description: "Learn CakePHP controllers: handle requests, render views, manage c
`class` Cake\\Controller\\**Controller**
-Controllers are the 'C' in MVC. After routing has been applied and the correct
-controller has been found, your controller's action is called. Your controller
-should handle interpreting the request data, making sure the correct models
-are called, and the right response or view is rendered. Controllers can be
-thought of as middle layer between the Model and View. You want to keep your
-controllers thin, and your models fat. This will help you reuse
-your code and makes your code easier to test.
-
-Commonly, a controller is used to manage the logic around a single model. For
-example, if you were building a site for an online bakery, you might have a
-RecipesController managing your recipes and an IngredientsController managing your
-ingredients. However, it's also possible to have controllers work with more than
-one model. In CakePHP, a controller is named after the primary model it
-handles.
-
-Your application's controllers extend the `AppController` class, which in turn
-extends the core `Controller` class. The `AppController`
-class can be defined in **src/Controller/AppController.php** and it should
-contain methods that are shared between all of your application's controllers.
-
-Controllers provide a number of methods that handle requests. These are called
-*actions*. By default, each public method in
-a controller is an action, and is accessible from a URL. An action is responsible
-for interpreting the request and creating the response. Usually responses are
-in the form of a rendered view, but there are other ways to create responses as
-well.
+Controllers are the 'C' in MVC. After routing is applied and the correct
+controller is found, your controller's action is called. Your controller
+should interpret the request, ensure the right models are called, and return
+the appropriate response or view. Controllers sit between Model and View.
+
+::: tip Keep Controllers Thin
+Move heavy business logic into models and services. Thin controllers are easier
+to test and reuse.
+:::
+
+Commonly, a controller manages logic around a single model. For example, for
+an online bakery you might have a RecipesController managing recipes and an
+IngredientsController managing ingredients. However, it's also possible to have
+controllers work with more than one model. In CakePHP, a controller is named
+after the primary model it handles.
+
+::: info At a Glance
+
+- Controllers coordinate request handling, model calls, and responses.
+- Each public method is an action by default.
+- Shared logic goes into `AppController`.
+
+:::
+
+Your application's controllers extend the `AppController` class, which extends
+the core `Controller` class. The `AppController` class can be defined in
+**src/Controller/AppController.php** and should contain methods shared between
+all of your application's controllers.
+
+Controllers provide methods that handle requests. These are called *actions*.
+By default, each public method in a controller is an action and is accessible
+from a URL. An action interprets the request and creates the response. Usually
+responses are rendered views, but there are other response types as well.
+
+::: details Naming and Conventions
+
+- Controller names are plural, e.g. `RecipesController`.
+- Action names map to view templates by convention.
+- Use `AppController` for shared behavior.
+
+:::
@@ -88,6 +103,14 @@ CakePHP puts all the important request information into the `$this->request`
property. See the section on [Cake Request](controllers/request-response#cake-request) for more information on the
CakePHP request object.
+::: info Request Flow Summary
+
+- Routes map URLs to a controller/action.
+- The request data is available via `$this->request`.
+- The action returns a response (often a rendered view).
+
+:::
+
## Controller Actions
Controller actions are responsible for converting the request parameters into a
@@ -138,6 +161,11 @@ If for some reason you'd like to skip the default behavior, you can return a
`Cake\Http\Response` object from the action with the fully
created response.
+::: tip Explicit Responses
+Return a `Response` when you need full control (JSON, file downloads, or
+custom status codes).
+:::
+
In order for you to use a controller effectively in your own application, we'll
cover some of the core attributes and methods provided by CakePHP's controllers.
@@ -158,17 +186,20 @@ The `Controller::set()` method is the main way to send data from your
controller to your view. Once you've used `Controller::set()`, the variable
can be accessed in your view:
-```php
-// First you pass data from the controller:
+::: code-group
+```php [Controller]
+// First you pass data from the controller:
$this->set('color', 'pink');
+```
+```php [Template]
// Then, in the view, you can utilize the data:
-?>
-
You have selected = h($color) ?> icing for the cake.
```
+:::
+
The `Controller::set()` method also takes an
associative array as its first parameter. This can often be a quick way to
assign a set of information to the view:
@@ -190,6 +221,11 @@ Keep in mind that view vars are shared among all parts rendered by your view.
They will be available in all parts of the view: the template, the layout and
all elements inside the former two.
+::: tip View Data Scope
+View variables are shared with the layout and elements. Prefer specific keys
+to avoid accidental collisions.
+:::
+
### Setting View Options
If you want to customize the view class, layout/template paths, helpers or the
@@ -228,6 +264,13 @@ Available strategies are:
You can retrieve the current strategy using `getConfigMergeStrategy()`.
+::: details When to Change Merge Strategy
+
+- Use shallow merges for small, explicit overrides.
+- Use deep merges when you want to extend nested defaults.
+
+:::
+
::: info Added in version 5.3.0
`ViewBuilder::setConfigMergeStrategy()` and `ViewBuilder::getConfigMergeStrategy()` were added.
:::
@@ -265,25 +308,22 @@ Although CakePHP will automatically call it after every action's logic
an alternate view file by specifying a view file name as first argument of
`Controller::render()` method.
+::: tip Skipping Auto-Render
+Call `$this->disableAutoRender()` when the action fully handles the response.
+:::
+
If `$view` starts with '/', it is assumed to be a view or
element file relative to the **templates** folder. This allows
direct rendering of elements, very useful in AJAX calls:
-```php
+::: code-group
+
+```php [Element]
// Render the element in templates/element/ajaxreturn.php
-$this->render('/element/ajaxreturn');
+return $this->render('/element/ajaxreturn');
```
-The second parameter `$layout` of `Controller::render()` allows you to specify the layout
-with which the view is rendered.
-
-#### Rendering a Specific Template
-
-In your controller, you may want to render a different view than the
-conventional one. You can do this by calling `Controller::render()` directly. Once you
-have called `Controller::render()`, CakePHP will not try to re-render the view:
-
-```php
+```php [Custom Template]
namespace App\Controller;
class PostsController extends AppController
@@ -295,14 +335,7 @@ class PostsController extends AppController
}
```
-This would render **templates/Posts/custom_file.php** instead of
-**templates/Posts/my_action.php**.
-
-You can also render views inside plugins using the following syntax:
-`$this->render('PluginName.PluginController/custom_file')`.
-For example:
-
-```php
+```php [Plugin Template]
namespace App\Controller;
class PostsController extends AppController
@@ -314,7 +347,22 @@ class PostsController extends AppController
}
```
-This would render **plugins/Users/templates/UserDetails/custom_file.php**
+:::
+
+The second parameter `$layout` of `Controller::render()` allows you to specify the layout
+with which the view is rendered.
+
+#### Rendering a Specific Template
+
+In your controller, you may want to render a different view than the
+conventional one. You can do this by calling `Controller::render()` directly.
+Once you have called `Controller::render()`, CakePHP will not try to re-render
+the view.
+
+This renders **templates/Posts/custom_file.php** instead of
+**templates/Posts/my_action.php**. Rendering plugin templates uses the syntax
+`$this->render('Users.UserDetails/custom_file')` and renders
+**plugins/Users/templates/UserDetails/custom_file.php**.
@@ -330,6 +378,10 @@ render an HTML view or render a JSON or XML response. To define the list of
supported view classes for a controller is done with the `addViewClasses()`
method:
+::: info Content Negotiation
+Use `addViewClasses()` to serve multiple formats from the same action.
+:::
+
```php
namespace App\Controller;
@@ -450,7 +502,9 @@ controller action and rendering a view.
You can redirect using `routing array` values:
-```php
+::: code-group
+
+```php [Array URL]
return $this->redirect([
'controller' => 'Orders',
'action' => 'confirm',
@@ -463,20 +517,20 @@ return $this->redirect([
]);
```
-Or using a relative or absolute URL:
-
-```php
+```php [Relative URL]
return $this->redirect('/orders/confirm');
+```
+```php [Absolute URL]
return $this->redirect('https://www.example.com');
```
-Or to the referer page:
-
-```php
+```php [Referer]
return $this->redirect($this->referer());
```
+:::
+
By using the second parameter you can define a status code for your redirect:
```php
@@ -573,9 +627,9 @@ public function initialize(): void
## Request Life-cycle Callbacks
CakePHP controllers trigger several events/callbacks that you can use to insert
-logic around the request life-cycle:
+logic around the request life-cycle.
-### Event List
+::: details Event List
- `Controller.initialize`
- `Controller.startup`
@@ -583,10 +637,12 @@ logic around the request life-cycle:
- `Controller.beforeRender`
- `Controller.shutdown`
+:::
+
### Controller Callback Methods
-By default, the following callback methods are connected to related events if the
-methods are implemented by your controllers
+By default, the following callback methods are connected to related events if
+the methods are implemented by your controllers.
#### beforeFilter()
@@ -623,13 +679,12 @@ To redirect from within a controller callback method you can use the following:
```php
public function beforeFilter(EventInterface $event): void
{
- if (...) {
+ if ($this->request->getParam('prefix') !== 'Admin') {
$event->setResult($this->redirect('/'));
return;
}
-
- ...
+ // Normal request handling continues.
}
```