@@ -5,16 +5,15 @@ Symfony follows the philosophy of *"thin controllers and fat models"*. This
55means that controllers should hold just the thin layer of *glue-code *
66needed to coordinate the different parts of the application.
77
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.
1311
1412..best-practice ::
1513
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.
1817
1918Coupling the controllers to the underlying framework allows you to leverage
2019all of its features and increases your productivity.
@@ -33,6 +32,18 @@ Overall, this means you should aggressively decouple your business logic
3332from the framework while, at the same time, aggressively coupling your controllers
3433and routing *to * the framework in order to get the most out of it.
3534
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+
3647Routing Configuration
3748---------------------
3849
@@ -94,32 +105,32 @@ for the homepage of our app:
94105 namespace App\Controller;
95106
96107 use App\Entity\Post;
97- use Symfony\Bundle\FrameworkBundle\Controller\Controller ;
108+ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController ;
98109 use Symfony\Component\Routing\Annotation\Route;
99110
100- class DefaultController extendsController
111+ class DefaultController extendsAbstractController
101112 {
102113 /**
103114 * @Route("/", name="homepage")
104115 */
105- public functionindexAction ()
116+ public functionindex ()
106117 {
107118 $posts = $this->getDoctrine()
108119 ->getRepository(Post::class)
109120 ->findLatest();
110121
111- return $this->render('default/index.html.twig',array(
122+ return $this->render('default/index.html.twig',[
112123 'posts' => $posts,
113- ) );
124+ ] );
114125 }
115126 }
116127
117128 Fetching Services
118129-----------------
119130
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
123134:ref: `type-hinting action method arguments <controller-accessing-services >`:
124135
125136..best-practice ::
@@ -153,40 +164,41 @@ For example:
153164 /**
154165 * @Route("/{id}", name="admin_post_show")
155166 */
156- public functionshowAction (Post $post)
167+ public functionshow (Post $post)
157168 {
158169 $deleteForm = $this->createDeleteForm($post);
159170
160- return $this->render('admin/post/show.html.twig',array(
171+ return $this->render('admin/post/show.html.twig',[
161172 'post' => $post,
162173 'delete_form' => $deleteForm->createView(),
163- ) );
174+ ] );
164175 }
165176
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.
171182
172183When Things Get More Advanced
173184~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174185
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 ``:
179191
180192..code-block ::php
181193
182194 /**
183195 * @Route("/comment/{postSlug}/new", name = "comment_new")
184196 */
185- public functionnewAction (Request $request, $postSlug)
197+ public functionnew (Request $request, $postSlug)
186198 {
187199 $post = $this->getDoctrine()
188200 ->getRepository(Post::class)
189- ->findOneBy(array( 'slug' => $postSlug) );
201+ ->findOneBy([ 'slug' => $postSlug] );
190202
191203 if (!$post) {
192204 throw $this->createNotFoundException();
@@ -209,7 +221,7 @@ flexible:
209221 * @Route("/comment/{postSlug}/new", name = "comment_new")
210222 * @ParamConverter("post", options={"mapping": {"postSlug": "slug"}})
211223 */
212- public functionnewAction (Request $request, Post $post)
224+ public functionnew (Request $request, Post $post)
213225 {
214226 // ...
215227 }