From c8050b190bdcb2e2209936995c474e290cf0ca86 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 16:14:21 +0200 Subject: [PATCH 01/29] Adding the ADR approach. With the new approach used by the container, the old controller can be replaced easily by the ADR pattern, as Symfony grow, I think it should be the role of the documentation to show how to use the pattern and how to adapt the framework structure. PS : I'm not pretty sure of the 'note' syntax. --- controller/service.rst | 120 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/controller/service.rst b/controller/service.rst index 07f24635be5..d973c5a3bb1 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -80,6 +80,126 @@ If your controller implements the ``__invoke()`` method - popular with the Action-Domain-Response (ADR) pattern, you can simply refer to the service id (``AppBundle\Controller\HelloController`` or ``app.hello_controller`` for example). +If you want to use the ADR pattern rather than the default controller approach, you can use +the new features provided by the container like public/private injections and autowiring, +in order to work, you must update the services.yml file :: + + parameters: + #parameter_name: value + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + # Allow to load every actions + AppBundle\Action\: + resource: '../../src/AppBundle/Action/' + public: true + +Once the file is updated, delete your Controller folder and create an Action one then +build a HelloAction class that use the ADR principes :: + + renderEngine = $renderEngine; + } + + /** + * @throws \InvalidArgumentException + * @throws \RuntimeException + * + * @return Response + */ + public function __invoke() : Response + { + return new Response( + $this->renderEngine->render('default/index.html.twig') + ); + } + } + +.. note:: + + Please note that the PHP 7.1 syntax isn't mandatory. + +.. _controller-service-invoke: + +By default, we define the class with the final keyword because this class shouldn't been extended, +the logic is pretty simple to understand as you understand the ADR pattern, in fact, the 'Action' +is linked to a single request and his dependencies are linked to this precise Action. + +Once this is done, you can define the routes like before using multiples approach : + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/routing.yml + hello: + path: /hello + methods: ['GET'] + defaults: { _controller: AppBundle\Action\HelloAction } + + .. code-block:: php-annotations + + # src/AppBundle/Action/HelloAction.php + // ... + + /** + * @Route("/hello", name="hello") + */ + final class HelloAction + { + // ... + } + + .. code-block:: xml + + + + + + + AppBundle\Action\HelloAction + + + + + .. code-block:: php + + // app/config/routing.php + $collection->add('hello', new Route('/hello', array( + '_controller' => 'AppBundle\Action\HelloAction', + ))); + +.. note:: + Alternatives to base Controller Methods --------------------------------------- From 0d0d4cc3f37b193ff6a6b308f3959ab3b3519c3f Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 16:19:55 +0200 Subject: [PATCH 02/29] Update service.rst Remove the PHP 7.1 syntax. --- controller/service.rst | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index d973c5a3bb1..c13659ffcd2 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -133,7 +133,7 @@ build a HelloAction class that use the ADR principes :: * * @return Response */ - public function __invoke() : Response + public function __invoke() { return new Response( $this->renderEngine->render('default/index.html.twig') @@ -141,12 +141,6 @@ build a HelloAction class that use the ADR principes :: } } -.. note:: - - Please note that the PHP 7.1 syntax isn't mandatory. - -.. _controller-service-invoke: - By default, we define the class with the final keyword because this class shouldn't been extended, the logic is pretty simple to understand as you understand the ADR pattern, in fact, the 'Action' is linked to a single request and his dependencies are linked to this precise Action. From 7359837d0171e333189b48943a6e2da245c4925c Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 16:37:11 +0200 Subject: [PATCH 03/29] Update service.rst Removed the ..note block. --- controller/service.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index c13659ffcd2..9146cf95a3f 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -192,8 +192,6 @@ Once this is done, you can define the routes like before using multiples approac '_controller' => 'AppBundle\Action\HelloAction', ))); -.. note:: - Alternatives to base Controller Methods --------------------------------------- From 885e69691e9a93814e2b9b3296d380ed06aef6f1 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 18:45:44 +0200 Subject: [PATCH 04/29] Update service.rst --- controller/service.rst | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index 9146cf95a3f..cf85edbbb2a 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -108,31 +108,16 @@ build a HelloAction class that use the ADR principes :: use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\EngineInterface; - /** - * Class HelloAction - */ final class HelloAction { - /** @var EngineInterface */ - private $renderEngine; - - /** - * HelloAction constructor. - * - * @param EngineInterface $renderEngine - */ + private $render; + public function __construct( - EngineInterface $renderEngine + EngineInterface $engine ) { - $this->renderEngine = $renderEngine; + $this->renderEngine = $render; } - /** - * @throws \InvalidArgumentException - * @throws \RuntimeException - * - * @return Response - */ public function __invoke() { return new Response( From 220021eab2ae71d39d24dc945bb4784945d45ab0 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 19:04:23 +0200 Subject: [PATCH 05/29] Update service.rst --- controller/service.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index cf85edbbb2a..eae426f95fe 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -112,10 +112,9 @@ build a HelloAction class that use the ADR principes :: { private $render; - public function __construct( - EngineInterface $engine - ) { - $this->renderEngine = $render; + public function __construct(EngineInterface $render) + { + $this->render = $render; } public function __invoke() From 1fda263d3d97b45b557d83da42843ad31ced0272 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 19:04:53 +0200 Subject: [PATCH 06/29] Update service.rst --- controller/service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/service.rst b/controller/service.rst index eae426f95fe..57aa777e6ba 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -120,7 +120,7 @@ build a HelloAction class that use the ADR principes :: public function __invoke() { return new Response( - $this->renderEngine->render('default/index.html.twig') + $this->render->render('default/index.html.twig') ); } } From 11c77c7f4e13d33b93aaf55fce0d46666817e224 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Fri, 14 Jul 2017 19:40:31 +0200 Subject: [PATCH 07/29] Update service.rst --- controller/service.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index 57aa777e6ba..b7aeb0bb935 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -119,9 +119,7 @@ build a HelloAction class that use the ADR principes :: public function __invoke() { - return new Response( - $this->render->render('default/index.html.twig') - ); + return new Response($this->render->render('default/index.html.twig')); } } From d21feb298200d041228e78a0e862b63c7ef33614 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Sat, 15 Jul 2017 08:16:59 +0200 Subject: [PATCH 08/29] Update service.rst Change the order of the routing files and deleted the methods key in yaml routing. --- controller/service.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index b7aeb0bb935..cd8692f369b 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -131,14 +131,6 @@ Once this is done, you can define the routes like before using multiples approac .. configuration-block:: - .. code-block:: yaml - - # app/config/routing.yml - hello: - path: /hello - methods: ['GET'] - defaults: { _controller: AppBundle\Action\HelloAction } - .. code-block:: php-annotations # src/AppBundle/Action/HelloAction.php @@ -152,6 +144,13 @@ Once this is done, you can define the routes like before using multiples approac // ... } + .. code-block:: yaml + + # app/config/routing.yml + hello: + path: /hello + defaults: { _controller: AppBundle\Action\HelloAction } + .. code-block:: xml From a449220c0be4b1f4e85796658b3768eab94c9fcb Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Mon, 17 Jul 2017 08:23:01 +0200 Subject: [PATCH 09/29] Update service.rst --- controller/service.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index cd8692f369b..9de393dbc34 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -84,8 +84,7 @@ If you want to use the ADR pattern rather than the default controller approach, the new features provided by the container like public/private injections and autowiring, in order to work, you must update the services.yml file :: - parameters: - #parameter_name: value +# ... services: _defaults: From 6d1ed62c7ee99a0468636738daf99c7df72b369c Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Mon, 17 Jul 2017 08:25:04 +0200 Subject: [PATCH 10/29] Update service.rst --- controller/service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/service.rst b/controller/service.rst index 9de393dbc34..b3d3bcd3d2a 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -84,7 +84,7 @@ If you want to use the ADR pattern rather than the default controller approach, the new features provided by the container like public/private injections and autowiring, in order to work, you must update the services.yml file :: -# ... + # ... services: _defaults: From a81b6257d0621235b727f3cb2c145fc4a0bc3e3d Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Thu, 3 Aug 2017 09:31:11 +0200 Subject: [PATCH 11/29] Update service.rst Updating the classes call and prepare for dedicated article. --- controller/service.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/controller/service.rst b/controller/service.rst index b3d3bcd3d2a..5231e9d6d6d 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -97,21 +97,20 @@ in order to work, you must update the services.yml file :: resource: '../../src/AppBundle/Action/' public: true -Once the file is updated, delete your Controller folder and create an Action one then -build a HelloAction class that use the ADR principes :: +Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e :: render = $render; } @@ -169,7 +168,7 @@ Once this is done, you can define the routes like before using multiples approac // app/config/routing.php $collection->add('hello', new Route('/hello', array( - '_controller' => 'AppBundle\Action\HelloAction', + '_controller' => 'HelloAction::class', ))); Alternatives to base Controller Methods From 8444e98d3256c3a29be6fec0bfe7c3951a1abe3f Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Thu, 3 Aug 2017 17:44:32 +0200 Subject: [PATCH 12/29] Added the dedicated file and link from service.rst --- controller/adr.rst | 187 +++++++++++++++++++++++++++++++++++++++++ controller/service.rst | 92 +------------------- 2 files changed, 190 insertions(+), 89 deletions(-) create mode 100644 controller/adr.rst diff --git a/controller/adr.rst b/controller/adr.rst new file mode 100644 index 00000000000..a6669296330 --- /dev/null +++ b/controller/adr.rst @@ -0,0 +1,187 @@ +.. index:: +single: Action Domain Responder approach + +How to implement the ADR pattern +================================ + +In Symfony, you're used to implement the MVC pattern and extending the default 'Controller' +class, since the 3.3 update, Symfony is capable of using natively the ADR approach. + +Updating your internal logic +---------------------------- + +As you saw from earlier example, you must update the services.yml file in order to +use the latest features of the DependencyInjection component, this way, here's the updates :: + + # ... + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + # Allow to load every actions + AppBundle\Action\: + resource: '../../src/AppBundle/Action/' + public: true + +Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e :: + + render = $render; + } + + public function __invoke() + { + return new Response($this->render->render('default/index.html.twig')); + } + } + +.. tip:: + + As described in the DependencyInjection doc, you must use the __construct() injection + approach, this way, your class is easier to update and keep in sync with the framework internal + services. + +By default, we define the class with the final keyword because this class shouldn't been extended, +the logic is pretty simple to understand as you understand the ADR pattern, in fact, the 'Action' +is linked to a single request and his dependencies are linked to this precise Action. + +.. tip:: + + By using the final approach and the private visibility (inside the container), our class + is faster to return and easier to keep out of the framework logic. + + +Once this is done, you can define the routes like before using multiples approach : + +.. configuration-block:: + + .. code-block:: php-annotations + + # src/AppBundle/Action/HelloAction.php + // ... + + /** + * @Route("/hello", name="hello") + */ + final class HelloAction + { + // ... + } + + .. code-block:: yaml + + # app/config/routing.yml + hello: + path: /hello + defaults: { _controller: AppBundle\Action\HelloAction } + + .. code-block:: xml + + + + + + + AppBundle\Action\HelloAction + + + + + .. code-block:: php + + // app/config/routing.php + $collection->add('hello', new Route('/hello', array( + '_controller' => 'HelloAction::class', + ))); + +Accessing the request +--------------------- + +As you can imagine, as the logic evolve, your class isn't capable of accessing +the request from simple method injection like this :: + + render->render('default/index.html.twig')); + } + } + +Like you can easily imagine, the container is the best option to gain access to ths request, +using this approach, a simple update is recommended :: + + requestStack = $requestStack + $this->render = $render; + } + + public function __invoke(Request $request) + { + return new Response($this->render->render('default/index.html.twig')); + } + } + +This way, you can easily access to parameters :: + + requestStack = $requestStack + $this->render = $render; + } + + public function __invoke(Request $request) + { + $data = $this->requestStack->getCurrentRequest()->get('id'); + + return new Response($this->render->render('default/index.html.twig')); + } + } + +Final though +------------ + +Keep in mind that this approach can be completely different from what you're used to use, in order to +keep your code clean and easy to maintain, we recommend to use this approach only if your code is +decoupled from the internal framework logic (like with Clean Architecture approach) or if you start a new +project and need to keep the logic linked to your business rules. diff --git a/controller/service.rst b/controller/service.rst index 5231e9d6d6d..e347bc0537c 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -80,96 +80,10 @@ If your controller implements the ``__invoke()`` method - popular with the Action-Domain-Response (ADR) pattern, you can simply refer to the service id (``AppBundle\Controller\HelloController`` or ``app.hello_controller`` for example). -If you want to use the ADR pattern rather than the default controller approach, you can use -the new features provided by the container like public/private injections and autowiring, -in order to work, you must update the services.yml file :: +As this approach is evolving faster and can be easily transposed into Symfony, we recommend +you to read the following part : - # ... - - services: - _defaults: - autowire: true - autoconfigure: true - public: false - - # Allow to load every actions - AppBundle\Action\: - resource: '../../src/AppBundle/Action/' - public: true - -Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e :: - - render = $render; - } - - public function __invoke() - { - return new Response($this->render->render('default/index.html.twig')); - } - } - -By default, we define the class with the final keyword because this class shouldn't been extended, -the logic is pretty simple to understand as you understand the ADR pattern, in fact, the 'Action' -is linked to a single request and his dependencies are linked to this precise Action. - -Once this is done, you can define the routes like before using multiples approach : - -.. configuration-block:: - - .. code-block:: php-annotations - - # src/AppBundle/Action/HelloAction.php - // ... - - /** - * @Route("/hello", name="hello") - */ - final class HelloAction - { - // ... - } - - .. code-block:: yaml - - # app/config/routing.yml - hello: - path: /hello - defaults: { _controller: AppBundle\Action\HelloAction } - - .. code-block:: xml - - - - - - - AppBundle\Action\HelloAction - - - - - .. code-block:: php - - // app/config/routing.php - $collection->add('hello', new Route('/hello', array( - '_controller' => 'HelloAction::class', - ))); +* :doc:`/controller/adr` Alternatives to base Controller Methods --------------------------------------- From a93fa6c9ee520924d66e916217d5aff1f295b522 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Thu, 3 Aug 2017 18:26:50 +0200 Subject: [PATCH 13/29] Update adr.rst Updated the twig call. --- controller/adr.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index a6669296330..c3567c3d167 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -37,16 +37,16 @@ Once the file is updated, delete your Controller folder and create an Action cla final class HelloAction { - private $renderer; + private $twig; - public function __construct(Environment $render) + public function __construct(Environment $twig) { - $this->render = $render; + $this->twig = $twig; } public function __invoke() { - return new Response($this->render->render('default/index.html.twig')); + return new Response($this->twig->render('default/index.html.twig')); } } @@ -124,7 +124,7 @@ the request from simple method injection like this :: public function __invoke(Request $request) { - return new Response($this->render->render('default/index.html.twig')); + return new Response($this->twig->render('default/index.html.twig')); } } @@ -144,17 +144,17 @@ using this approach, a simple update is recommended :: { private $requestStack; - private $renderer; + private $twig; - public function __construct(RequestStack $requestStack, Environment $render) + public function __construct(RequestStack $requestStack, Environment $twig) { $this->requestStack = $requestStack - $this->render = $render; + $this->twig = $twig; } public function __invoke(Request $request) { - return new Response($this->render->render('default/index.html.twig')); + return new Response($this->twig->render('default/index.html.twig')); } } @@ -164,21 +164,21 @@ This way, you can easily access to parameters :: // ... - public function __construct(RequestStack $requestStack, Environment $render) + public function __construct(RequestStack $requestStack, Environment $twig) { $this->requestStack = $requestStack - $this->render = $render; + $this->twig = $twig; } public function __invoke(Request $request) { $data = $this->requestStack->getCurrentRequest()->get('id'); - return new Response($this->render->render('default/index.html.twig')); + return new Response($this->twig->render('default/index.html.twig')); } } -Final though +Final thought ------------ Keep in mind that this approach can be completely different from what you're used to use, in order to From 97bcbacbcc2bf89c6e304952c1a201563213c8ae Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Thu, 3 Aug 2017 18:52:28 +0200 Subject: [PATCH 14/29] Update adr.rst Updated the syntax errors and unused use statements. --- controller/adr.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index c3567c3d167..72cd361ddda 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -4,14 +4,15 @@ single: Action Domain Responder approach How to implement the ADR pattern ================================ -In Symfony, you're used to implement the MVC pattern and extending the default 'Controller' -class, since the 3.3 update, Symfony is capable of using natively the ADR approach. +In Symfony, you're used to implement the MVC pattern and extending the default :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` +class. +Since the 3.3 update, Symfony is capable of using natively the ADR approach. -Updating your internal logic ----------------------------- +Updating your configuration +--------------------------- -As you saw from earlier example, you must update the services.yml file in order to -use the latest features of the DependencyInjection component, this way, here's the updates :: +As the framework evolve, you must update the services.yml file in order to +use the latest features of the DependencyInjection component, this way, here's the updates:: # ... @@ -26,14 +27,13 @@ use the latest features of the DependencyInjection component, this way, here's t resource: '../../src/AppBundle/Action/' public: true -Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e :: +Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e:: requestStack->getCurrentRequest()->get('id'); - return new Response($this->twig->render('default/index.html.twig')); + return new Response($this->twig->render('default/index.html.twig', ['data' => $data])); } } From 72c2c741aa5804cab928a5b87920f106eddd7361 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Thu, 3 Aug 2017 18:53:21 +0200 Subject: [PATCH 15/29] Update service.rst Removed the space before colon. --- controller/service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/service.rst b/controller/service.rst index e347bc0537c..383ceb574a9 100644 --- a/controller/service.rst +++ b/controller/service.rst @@ -81,7 +81,7 @@ Action-Domain-Response (ADR) pattern, you can simply refer to the service id (``AppBundle\Controller\HelloController`` or ``app.hello_controller`` for example). As this approach is evolving faster and can be easily transposed into Symfony, we recommend -you to read the following part : +you to read the following part: * :doc:`/controller/adr` From 666a89fcc89314bcfcf4447e882dfc42177c9566 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Thu, 3 Aug 2017 18:57:27 +0200 Subject: [PATCH 16/29] Update adr.rst Add the use statement for routing and corrected the request part. --- controller/adr.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index 72cd361ddda..b3a378af236 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -108,14 +108,16 @@ Once this is done, you can define the routes like before using multiples approac .. code-block:: php // app/config/routing.php + use AppBundle\Action\HelloAction + $collection->add('hello', new Route('/hello', array( - '_controller' => 'HelloAction::class', + '_controller' => HelloAction::class, ))); Accessing the request --------------------- -As you can imagine, as the logic evolve, your class isn't capable of accessing +As you can imagine, as the logic evolve, your class is capable of accessing the request from simple method injection like this :: Date: Sat, 5 Aug 2017 17:58:35 +0200 Subject: [PATCH 17/29] Update adr.rst Update the missing use and adding the return type, also correct the typos --- controller/adr.rst | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index b3a378af236..891c3877f91 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -34,6 +34,7 @@ Once the file is updated, delete your Controller folder and create an Action cla namespace AppBundle\Action; use Twig\Environment; + use Symfony\Component\HTTPFoundation\Response; final class HelloAction { @@ -44,7 +45,7 @@ Once the file is updated, delete your Controller folder and create an Action cla $this->twig = $twig; } - public function __invoke() + public function __invoke() : Response { return new Response($this->twig->render('default/index.html.twig')); } @@ -65,8 +66,7 @@ is linked to a single request and his dependencies are linked to this precise Ac By using the final approach and the private visibility (inside the container), our class is faster to return and easier to keep out of the framework logic. - -Once this is done, you can define the routes like before using multiples approach: +Once this is done, you can define the routes like before using multiples approaches: .. configuration-block:: @@ -122,25 +122,24 @@ the request from simple method injection like this :: twig->render('default/index.html.twig')); } } -Like you can easily imagine, the container is the best option to gain access to ths request, -using this approach, a simple update is recommended :: +Like you can easily imagine, the :class:`Symfony\\Component\Httpfoundation\RequestStack` is the best option to gain access to the request, using this approach, a simple update is recommended and the access to request parameters is way easier:: twig = $twig; } - public function __invoke(Request $request) - { - return new Response($this->twig->render('default/index.html.twig')); - } - } - -This way, you can easily access to parameters:: - - requestStack = $requestStack - $this->twig = $twig; - } - - public function __invoke(Request $request) + public function __invoke() : Response { $data = $this->requestStack->getCurrentRequest()->get('id'); - - return new Response($this->twig->render('default/index.html.twig', ['data' => $data])); + + return new Response($this->twig->render('default/index.html.twig', array('data' => $data)); } } Final thought ------------- +------------- Keep in mind that this approach can be completely different from what you're used to use, in order to keep your code clean and easy to maintain, we recommend to use this approach only if your code is From 0d2022ad3cc9ce5a75ef1265fb0ddb5ff3ebda9c Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Sat, 5 Aug 2017 18:08:20 +0200 Subject: [PATCH 18/29] Corrected the index typo. --- controller/adr.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index 891c3877f91..896f7e88359 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -1,11 +1,11 @@ .. index:: -single: Action Domain Responder approach + single: Action Domain Responder approach How to implement the ADR pattern ================================ In Symfony, you're used to implement the MVC pattern and extending the default :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` -class. +class. Since the 3.3 update, Symfony is capable of using natively the ADR approach. Updating your configuration @@ -109,7 +109,7 @@ Once this is done, you can define the routes like before using multiples approac // app/config/routing.php use AppBundle\Action\HelloAction - + $collection->add('hello', new Route('/hello', array( '_controller' => HelloAction::class, ))); @@ -156,7 +156,7 @@ Like you can easily imagine, the :class:`Symfony\\Component\Httpfoundation\Reque public function __invoke() : Response { $data = $this->requestStack->getCurrentRequest()->get('id'); - + return new Response($this->twig->render('default/index.html.twig', array('data' => $data)); } } From 582f4bf73d7c1a1ad41eabee7620ff9ccf7fba58 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Sat, 5 Aug 2017 18:12:10 +0200 Subject: [PATCH 19/29] Update adr.rst Add the backslash escape --- controller/adr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/adr.rst b/controller/adr.rst index 896f7e88359..d260ae43c14 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -131,7 +131,7 @@ the request from simple method injection like this :: } } -Like you can easily imagine, the :class:`Symfony\\Component\Httpfoundation\RequestStack` is the best option to gain access to the request, using this approach, a simple update is recommended and the access to request parameters is way easier:: +Like you can easily imagine, the :class:`Symfony\\Component\\Httpfoundation\\RequestStack` is the best option to gain access to the request, using this approach, a simple update is recommended and the access to request parameters is way easier:: Date: Sun, 6 Aug 2017 09:12:00 +0200 Subject: [PATCH 20/29] Update adr.rst Updated the HttpFoundation calls. --- controller/adr.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index d260ae43c14..5052f546819 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -34,7 +34,7 @@ Once the file is updated, delete your Controller folder and create an Action cla namespace AppBundle\Action; use Twig\Environment; - use Symfony\Component\HTTPFoundation\Response; + use Symfony\Component\HttpFoundation\Response; final class HelloAction { @@ -45,7 +45,7 @@ Once the file is updated, delete your Controller folder and create an Action cla $this->twig = $twig; } - public function __invoke() : Response + public function __invoke(): Response { return new Response($this->twig->render('default/index.html.twig')); } @@ -122,10 +122,10 @@ the request from simple method injection like this :: twig->render('default/index.html.twig')); } @@ -138,7 +138,7 @@ Like you can easily imagine, the :class:`Symfony\\Component\\Httpfoundation\\Req namespace AppBundle\Action; use Twig\Environment; - use Symfony\Component\HTTPFoundation\Response; + use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\RequestStack; final class HelloAction @@ -153,7 +153,7 @@ Like you can easily imagine, the :class:`Symfony\\Component\\Httpfoundation\\Req $this->twig = $twig; } - public function __invoke() : Response + public function __invoke(): Response { $data = $this->requestStack->getCurrentRequest()->get('id'); From cd4650122634a842fac6ed10f8669704e5e7cdc5 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Wed, 16 Aug 2017 10:26:13 +0200 Subject: [PATCH 21/29] Update adr.rst Removed the RequestStack injection. --- controller/adr.rst | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index 5052f546819..548a734f14c 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -127,40 +127,12 @@ the request from simple method injection like this :: public function __invoke(Request $request): Response { - return new Response($this->twig->render('default/index.html.twig')); + $id = $this->requestStack->getCurrentRequest()->get('id'); + + return new Response($this->twig->render('default/index.html.twig', array('id' => $id)); } } - -Like you can easily imagine, the :class:`Symfony\\Component\\Httpfoundation\\RequestStack` is the best option to gain access to the request, using this approach, a simple update is recommended and the access to request parameters is way easier:: - - requestStack = $requestStack - $this->twig = $twig; - } - - public function __invoke(): Response - { - $data = $this->requestStack->getCurrentRequest()->get('id'); - - return new Response($this->twig->render('default/index.html.twig', array('data' => $data)); - } - } - + Final thought ------------- From 24416f54e0c55e24346ff7b0f0027a6cdbdd34e1 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Tue, 12 Sep 2017 09:42:47 +0200 Subject: [PATCH 22/29] Update adr.rst Updated the Request call and the Twig\Environment render() call. --- controller/adr.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index 548a734f14c..f036f013069 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -127,9 +127,9 @@ the request from simple method injection like this :: public function __invoke(Request $request): Response { - $id = $this->requestStack->getCurrentRequest()->get('id'); + $id = $request->get('id'); - return new Response($this->twig->render('default/index.html.twig', array('id' => $id)); + return $this->twig->render('default/index.html.twig', array('id' => $id)); } } From dc6ddc689ae8e00831366a964bb919803e2b453f Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Mon, 16 Oct 2017 14:32:21 +0200 Subject: [PATCH 23/29] Update adr.rst Corrected the service injection and services configuration. --- controller/adr.rst | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index f036f013069..47b00c8607b 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -25,6 +25,7 @@ use the latest features of the DependencyInjection component, this way, here's t # Allow to load every actions AppBundle\Action\: resource: '../../src/AppBundle/Action/' + tags: ['controller.service_arguments'] public: true Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e:: @@ -38,24 +39,16 @@ Once the file is updated, delete your Controller folder and create an Action cla final class HelloAction { - private $twig; - - public function __construct(Environment $twig) - { - $this->twig = $twig; - } - - public function __invoke(): Response + public function __invoke(Environment $twig): Response { - return new Response($this->twig->render('default/index.html.twig')); + return new Response($twig->render('default/index.html.twig')); } } .. tip:: - As described in the DependencyInjection doc, you must use the __construct() injection - approach, this way, your class is easier to update and keep in sync with any framework internal - services. + As described in the DependencyInjection doc, you can still use the __construct() injection + approach. By default, we define the class with the final keyword because this class shouldn't be extended, the logic is pretty simple to understand as you understand the ADR pattern, in fact, the 'Action' @@ -125,11 +118,11 @@ the request from simple method injection like this :: use Symfony\Component\HttpFoundation\Request; // ... - public function __invoke(Request $request): Response + public function __invoke(Environment $twig, Request $request): Response { $id = $request->get('id'); - return $this->twig->render('default/index.html.twig', array('id' => $id)); + return $twig->render('default/index.html.twig', array('id' => $id)); } } From f1aad206cb6d6265a803674fa1b41c7daab19dce Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Mon, 16 Oct 2017 14:59:45 +0200 Subject: [PATCH 24/29] Update adr.rst --- controller/adr.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/controller/adr.rst b/controller/adr.rst index 47b00c8607b..4f989707794 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -26,7 +26,6 @@ use the latest features of the DependencyInjection component, this way, here's t AppBundle\Action\: resource: '../../src/AppBundle/Action/' tags: ['controller.service_arguments'] - public: true Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e:: From 16c84723f331945486d6d7b9cb187bf186ba4b33 Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Mon, 16 Oct 2017 15:01:08 +0200 Subject: [PATCH 25/29] Update adr.rst --- controller/adr.rst | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index 4f989707794..c8880bdf9ad 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -8,26 +8,10 @@ In Symfony, you're used to implement the MVC pattern and extending the default : class. Since the 3.3 update, Symfony is capable of using natively the ADR approach. -Updating your configuration ---------------------------- - -As the framework evolve, you must update the services.yml file in order to -use the latest features of the DependencyInjection component, this way, here's the updates:: - - # ... - - services: - _defaults: - autowire: true - autoconfigure: true - public: false - - # Allow to load every actions - AppBundle\Action\: - resource: '../../src/AppBundle/Action/' - tags: ['controller.service_arguments'] +Updating your classes +--------------------- -Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e:: +As the framework evolve, you must update your classes, first, delete your Controller folder and create an Action one then a new class using the ADR principles, i.e:: Date: Fri, 24 Nov 2017 14:44:53 +0100 Subject: [PATCH 26/29] [ADD](Responder classe)[!P2] Added a Responder call and the configuration linked. --- controller/adr.rst | 103 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index c8880bdf9ad..e454d5c7f9e 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -8,29 +8,56 @@ In Symfony, you're used to implement the MVC pattern and extending the default : class. Since the 3.3 update, Symfony is capable of using natively the ADR approach. +Update the configuration +------------------------ + +The first step is to update the default services.yaml file, here's the new content: + +.. code-block:: yml + + parameters: + locale: 'en' + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + App\Actions\: + resource: '../src/Actions' + tags: + - 'controller.service_arguments' + +Now that the container knows about our actions, time to build a simple Action ! + Updating your classes --------------------- -As the framework evolve, you must update your classes, first, delete your Controller folder and create an Action one then a new class using the ADR principles, i.e:: +As the framework evolve, you must update your classes, first, delete your Controller folder and create an Actions one then a new class using the ADR principles, for this example, call it ``HelloAction.php``: + +.. code-block:: php render('default/index.html.twig')); + public function __invoke(HelloResponder $responder): Response + { + return $responder([ + 'text' => 'Hello World' + ]); } } .. tip:: - As described in the DependencyInjection doc, you can still use the __construct() injection + As described in the DependencyInjection component documentation, you can still use the __construct() injection approach. By default, we define the class with the final keyword because this class shouldn't be extended, @@ -90,11 +117,69 @@ Once this is done, you can define the routes like before using multiples approac '_controller' => HelloAction::class, ))); +Creating a Responder +-------------------- + +As you can see in the __invoke call, this action require a ``HelloResponder`` class in order to build the response which is returned to the browser, first, update the services.yaml according to this need: + +.. code-block:: yml + + parameters: + locale: 'en' + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + App\Actions\: + resource: '../src/Actions' + tags: + - 'controller.service_arguments' + + + App\Responders\: + resource: '../src/Responders' + +Here, the container only need to know about the existence of the classes, nothing difficult to understand as the fact that our Responders are responsable of returning the actual Response to the browser, no need to add the 'controller.service_arguments' tags as the Responders need to be called using the __invoke method in order to receive data from the Action. + +Now that the logic behind is clear, time to create the ``HelloResponder.php`` file: + +.. code-block:: php + + twig = $twig; + } + + public function __invoke(array $data) + { + return new Response( + $this->twig->render('index.html.twig', $data) + ); + } + } + +If the routing is clearly define, the browser should display the traditional "Hello World" using the ADR approach, congrats ! + Accessing the request --------------------- -As you can imagine, as the logic evolve, your class is capable of accessing -the request from simple method injection like this :: +In many case, your classes can ask for any data passed via a form or via an API call, +as you can imagine, as the logic evolve, your class is capable of accessing the request +from a simple method injection like this :: Date: Fri, 24 Nov 2017 14:46:43 +0100 Subject: [PATCH 27/29] [FIX](Syntax)[!P2] Fix the yaml call and the extra line in the responder configuration block. --- controller/adr.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index e454d5c7f9e..07edc5d886e 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -13,7 +13,7 @@ Update the configuration The first step is to update the default services.yaml file, here's the new content: -.. code-block:: yml +.. code-block:: yaml parameters: locale: 'en' @@ -122,7 +122,7 @@ Creating a Responder As you can see in the __invoke call, this action require a ``HelloResponder`` class in order to build the response which is returned to the browser, first, update the services.yaml according to this need: -.. code-block:: yml +.. code-block:: yaml parameters: locale: 'en' @@ -138,7 +138,6 @@ As you can see in the __invoke call, this action require a ``HelloResponder`` cl tags: - 'controller.service_arguments' - App\Responders\: resource: '../src/Responders' @@ -179,7 +178,9 @@ Accessing the request In many case, your classes can ask for any data passed via a form or via an API call, as you can imagine, as the logic evolve, your class is capable of accessing the request -from a simple method injection like this :: +from a simple method injection like this: + +.. code-block:: php Date: Fri, 24 Nov 2017 16:00:22 +0100 Subject: [PATCH 28/29] [FIX](ADR Repository)[!P2] Just added the link to the official ADR repository. --- controller/adr.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controller/adr.rst b/controller/adr.rst index 07edc5d886e..1a891777769 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -6,7 +6,7 @@ How to implement the ADR pattern In Symfony, you're used to implement the MVC pattern and extending the default :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` class. -Since the 3.3 update, Symfony is capable of using natively the ADR approach. +Since the 3.3 update, Symfony is capable of using natively the `ADR`_ approach. Update the configuration ------------------------ @@ -202,3 +202,5 @@ Keep in mind that this approach can be completely different from what you're use keep your code clean and easy to maintain, we recommend to use this approach only if your code is decoupled from the internal framework logic (like with Clean Architecture approach) or if you start a new project and need to keep the logic linked to your business rules. + +.. _`ADR`: https://github.com/pmjones/adr From 3dacc68468500620bfffeff86c827378234cea8e Mon Sep 17 00:00:00 2001 From: Loulier Guillaume Date: Wed, 24 Jan 2018 19:03:43 +0100 Subject: [PATCH 29/29] fix(typo): fix on typo and space. --- controller/adr.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controller/adr.rst b/controller/adr.rst index 1a891777769..7a5a767c55e 100644 --- a/controller/adr.rst +++ b/controller/adr.rst @@ -29,12 +29,12 @@ The first step is to update the default services.yaml file, here's the new conte tags: - 'controller.service_arguments' -Now that the container knows about our actions, time to build a simple Action ! +Now that the container knows about our actions, time to build a simple Action! Updating your classes --------------------- -As the framework evolve, you must update your classes, first, delete your Controller folder and create an Actions one then a new class using the ADR principles, for this example, call it ``HelloAction.php``: +As the framework evolves, you must update your classes, first, delete your Controller folder and create an Actions one then a new class using the ADR principles, for this example, call it ``HelloAction.php``: .. code-block:: php