@@ -5,16 +5,15 @@ Symfony follows the philosophy of *"thin controllers and fat models"*. This
5
5
means that controllers should hold just the thin layer of *glue-code *
6
6
needed to coordinate the different parts of the application.
7
7
8
- As a rule of thumb, you should follow the 5-10-20 rule, where controllers should
9
- only define 5 variables or less, contain 10 actions or less and include 20 lines
10
- of code or less in each action. This isn't an exact science, but it should
11
- help you realize when code should be refactored out of the controller and
12
- into a service.
8
+ Your controller methods should just call to other services, trigger some events
9
+ if needed and then return a response, but they should not contain any actual
10
+ business logic. If they do, refactor it out of the controller and into a service.
13
11
14
12
.. best-practice ::
15
13
16
- Make your controller extend the FrameworkBundle base controller and use
17
- annotations to configure routing, caching and security whenever possible.
14
+ Make your controller extend the ``AbstractController `` base controller
15
+ provided by Symfony and use annotations to configure routing, caching and
16
+ security whenever possible.
18
17
19
18
Coupling the controllers to the underlying framework allows you to leverage
20
19
all of its features and increases your productivity.
@@ -33,6 +32,18 @@ Overall, this means you should aggressively decouple your business logic
33
32
from the framework while, at the same time, aggressively coupling your controllers
34
33
and routing *to * the framework in order to get the most out of it.
35
34
35
+ Controller Action Naming
36
+ ------------------------
37
+
38
+ .. best-practice ::
39
+
40
+ Don't add the ``Action `` suffix to the methods of the controller actions.
41
+
42
+ The first Symfony versions required that controller method names ended in
43
+ ``Action `` (e.g. ``newAction() ``, ``showAction() ``). This suffix became optional
44
+ when annotations were introduced for controllers. In modern Symfony applications
45
+ this suffix is neither required nor recommended, so you can safely remove it.
46
+
36
47
Routing Configuration
37
48
---------------------
38
49
@@ -94,32 +105,32 @@ for the homepage of our app:
94
105
namespace App\Controller;
95
106
96
107
use App\Entity\Post;
97
- use Symfony\Bundle\FrameworkBundle\Controller\Controller ;
108
+ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController ;
98
109
use Symfony\Component\Routing\Annotation\Route;
99
110
100
- class DefaultController extends Controller
111
+ class DefaultController extends AbstractController
101
112
{
102
113
/**
103
114
* @Route("/", name="homepage")
104
115
*/
105
- public function indexAction ()
116
+ public function index ()
106
117
{
107
118
$posts = $this->getDoctrine()
108
119
->getRepository(Post::class)
109
120
->findLatest();
110
121
111
- return $this->render('default/index.html.twig', array(
122
+ return $this->render('default/index.html.twig', [
112
123
'posts' => $posts,
113
- ) );
124
+ ] );
114
125
}
115
126
}
116
127
117
128
Fetching Services
118
129
-----------------
119
130
120
- If you extend the base ``Controller `` class, you can access services directly from
121
- the container via ``$this->container->get() `` or ``$this->get() ``. But instead, you
122
- should use dependency injection to fetch services: most easily done by
131
+ If you extend the base ``AbstractController `` class, you can't access services
132
+ directly from the container via ``$this->container->get() `` or ``$this->get() ``.
133
+ Instead, you must use dependency injection to fetch services: most easily done by
123
134
:ref: `type-hinting action method arguments <controller-accessing-services >`:
124
135
125
136
.. best-practice ::
@@ -153,40 +164,41 @@ For example:
153
164
/**
154
165
* @Route("/{id}", name="admin_post_show")
155
166
*/
156
- public function showAction (Post $post)
167
+ public function show (Post $post)
157
168
{
158
169
$deleteForm = $this->createDeleteForm($post);
159
170
160
- return $this->render('admin/post/show.html.twig', array(
171
+ return $this->render('admin/post/show.html.twig', [
161
172
'post' => $post,
162
173
'delete_form' => $deleteForm->createView(),
163
- ) );
174
+ ] );
164
175
}
165
176
166
- Normally, you'd expect a ``$id `` argument to ``showAction () ``. Instead, by
167
- creating a new argument (``$post ``) and type-hinting it with the ``Post ``
168
- class (which is a Doctrine entity), the ParamConverter automatically queries
169
- for an object whose ``$id `` property matches the ``{id} `` value. It will
170
- also show a 404 page if no ``Post `` can be found.
177
+ Normally, you'd expect a ``$id `` argument to ``show () ``. Instead, by creating a
178
+ new argument (``$post ``) and type-hinting it with the ``Post `` class (which is a
179
+ Doctrine entity), the ParamConverter automatically queries for an object whose
180
+ ``$id `` property matches the ``{id} `` value. It will also show a 404 page if no
181
+ ``Post `` can be found.
171
182
172
183
When Things Get More Advanced
173
184
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174
185
175
- The above example works without any configuration because the wildcard name ``{id} `` matches
176
- the name of the property on the entity. If this isn't true, or if you have
177
- even more complex logic, the easiest thing to do is just query for the entity
178
- manually. In our application, we have this situation in ``CommentController ``:
186
+ The above example works without any configuration because the wildcard name
187
+ ``{id} `` matches the name of the property on the entity. If this isn't true, or
188
+ if you have even more complex logic, the easiest thing to do is just query for
189
+ the entity manually. In our application, we have this situation in
190
+ ``CommentController ``:
179
191
180
192
.. code-block :: php
181
193
182
194
/**
183
195
* @Route("/comment/{postSlug}/new", name = "comment_new")
184
196
*/
185
- public function newAction (Request $request, $postSlug)
197
+ public function new (Request $request, $postSlug)
186
198
{
187
199
$post = $this->getDoctrine()
188
200
->getRepository(Post::class)
189
- ->findOneBy(array( 'slug' => $postSlug) );
201
+ ->findOneBy([ 'slug' => $postSlug] );
190
202
191
203
if (!$post) {
192
204
throw $this->createNotFoundException();
@@ -209,7 +221,7 @@ flexible:
209
221
* @Route("/comment/{postSlug}/new", name = "comment_new")
210
222
* @ParamConverter("post", options={"mapping": {"postSlug": "slug"}})
211
223
*/
212
- public function newAction (Request $request, Post $post)
224
+ public function new (Request $request, Post $post)
213
225
{
214
226
// ...
215
227
}
0 commit comments