diff --git a/book/controller.rst b/book/controller.rst index e79af5c803c..d424d8b4426 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -429,35 +429,47 @@ A great way to see the core functionality in action is to look in the Redirecting ~~~~~~~~~~~ -If you want to redirect the user to another page, use the -:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::redirect` -method:: +If you want to redirect the user to another page, use the ``redirectToRoute()`` method:: public function indexAction() { - return $this->redirect($this->generateUrl('homepage')); + return $this->redirectToRoute('homepage'); + + // redirectToRoute is equivalent to using redirect() and generateUrl() together: + // return $this->redirect($this->generateUrl('homepage'), 301); } -The ``generateUrl()`` method is just a helper function that generates the URL -for a given route. For more information, see the :doc:`Routing ` -chapter. +.. versionadded:: 2.6 + The ``redirectToRoute()`` method was added in Symfony 2.6. Previously (and still now), you + could use ``redirect()`` and ``generateUrl()`` together for this (see the example above). + +Or, if you want to redirect externally, just use ``redirect()`` and pass it the URL:: + + public function indexAction() + { + return $this->redirect('http://symfony.com/doc'); + } -By default, the ``redirect()`` method performs a 302 (temporary) redirect. To +By default, the ``redirectToRoute()`` method performs a 302 (temporary) redirect. To perform a 301 (permanent) redirect, modify the second argument:: public function indexAction() { - return $this->redirect($this->generateUrl('homepage'), 301); + return $this->redirectToRoute('homepage', array(), 301); } .. tip:: - The ``redirect()`` method is simply a shortcut that creates a ``Response`` - object that specializes in redirecting the user. It's equivalent to:: + The ``redirectToRoute()`` method is simply a shortcut that creates a + ``Response`` object that specializes in redirecting the user. It's + equivalent to:: use Symfony\Component\HttpFoundation\RedirectResponse; - return new RedirectResponse($this->generateUrl('homepage')); + public function indexAction() + { + return new RedirectResponse($this->generateUrl('homepage')); + } .. index:: single: Controller; Rendering templates @@ -623,12 +635,14 @@ For example, imagine you're processing a form submit:: if ($form->isValid()) { // do some sort of processing - $request->getSession()->getFlashBag()->add( + $this->addFlash( 'notice', 'Your changes were saved!' ); - return $this->redirect($this->generateUrl(...)); + // $this->addFlash is equivalent to $this->get('session')->getFlashBag()->add + + return $this->redirectToRoute(...); } return $this->render(...); @@ -638,8 +652,8 @@ After processing the request, the controller sets a ``notice`` flash message in the session and then redirects. The name (``notice``) isn't significant - it's just something you invent and reference next. -In the template of the next page (or even better, in your base layout template), -the following code will render the ``notice`` message: +In the template of the next action, the following code could be used to render +the ``notice`` message: .. configuration-block:: diff --git a/book/doctrine.rst b/book/doctrine.rst index e60ab0118fe..989e6df93eb 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -667,7 +667,7 @@ you have a route that maps a product id to an update action in a controller:: $product->setName('New product name!'); $em->flush(); - return $this->redirect($this->generateUrl('homepage')); + return $this->redirectToRoute('homepage'); } Updating an object involves just three steps: diff --git a/book/forms.rst b/book/forms.rst index 7bdfd2d991c..4eba6a4f60e 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -234,7 +234,7 @@ controller:: if ($form->isValid()) { // perform some action, such as saving the task to the database - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } // ... @@ -319,7 +319,7 @@ querying if the "Save and add" button was clicked:: ? 'task_new' : 'task_success'; - return $this->redirect($this->generateUrl($nextAction)); + return $this->redirectToRoute($nextAction); } .. index:: @@ -1233,7 +1233,7 @@ it after a form submission can be done when the form is valid:: $em->persist($task); $em->flush(); - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } If, for some reason, you don't have access to your original ``$task`` object, diff --git a/book/propel.rst b/book/propel.rst index 9ff589afb04..483fbfdaedb 100644 --- a/book/propel.rst +++ b/book/propel.rst @@ -234,7 +234,7 @@ have a route that maps a product id to an update action in a controller:: $product->setName('New product name!'); $product->save(); - return $this->redirect($this->generateUrl('homepage')); + return $this->redirectToRoute('homepage'); } Updating an object involves just three steps: diff --git a/book/security.rst b/book/security.rst index cb383cfa7d9..f96a277c256 100644 --- a/book/security.rst +++ b/book/security.rst @@ -813,23 +813,25 @@ You can easily deny access from inside a controller:: public function helloAction($name) { - if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { - throw $this->createAccessDeniedException(); - } + // The second parameter is used to specify on what object the role is tested. + $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); + + // Old way : + // if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { + // throw $this->createAccessDeniedException('Unable to access this page!'); + // } // ... } .. versionadded:: 2.6 - The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior - to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. - -.. versionadded:: 2.5 - The ``createAccessDeniedException`` method was introduced in Symfony 2.5. + The ``denyAccessUnlessGranted()`` method was introduced in Symfony 2.6. Previously (and + still now), you could check access directly and throw the ``AccessDeniedException`` as shown + in the example above). -The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException` -method creates a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` -object, which ultimately triggers a 403 HTTP response inside Symfony. +In both cases, a special +:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` +is thrown, which ultimately triggers a 403 HTTP response inside Symfony. That's it! If the user isn't logged in yet, they will be asked to login (e.g. redirected to the login page). If they *are* logged in, they'll be shown diff --git a/book/validation.rst b/book/validation.rst index a7a6a3c1d75..fd4264d7a1d 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -231,7 +231,7 @@ workflow looks like the following from inside a controller:: if ($form->isValid()) { // the validation passed, do something with the $author object - return $this->redirect($this->generateUrl(...)); + return $this->redirectToRoute(...); } return $this->render('BlogBundle:Author:form.html.twig', array( diff --git a/components/form/introduction.rst b/components/form/introduction.rst index 7321a1029a1..2e4a6e891f9 100644 --- a/components/form/introduction.rst +++ b/components/form/introduction.rst @@ -587,7 +587,7 @@ method: // ... perform some action, such as saving the data to the database - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } // ... diff --git a/cookbook/doctrine/file_uploads.rst b/cookbook/doctrine/file_uploads.rst index ab52ae4c940..21910b7d2d2 100644 --- a/cookbook/doctrine/file_uploads.rst +++ b/cookbook/doctrine/file_uploads.rst @@ -244,7 +244,7 @@ The following controller shows you how to handle the entire process:: $em->persist($document); $em->flush(); - return $this->redirect($this->generateUrl(...)); + return $this->redirectToRoute(...); } return array('form' => $form->createView()); @@ -267,7 +267,7 @@ in a moment to handle the file upload:: $em->persist($document); $em->flush(); - return $this->redirect(...); + return $this->redirectToRoute(...); } The ``upload()`` method will take advantage of the :class:`Symfony\\Component\\HttpFoundation\\File\\UploadedFile` @@ -432,7 +432,7 @@ call to ``$document->upload()`` should be removed from the controller:: $em->persist($document); $em->flush(); - return $this->redirect(...); + return $this->redirectToRoute(...); } .. note:: diff --git a/cookbook/doctrine/registration_form.rst b/cookbook/doctrine/registration_form.rst index 4e4abbb5a05..b6849791212 100644 --- a/cookbook/doctrine/registration_form.rst +++ b/cookbook/doctrine/registration_form.rst @@ -287,7 +287,7 @@ the validation and saves the data into the database:: $em->persist($registration->getUser()); $em->flush(); - return $this->redirect(...); + return $this->redirectToRoute(...); } return $this->render( diff --git a/cookbook/expression/expressions.rst b/cookbook/expression/expressions.rst index 63fc728343c..73e43745bb8 100644 --- a/cookbook/expression/expressions.rst +++ b/cookbook/expression/expressions.rst @@ -33,11 +33,9 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object:: public function indexAction() { - if (!$this->get('security.authorization_checker')->isGranted(new Expression( + $this->denyAccessUnlessGranted(new Expression( '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' - ))) { - throw $this->createAccessDeniedException(); - } + )); // ... } diff --git a/cookbook/form/direct_submit.rst b/cookbook/form/direct_submit.rst index 221f7f534d8..7166210319b 100644 --- a/cookbook/form/direct_submit.rst +++ b/cookbook/form/direct_submit.rst @@ -25,7 +25,7 @@ submissions:: if ($form->isValid()) { // perform some action... - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } return $this->render('AcmeTaskBundle:Default:new.html.twig', array( @@ -66,7 +66,7 @@ method, pass the submitted data directly to if ($form->isValid()) { // perform some action... - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } } @@ -111,7 +111,7 @@ a convenient shortcut to the previous example:: if ($form->isValid()) { // perform some action... - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } } diff --git a/cookbook/form/form_collections.rst b/cookbook/form/form_collections.rst index 638a1dc2f49..32ccbc263f6 100644 --- a/cookbook/form/form_collections.rst +++ b/cookbook/form/form_collections.rst @@ -717,7 +717,7 @@ the relationship between the removed ``Tag`` and ``Task`` object. $em->flush(); // redirect back to some edit page - return $this->redirect($this->generateUrl('task_edit', array('id' => $id))); + return $this->redirectToRoute('task_edit', array('id' => $id)); } // render some form template diff --git a/cookbook/security/remember_me.rst b/cookbook/security/remember_me.rst index 4a302a16c49..93987552e68 100644 --- a/cookbook/security/remember_me.rst +++ b/cookbook/security/remember_me.rst @@ -162,19 +162,11 @@ In the following example, the action is only allowed if the user has the public function editAction() { - if (false === $this->get('security.authorization_checker')->isGranted( - 'IS_AUTHENTICATED_FULLY' - )) { - throw new AccessDeniedException(); - } + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); // ... } -.. versionadded:: 2.6 - The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior - to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. - If your application is based on the Symfony Standard Edition, you can also secure your controller using annotations: diff --git a/cookbook/security/securing_services.rst b/cookbook/security/securing_services.rst index f877cffd125..0b37720654a 100644 --- a/cookbook/security/securing_services.rst +++ b/cookbook/security/securing_services.rst @@ -5,41 +5,34 @@ How to Secure any Service or Method in your Application ======================================================= -In the security chapter, you can see how to :ref:`secure a controller ` -by requesting the ``security.authorization_checker`` service from the Service Container -and checking the current user's role:: +In the security chapter, you can see how to +:ref:`secure a controller ` by requesting +the ``security.authorization_checker`` service from the Service Container and +checking the current user's role:: // ... use Symfony\Component\Security\Core\Exception\AccessDeniedException; public function helloAction($name) { - if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { - throw new AccessDeniedException(); - } + $this->denyAccessUnlessGranted('ROLE_ADMIN'); // ... } -.. versionadded:: 2.6 - The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior - to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. - -You can also secure *any* service in a similar way by injecting the ``security.authorization_checker`` +You can also secure *any* service by injecting the ``security.authorization_checker`` service into it. For a general introduction to injecting dependencies into services see the :doc:`/book/service_container` chapter of the book. For example, suppose you have a ``NewsletterManager`` class that sends out emails -and you want to restrict its use to only users who have some ``ROLE_NEWSLETTER_ADMIN`` -role. Before you add security, the class looks something like this: - -.. code-block:: php +and you want to restrict its use to only users who have some +``ROLE_NEWSLETTER_ADMIN`` role. Before you add security, the class looks +something like this:: // src/AppBundle/Newsletter/NewsletterManager.php namespace AppBundle\Newsletter; class NewsletterManager { - public function sendNewsletter() { // ... where you actually do the work @@ -55,8 +48,9 @@ check, this is an ideal candidate for constructor injection, which guarantees that the authorization checker object will be available inside the ``NewsletterManager`` class:: - namespace AppBundle\Newsletter; + // src/AppBundle/Newsletter/NewsletterManager.php + // ... use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class NewsletterManager