diff --git a/book/controller.rst b/book/controller.rst
index c4d6d031900..167ffbecaaa 100644
--- a/book/controller.rst
+++ b/book/controller.rst
@@ -590,8 +590,6 @@ Accessing other Services
When extending the base controller class, you can access any Symfony2 service
via the ``get()`` method. Here are several common services you might need::
- $request = $this->getRequest();
-
$templating = $this->get('templating');
$router = $this->get('router');
@@ -660,16 +658,21 @@ by using the native PHP sessions.
Storing and retrieving information from the session can be easily achieved
from any controller::
- $session = $this->getRequest()->getSession();
+ use Symfony\Component\HttpFoundation\Request;
+
+ public function indexAction(Request $request)
+ {
+ $session = $request->getSession();
- // store an attribute for reuse during a later user request
- $session->set('foo', 'bar');
+ // store an attribute for reuse during a later user request
+ $session->set('foo', 'bar');
- // in another controller for another request
- $foo = $session->get('foo');
+ // in another controller for another request
+ $foo = $session->get('foo');
- // use a default value if the key doesn't exist
- $filters = $session->get('filters', array());
+ // use a default value if the key doesn't exist
+ $filters = $session->get('filters', array());
+ }
These attributes will remain on the user for the remainder of that user's
session.
@@ -687,11 +690,13 @@ These types of messages are called "flash" messages.
For example, imagine you're processing a form submit::
- public function updateAction()
+ use Symfony\Component\HttpFoundation\Request;
+
+ public function updateAction(Request $request)
{
$form = $this->createForm(...);
- $form->handleRequest($this->getRequest());
+ $form->handleRequest($request);
if ($form->isValid()) {
// do some sort of processing
@@ -783,17 +788,22 @@ The Request Object
------------------
Besides the values of the routing placeholders, the controller also has access
-to the ``Request`` object when extending the base ``Controller`` class::
+to the ``Request`` object. The framework injects the ``Request`` object in the
+controller if a variable is type-hinted with
+`Symfony\Component\HttpFoundation\Request`::
- $request = $this->getRequest();
+ use Symfony\Component\HttpFoundation\Request;
- $request->isXmlHttpRequest(); // is it an Ajax request?
+ public function indexAction(Request $request)
+ {
+ $request->isXmlHttpRequest(); // is it an Ajax request?
- $request->getPreferredLanguage(array('en', 'fr'));
+ $request->getPreferredLanguage(array('en', 'fr'));
- $request->query->get('page'); // get a $_GET parameter
+ $request->query->get('page'); // get a $_GET parameter
- $request->request->get('page'); // get a $_POST parameter
+ $request->request->get('page'); // get a $_POST parameter
+ }
Like the ``Response`` object, the request headers are stored in a ``HeaderBag``
object and are easily accessible.
diff --git a/book/http_cache.rst b/book/http_cache.rst
index 8079bd3571d..4133ee0d2f9 100644
--- a/book/http_cache.rst
+++ b/book/http_cache.rst
@@ -557,12 +557,14 @@ each ``ETag`` must be unique across all representations of the same resource.
To see a simple implementation, generate the ETag as the md5 of the content::
- public function indexAction()
+ use Symfony\Component\HttpFoundation\Request;
+
+ public function indexAction(Request $request)
{
$response = $this->render('MyBundle:Main:index.html.twig');
$response->setETag(md5($response->getContent()));
$response->setPublic(); // make sure the response is public/cacheable
- $response->isNotModified($this->getRequest());
+ $response->isNotModified($request);
return $response;
}
@@ -604,7 +606,9 @@ For instance, you can use the latest update date for all the objects needed to
compute the resource representation as the value for the ``Last-Modified``
header value::
- public function showAction($articleSlug)
+ use Symfony\Component\HttpFoundation\Request;
+
+ public function showAction($articleSlug, Request $request)
{
// ...
@@ -617,7 +621,7 @@ header value::
// Set response as public. Otherwise it will be private by default.
$response->setPublic();
- if ($response->isNotModified($this->getRequest())) {
+ if ($response->isNotModified($request)) {
return $response;
}
@@ -653,8 +657,9 @@ the better. The ``Response::isNotModified()`` method does exactly that by
exposing a simple and efficient pattern::
use Symfony\Component\HttpFoundation\Response;
+ use Symfony\Component\HttpFoundation\Request;
- public function showAction($articleSlug)
+ public function showAction($articleSlug, Request $request)
{
// Get the minimum information to compute
// the ETag or the Last-Modified value
@@ -671,7 +676,7 @@ exposing a simple and efficient pattern::
$response->setPublic();
// Check that the Response is not modified for the given Request
- if ($response->isNotModified($this->getRequest())) {
+ if ($response->isNotModified($request)) {
// return the 304 Response immediately
return $response;
} else {
diff --git a/book/security.rst b/book/security.rst
index dfcbfbad729..edf3172febd 100644
--- a/book/security.rst
+++ b/book/security.rst
@@ -319,7 +319,7 @@ First, enable form login under your firewall:
-
+
@@ -425,13 +425,13 @@ Next, create the controller that will display the login form::
namespace Acme\SecurityBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContext;
class SecurityController extends Controller
{
- public function loginAction()
+ public function loginAction(Request $request)
{
- $request = $this->getRequest();
$session = $request->getSession();
// get the login error if there is one
@@ -515,6 +515,11 @@ Finally, create the corresponding template:
+.. caution::
+
+ This login form is currently not protected against CSRF attacks. Read
+ :doc:`/cookbook/security/csrf_in_login_form` on how to protect your login form.
+
.. tip::
The ``error`` variable passed into the template is an instance of
@@ -673,6 +678,13 @@ see :doc:`/cookbook/security/form_login`.
for different firewalls. But usually for most applications, having one
main firewall is enough.
+ **5. Routing error pages are not covered by firewalls**
+
+ As Routing is done *before* security, Routing error pages are not covered
+ by any firewall. This means you can't check for security or even access
+ the user object on these pages. See :doc:`/cookbook/controller/error_pages`
+ for more details.
+
Authorization
-------------
@@ -1050,73 +1062,6 @@ the user will be redirected to ``https``:
),
),
-.. _book-security-securing-controller:
-
-Securing a Controller
-~~~~~~~~~~~~~~~~~~~~~
-
-Protecting your application based on URL patterns is easy, but may not be
-fine-grained enough in certain cases. When necessary, you can easily force
-authorization from inside a controller::
-
- // ...
- use Symfony\Component\Security\Core\Exception\AccessDeniedException;
-
- public function helloAction($name)
- {
- if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
- throw new AccessDeniedException();
- }
-
- // ...
- }
-
-.. _book-security-securing-controller-annotations:
-
-You can also choose to install and use the optional JMSSecurityExtraBundle,
-which can secure your controller using annotations::
-
- // ...
- use JMS\SecurityExtraBundle\Annotation\Secure;
-
- /**
- * @Secure(roles="ROLE_ADMIN")
- */
- public function helloAction($name)
- {
- // ...
- }
-
-For more information, see the `JMSSecurityExtraBundle`_ documentation.
-
-Securing other Services
-~~~~~~~~~~~~~~~~~~~~~~~
-
-In fact, anything in Symfony can be protected using a strategy similar to
-the one seen in the previous section. For example, suppose you have a service
-(i.e. a PHP class) whose job is to send emails from one user to another.
-You can restrict use of this class - no matter where it's being used from -
-to users that have a specific role.
-
-For more information on how you can use the Security component to secure
-different services and methods in your application, see :doc:`/cookbook/security/securing_services`.
-
-Access Control Lists (ACLs): Securing Individual Database Objects
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Imagine you are designing a blog system where your users can comment on your
-posts. Now, you want a user to be able to edit their own comments, but not
-those of other users. Also, as the admin user, you yourself want to be able
-to edit *all* comments.
-
-The Security component comes with an optional access control list (ACL) system
-that you can use when you need to control access to individual instances
-of an object in your system. *Without* ACL, you can secure your system so that
-only certain users can edit blog comments in general. But *with* ACL, you
-can restrict or allow access on a comment-by-comment basis.
-
-For more information, see the cookbook article: :doc:`/cookbook/security/acl`.
-
Users
-----
@@ -1406,6 +1351,11 @@ the password is simply run through the ``sha1`` algorithm one time and without
any extra encoding. You can now calculate the hashed password either programmatically
(e.g. ``hash('sha1', 'ryanpass')``) or via some online tool like `functions-online.com`_
+.. tip::
+
+ Supported algorithms for this method depend on your PHP version.
+ A full list is available calling the PHP function :phpfunction:`hash_algos`.
+
If you're creating your users dynamically (and storing them in a database),
you can use even tougher hashing algorithms and then rely on an actual password
encoder object to help you encode passwords. For example, suppose your User
@@ -1706,191 +1656,38 @@ In the above configuration, users with ``ROLE_ADMIN`` role will also have the
``ROLE_USER`` role. The ``ROLE_SUPER_ADMIN`` role has ``ROLE_ADMIN``, ``ROLE_ALLOWED_TO_SWITCH``
and ``ROLE_USER`` (inherited from ``ROLE_ADMIN``).
-.. _book-security-logging-out:
-
-Logging Out
------------
-
-Usually, you'll also want your users to be able to log out. Fortunately,
-the firewall can handle this automatically for you when you activate the
-``logout`` config parameter:
-
-.. configuration-block::
-
- .. code-block:: yaml
-
- # app/config/security.yml
- security:
- firewalls:
- secured_area:
- # ...
- logout:
- path: /logout
- target: /
- # ...
-
- .. code-block:: xml
-
-
-
-
-
-
-
-
-
-
- .. code-block:: php
-
- // app/config/security.php
- $container->loadFromExtension('security', array(
- 'firewalls' => array(
- 'secured_area' => array(
- // ...
- 'logout' => array('path' => 'logout', 'target' => '/'),
- ),
- ),
- // ...
- ));
-
-Once this is configured under your firewall, sending a user to ``/logout``
-(or whatever you configure the ``path`` to be), will un-authenticate the
-current user. The user will then be sent to the homepage (the value defined
-by the ``target`` parameter). Both the ``path`` and ``target`` config parameters
-default to what's specified here. In other words, unless you need to customize
-them, you can omit them entirely and shorten your configuration:
-
-.. configuration-block::
-
- .. code-block:: yaml
-
- logout: ~
-
- .. code-block:: xml
-
-
-
- .. code-block:: php
-
- 'logout' => array(),
-
-Note that you will *not* need to implement a controller for the ``/logout``
-URL as the firewall takes care of everything. You *do*, however, need to create
-a route so that you can use it to generate the URL:
-
-.. configuration-block::
-
- .. code-block:: yaml
-
- # app/config/routing.yml
- logout:
- path: /logout
-
- .. code-block:: xml
-
-
-
-
-
-
-
-
- .. code-block:: php
-
- // app/config/routing.php
- use Symfony\Component\Routing\RouteCollection;
- use Symfony\Component\Routing\Route;
-
- $collection = new RouteCollection();
- $collection->add('logout', new Route('/logout', array()));
-
- return $collection;
-
-Once the user has been logged out, they will be redirected to whatever path
-is defined by the ``target`` parameter above (e.g. the ``homepage``). For
-more information on configuring the logout, see the
-:doc:`Security Configuration Reference `.
-
-.. _book-security-template:
-
-Access Control in Templates
----------------------------
-
-If you want to check if the current user has a role inside a template, use
-the built-in helper function:
-
-.. configuration-block::
-
- .. code-block:: html+jinja
-
- {% if is_granted('ROLE_ADMIN') %}
- Delete
- {% endif %}
-
- .. code-block:: html+php
-
- isGranted('ROLE_ADMIN')): ?>
- Delete
-
-
-.. note::
-
- If you use this function and are *not* at a URL where there is a firewall
- active, an exception will be thrown. Again, it's almost always a good
- idea to have a main firewall that covers all URLs (as has been shown
- in this chapter).
-
-.. _book-security-template-expression:
+Access Control
+--------------
-.. versionadded:: 2.4
- The ``expression`` functionality was introduced in Symfony 2.4.
-
-You can also use expressions inside your templates:
-
-.. configuration-block::
-
- .. code-block:: html+jinja
-
- {% if is_granted(expression(
- '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
- )) %}
- Delete
- {% endif %}
-
- .. code-block:: html+php
-
- isGranted(new Expression(
- '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
- ))): ?>
- Delete
-
+Now that you have a User and Roles, you can go further than URL-pattern based
+authorization.
-For more details on expressions and security, see :ref:`book-security-expressions`.
+.. _book-security-securing-controller:
Access Control in Controllers
------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If you want to check if the current user has a role in your controller, use
-the :method:`Symfony\\Component\\Security\\Core\\SecurityContext::isGranted`
-method of the security context::
+Protecting your application based on URL patterns is easy, but may not be
+fine-grained enough in certain cases. When necessary, you can easily force
+authorization from inside a controller::
- public function indexAction()
+ // ...
+ use Symfony\Component\Security\Core\Exception\AccessDeniedException;
+
+ public function helloAction($name)
{
- // show different content to admin users
- if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
- // ... load admin content here
+ if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
+ throw new AccessDeniedException();
}
- // ... load other regular content here
+ // ...
}
-.. note::
+.. caution::
- A firewall must be active or an exception will be thrown when the ``isGranted``
- method is called. See the note above about templates for more details.
+ A firewall must be active or an exception will be thrown when the ``isGranted()``
+ method is called. It's almost always a good idea to have a main firewall that
+ covers all URLs (as is shown in this chapter).
.. _book-security-expressions:
@@ -1977,89 +1774,98 @@ Additionally, you have access to a number of functions inside the expression:
true if the user has actually logged in during this session (i.e. is
full-fledged).
-Impersonating a User
---------------------
+Access Control in Other Services
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sometimes, it's useful to be able to switch from one user to another without
-having to log out and log in again (for instance when you are debugging or trying
-to understand a bug a user sees that you can't reproduce). This can be easily
-done by activating the ``switch_user`` firewall listener:
+In fact, anything in Symfony can be protected using a strategy similar to
+the one seen in the previous section. For example, suppose you have a service
+(i.e. a PHP class) whose job is to send emails from one user to another.
+You can restrict use of this class - no matter where it's being used from -
+to users that have a specific role.
-.. configuration-block::
+For more information on how you can use the Security component to secure
+different services and methods in your application, see :doc:`/cookbook/security/securing_services`.
- .. code-block:: yaml
+.. _book-security-template:
- # app/config/security.yml
- security:
- firewalls:
- main:
- # ...
- switch_user: true
+Access Control in Templates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
- .. code-block:: xml
+If you want to check if the current user has a role inside a template, use
+the built-in helper function:
-
-
-
-
-
-
-
+.. configuration-block::
- .. code-block:: php
+ .. code-block:: html+jinja
- // app/config/security.php
- $container->loadFromExtension('security', array(
- 'firewalls' => array(
- 'main'=> array(
- // ...
- 'switch_user' => true
- ),
- ),
- ));
+ {% if is_granted('ROLE_ADMIN') %}
+ Delete
+ {% endif %}
-To switch to another user, just add a query string with the ``_switch_user``
-parameter and the username as the value to the current URL:
+ .. code-block:: html+php
-.. code-block:: text
+ isGranted('ROLE_ADMIN')): ?>
+ Delete
+
- http://example.com/somewhere?_switch_user=thomas
+.. note::
-To switch back to the original user, use the special ``_exit`` username:
+ If you use this function and are *not* at a URL behind a firewall
+ active, an exception will be thrown. Again, it's almost always a good
+ idea to have a main firewall that covers all URLs (as has been shown
+ in this chapter).
-.. code-block:: text
+.. _book-security-template-expression:
- http://example.com/somewhere?_switch_user=_exit
+.. versionadded:: 2.4
+ The ``expression`` functionality was introduced in Symfony 2.4.
-During impersonation, the user is provided with a special role called
-``ROLE_PREVIOUS_ADMIN``. In a template, for instance, this role can be used
-to show a link to exit impersonation:
+You can also use expressions inside your templates:
.. configuration-block::
.. code-block:: html+jinja
- {% if is_granted('ROLE_PREVIOUS_ADMIN') %}
- Exit impersonation
+ {% if is_granted(expression(
+ '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
+ )) %}
+ Delete
{% endif %}
.. code-block:: html+php
- isGranted('ROLE_PREVIOUS_ADMIN')): ?>
-
- Exit impersonation
-
+ isGranted(new Expression(
+ '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
+ ))): ?>
+ Delete
-Of course, this feature needs to be made available to a small group of users.
-By default, access is restricted to users having the ``ROLE_ALLOWED_TO_SWITCH``
-role. The name of this role can be modified via the ``role`` setting. For
-extra security, you can also change the query parameter name via the ``parameter``
-setting:
+For more details on expressions and security, see :ref:`book-security-expressions`.
+
+Access Control Lists (ACLs): Securing Individual Database Objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Imagine you are designing a blog system where your users can comment on your
+posts. Now, you want a user to be able to edit their own comments, but not
+those of other users. Also, as the admin user, you yourself want to be able
+to edit *all* comments.
+
+The Security component comes with an optional access control list (ACL) system
+that you can use when you need to control access to individual instances
+of an object in your system. *Without* ACL, you can secure your system so that
+only certain users can edit blog comments in general. But *with* ACL, you
+can restrict or allow access on a comment-by-comment basis.
+
+For more information, see the cookbook article: :doc:`/cookbook/security/acl`.
+
+.. _book-security-logging-out:
+
+Logging Out
+-----------
+
+Usually, you'll also want your users to be able to log out. Fortunately,
+the firewall can handle this automatically for you when you activate the
+``logout`` config parameter:
.. configuration-block::
@@ -2068,18 +1874,22 @@ setting:
# app/config/security.yml
security:
firewalls:
- main:
+ secured_area:
# ...
- switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
+ logout:
+ path: /logout
+ target: /
+ # ...
.. code-block:: xml
-
+
-
+
+
.. code-block:: php
@@ -2087,16 +1897,75 @@ setting:
// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
- 'main'=> array(
+ 'secured_area' => array(
// ...
- 'switch_user' => array(
- 'role' => 'ROLE_ADMIN',
- 'parameter' => '_want_to_be_this_user',
- ),
+ 'logout' => array('path' => 'logout', 'target' => '/'),
),
),
+ // ...
));
+Once this is configured under your firewall, sending a user to ``/logout``
+(or whatever you configure the ``path`` to be), will un-authenticate the
+current user. The user will then be sent to the homepage (the value defined
+by the ``target`` parameter). Both the ``path`` and ``target`` config parameters
+default to what's specified here. In other words, unless you need to customize
+them, you can omit them entirely and shorten your configuration:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ logout: ~
+
+ .. code-block:: xml
+
+
+
+ .. code-block:: php
+
+ 'logout' => array(),
+
+Note that you will *not* need to implement a controller for the ``/logout``
+URL as the firewall takes care of everything. You *do*, however, need to create
+a route so that you can use it to generate the URL:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/routing.yml
+ logout:
+ path: /logout
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/routing.php
+ use Symfony\Component\Routing\RouteCollection;
+ use Symfony\Component\Routing\Route;
+
+ $collection = new RouteCollection();
+ $collection->add('logout', new Route('/logout', array()));
+
+ return $collection;
+
+Once the user has been logged out, they will be redirected to whatever path
+is defined by the ``target`` parameter above (e.g. the ``homepage``). For
+more information on configuring the logout, see the
+:doc:`Security Configuration Reference `.
+
Stateless Authentication
------------------------
@@ -2217,6 +2086,7 @@ Learn more from the Cookbook
----------------------------
* :doc:`Forcing HTTP/HTTPS `
+* :doc:`Impersonating a User `
* :doc:`Blacklist users by IP address with a custom voter `
* :doc:`Access Control Lists (ACLs) `
* :doc:`/cookbook/security/remember_me`
diff --git a/book/translation.rst b/book/translation.rst
index 930e5641187..193945da32a 100644
--- a/book/translation.rst
+++ b/book/translation.rst
@@ -408,12 +408,14 @@ Handling the User's Locale
The locale of the current user is stored in the request and is accessible
via the ``request`` object::
- // access the request object in a standard controller
- $request = $this->getRequest();
+ use Symfony\Component\HttpFoundation\Request;
- $locale = $request->getLocale();
+ public function indexAction(Request $request)
+ {
+ $locale = $request->getLocale();
- $request->setLocale('en_US');
+ $request->setLocale('en_US');
+ }
.. tip::
diff --git a/components/console/introduction.rst b/components/console/introduction.rst
index 6af03289796..ea60102dcd6 100644
--- a/components/console/introduction.rst
+++ b/components/console/introduction.rst
@@ -160,6 +160,8 @@ You can also set these colors and options inside the tagname::
// bold text on a yellow background
$output->writeln('foo');
+.. verbosity-levels:
+
Verbosity Levels
~~~~~~~~~~~~~~~~
@@ -226,6 +228,13 @@ When the quiet level is used, all output is suppressed as the default
:method:`Symfony\Component\Console\Output::write `
method returns without actually printing.
+.. tip::
+
+ The MonologBridge provides a :class:`Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler`
+ class that allows you to display messages on the console. This is cleaner
+ than wrapping your output calls in conditions. For an example use in
+ the Symfony Framework, see :doc:/cookbook/logging/monolog_console.
+
Using Command Arguments
-----------------------
diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst
index c3c3247cbf8..d2dae74d2fd 100644
--- a/contributing/code/patches.rst
+++ b/contributing/code/patches.rst
@@ -177,14 +177,12 @@ in mind the following:
.. tip::
- You can check the coding standards of your patch by running the following
- `script `_
- (`source `_):
+ When submitting pull requests, `fabbot`_ checks your code
+ for common typos and verifies that you are using the PHP coding standards
+ as defined in PSR-1 and PSR-2.
- .. code-block:: bash
-
- $ cd /path/to/symfony/src
- $ php symfony-cs-fixer.phar fix . Symfony20Finder
+ A status is posted below the pull request description with a summary
+ of any problems it detects or any Travis CI build failures.
.. tip::
@@ -410,3 +408,4 @@ of all the commits. When you finish, execute the push command.
.. _`travis-ci.org status icon`: http://about.travis-ci.org/docs/user/status-images/
.. _`travis-ci.org Getting Started Guide`: http://about.travis-ci.org/docs/user/getting-started/
.. _`documentation repository`: https://github.com/symfony/symfony-docs
+.. _`fabbot`: http://fabbot.io
diff --git a/cookbook/console/logging.rst b/cookbook/console/logging.rst
index 5352fb581ee..b4c9ea9f872 100644
--- a/cookbook/console/logging.rst
+++ b/cookbook/console/logging.rst
@@ -34,7 +34,7 @@ container and use it to do the logging::
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\HttpKernel\Log\LoggerInterface;
+ use \Psr\Log\LoggerInterface;
class GreetCommand extends ContainerAwareCommand
{
@@ -54,7 +54,7 @@ container and use it to do the logging::
if ($input->getOption('yell')) {
$text = strtoupper($text);
- $logger->warn('Yelled: '.$text);
+ $logger->warning('Yelled: '.$text);
} else {
$logger->info('Greeted: '.$text);
}
@@ -69,146 +69,109 @@ setup), you should see the logged entries in ``app/logs/dev.log`` or ``app/logs/
Enabling automatic Exceptions logging
-------------------------------------
-To get your console application to automatically log uncaught exceptions
-for all of your commands, you'll need to do a little bit more work.
-
-First, create a new sub-class of :class:`Symfony\\Bundle\\FrameworkBundle\\Console\\Application`
-and override its :method:`Symfony\\Bundle\\FrameworkBundle\\Console\\Application::run`
-method, where exception handling should happen:
-
-.. caution::
-
- Due to the nature of the core :class:`Symfony\\Component\\Console\\Application`
- class, much of the :method:`run `
- method has to be duplicated and even a private property ``originalAutoExit``
- re-implemented. This serves as an example of what you *could* do in your
- code, though there is a high risk that something may break when upgrading
- to future versions of Symfony.
-
-.. code-block:: php
-
- // src/Acme/DemoBundle/Console/Application.php
- namespace Acme\DemoBundle\Console;
-
- use Symfony\Bundle\FrameworkBundle\Console\Application as BaseApplication;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\ConsoleOutputInterface;
- use Symfony\Component\HttpKernel\Log\LoggerInterface;
- use Symfony\Component\HttpKernel\KernelInterface;
- use Symfony\Component\Console\Output\ConsoleOutput;
- use Symfony\Component\Console\Input\ArgvInput;
-
- class Application extends BaseApplication
+To get your console application to automatically log uncaught exceptions for
+all of your commands, you can use :doc:`console events`.
+
+.. versionadded:: 2.3
+ Console events were added in Symfony 2.3.
+
+First configure a listener for console exception events in the service container:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/services.yml
+ services:
+ kernel.listener.command_dispatch:
+ class: Acme\DemoBundle\EventListener\ConsoleExceptionListener
+ arguments:
+ logger: "@logger"
+ tags:
+ - { name: kernel.event_listener, event: console.exception }
+
+ .. code-block:: xml
+
+
+
+
+
+
+ Acme\DemoBundle\EventListener\ConsoleExceptionListener
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/services.php
+ use Symfony\Component\DependencyInjection\Definition;
+ use Symfony\Component\DependencyInjection\Reference;
+
+ $container->setParameter(
+ 'console_exception_listener.class',
+ 'Acme\DemoBundle\EventListener\ConsoleExceptionListener'
+ );
+ $definitionConsoleExceptionListener = new Definition(
+ '%console_exception_listener.class%',
+ array(new Reference('logger'))
+ );
+ $definitionConsoleExceptionListener->addTag(
+ 'kernel.event_listener',
+ array('event' => 'console.exception')
+ );
+ $container->setDefinition(
+ 'kernel.listener.command_dispatch',
+ $definitionConsoleExceptionListener
+ );
+
+Then implement the actual listener::
+
+ // src/Acme/DemoBundle/EventListener/ConsoleExceptionListener.php
+ namespace Acme\DemoBundle\EventListener;
+
+ use Symfony\Component\Console\Event\ConsoleExceptionEvent;
+ use Psr\Log\LoggerInterface;
+
+ class ConsoleExceptionListener
{
- private $originalAutoExit;
+ private $logger;
- public function __construct(KernelInterface $kernel)
+ public function __construct(LoggerInterface $logger)
{
- parent::__construct($kernel);
- $this->originalAutoExit = true;
+ $this->logger = $logger;
}
- /**
- * Runs the current application.
- *
- * @param InputInterface $input An Input instance
- * @param OutputInterface $output An Output instance
- *
- * @return integer 0 if everything went fine, or an error code
- *
- * @throws \Exception When doRun returns Exception
- *
- * @api
- */
- public function run(InputInterface $input = null, OutputInterface $output = null)
- {
- // make the parent method throw exceptions, so you can log it
- $this->setCatchExceptions(false);
-
- if (null === $input) {
- $input = new ArgvInput();
- }
-
- if (null === $output) {
- $output = new ConsoleOutput();
- }
-
- try {
- $statusCode = parent::run($input, $output);
- } catch (\Exception $e) {
-
- /** @var $logger LoggerInterface */
- $logger = $this->getKernel()->getContainer()->get('logger');
-
- $message = sprintf(
- '%s: %s (uncaught exception) at %s line %s while running console command `%s`',
- get_class($e),
- $e->getMessage(),
- $e->getFile(),
- $e->getLine(),
- $this->getCommandName($input)
- );
- $logger->crit($message);
-
- if ($output instanceof ConsoleOutputInterface) {
- $this->renderException($e, $output->getErrorOutput());
- } else {
- $this->renderException($e, $output);
- }
- $statusCode = $e->getCode();
-
- $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1;
- }
-
- if ($this->originalAutoExit) {
- if ($statusCode > 255) {
- $statusCode = 255;
- }
- // @codeCoverageIgnoreStart
- exit($statusCode);
- // @codeCoverageIgnoreEnd
- }
+ public function onConsoleException(ConsoleExceptionEvent $event) {
+ $command = $event->getCommand();
+ $exception = $event->getException();
- return $statusCode;
- }
+ $message = sprintf(
+ '%s: %s (uncaught exception) at %s line %s while running console command `%s`',
+ get_class($exception),
+ $exception->getMessage(),
+ $exception->getFile(),
+ $exception->getLine(),
+ $command->getName()
+ );
- public function setAutoExit($bool)
- {
- // parent property is private, so we need to intercept it in a setter
- $this->originalAutoExit = (Boolean) $bool;
- parent::setAutoExit($bool);
+ $this->logger->error($message);
}
-
}
-In the code above, you disable exception catching so the parent ``run`` method
-will throw all exceptions. When an exception is caught, you simply log it by
-accessing the ``logger`` service from the service container and then handle
-the rest of the logic in the same way that the parent ``run`` method does
-(specifically, since the parent :method:`run `
-method will not handle exceptions rendering and status code handling when
-``catchExceptions`` is set to false, it has to be done in the overridden
-method).
-
-For the extended ``Application`` class to work properly with in console shell mode,
-you have to do a small trick to intercept the ``autoExit`` setter and store the
-setting in a different property, since the parent property is private.
-
-Now to be able to use your extended ``Application`` class you need to adjust
-the ``app/console`` script to use the new class instead of the default::
-
- // app/console
-
- // ...
- // replace the following line:
- // use Symfony\Bundle\FrameworkBundle\Console\Application;
- use Acme\DemoBundle\Console\Application;
-
- // ...
-
-That's it! Thanks to autoloader, your class will now be used instead of original
-one.
+In the code above, when any command throws an exception, the listener will
+receive an event. You can simply log it by passing the logger service via the
+service configuration. Your method receives a
+:class:`Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent`` object,
+which has methods to get information about the event and the exception.
Logging non-0 exit statuses
---------------------------
@@ -217,36 +180,98 @@ The logging capabilities of the console can be further extended by logging
non-0 exit statuses. This way you will know if a command had any errors, even
if no exceptions were thrown.
-In order to do that, you'd have to modify the ``run()`` method of your extended
-``Application`` class in the following way::
-
- public function run(InputInterface $input = null, OutputInterface $output = null)
+First configure a listener for console terminate events in the service container:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/services.yml
+ services:
+ kernel.listener.command_dispatch:
+ class: Acme\DemoBundle\EventListener\ConsoleTerminateListener
+ arguments:
+ logger: "@logger"
+ tags:
+ - { name: kernel.event_listener, event: console.terminate }
+
+ .. code-block:: xml
+
+
+
+
+
+
+ Acme\DemoBundle\EventListener\ConsoleExceptionListener
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/services.php
+ use Symfony\Component\DependencyInjection\Definition;
+ use Symfony\Component\DependencyInjection\Reference;
+
+ $container->setParameter(
+ 'console_terminate_listener.class',
+ 'Acme\DemoBundle\EventListener\ConsoleExceptionListener'
+ );
+ $definitionConsoleExceptionListener = new Definition(
+ '%console_terminate_listener.class%',
+ array(new Reference('logger'))
+ );
+ $definitionConsoleExceptionListener->addTag(
+ 'kernel.event_listener',
+ array('event' => 'console.terminate')
+ );
+ $container->setDefinition(
+ 'kernel.listener.command_dispatch',
+ $definitionConsoleExceptionListener
+ );
+
+Then implement the actual listener::
+
+ // src/Acme/DemoBundle/EventListener/ConsoleExceptionListener.php
+ namespace Acme/DemoBundle\EventListener;
+
+ use Symfony\Component\Console\Event\ConsoleTerminateEvent;
+ use Psr\Log\LoggerInterface;
+
+ class ConsoleTerminateListener
{
- // make the parent method throw exceptions, so you can log it
- $this->setCatchExceptions(false);
+ private $logger;
- // store the autoExit value before resetting it - you'll need it later
- $autoExit = $this->originalAutoExit;
- $this->setAutoExit(false);
+ public function __construct(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
- // ...
+ public function onConsoleTerminate(ConsoleTerminateEvent $event) {
+ $statusCode = $event->getExitCode();
+ $command = $event->getCommand();
- if ($autoExit) {
- if ($statusCode > 255) {
- $statusCode = 255;
+ if ($statusCode === 0) {
+ return;
}
- // log non-0 exit codes along with command name
- if ($statusCode !== 0) {
- /** @var $logger LoggerInterface */
- $logger = $this->getKernel()->getContainer()->get('logger');
- $logger->warn(sprintf('Command `%s` exited with status code %d', $this->getCommandName($input), $statusCode));
+ if ($statusCode > 255) {
+ $statusCode = 255;
+ $event->setExitCode($statusCode);
}
- // @codeCoverageIgnoreStart
- exit($statusCode);
- // @codeCoverageIgnoreEnd
+ $this->logger->warning(sprintf(
+ 'Command `%s` exited with status code %d',
+ $command->getName(),
+ $statusCode
+ ));
}
-
- return $statusCode;
}
diff --git a/cookbook/doctrine/custom_dql_functions.rst b/cookbook/doctrine/custom_dql_functions.rst
index 9c863055c08..35141309b5e 100644
--- a/cookbook/doctrine/custom_dql_functions.rst
+++ b/cookbook/doctrine/custom_dql_functions.rst
@@ -17,17 +17,14 @@ In Symfony, you can register your custom DQL functions as follows:
doctrine:
orm:
# ...
- entity_managers:
- default:
- # ...
- dql:
- string_functions:
- test_string: Acme\HelloBundle\DQL\StringFunction
- second_string: Acme\HelloBundle\DQL\SecondStringFunction
- numeric_functions:
- test_numeric: Acme\HelloBundle\DQL\NumericFunction
- datetime_functions:
- test_datetime: Acme\HelloBundle\DQL\DatetimeFunction
+ dql:
+ string_functions:
+ test_string: Acme\HelloBundle\DQL\StringFunction
+ second_string: Acme\HelloBundle\DQL\SecondStringFunction
+ numeric_functions:
+ test_numeric: Acme\HelloBundle\DQL\NumericFunction
+ datetime_functions:
+ test_datetime: Acme\HelloBundle\DQL\DatetimeFunction
.. code-block:: xml
@@ -41,15 +38,12 @@ In Symfony, you can register your custom DQL functions as follows:
-
-
-
- Acme\HelloBundle\DQL\SecondStringFunction
- Acme\HelloBundle\DQL\DatetimeFunction
-
-
+
+ Acme\HelloBundle\DQL\SecondStringFunction
+ Acme\HelloBundle\DQL\DatetimeFunction
+
@@ -60,23 +54,16 @@ In Symfony, you can register your custom DQL functions as follows:
$container->loadFromExtension('doctrine', array(
'orm' => array(
// ...
-
- 'entity_managers' => array(
- 'default' => array(
- // ...
-
- 'dql' => array(
- 'string_functions' => array(
- 'test_string' => 'Acme\HelloBundle\DQL\StringFunction',
- 'second_string' => 'Acme\HelloBundle\DQL\SecondStringFunction',
- ),
- 'numeric_functions' => array(
- 'test_numeric' => 'Acme\HelloBundle\DQL\NumericFunction',
- ),
- 'datetime_functions' => array(
- 'test_datetime' => 'Acme\HelloBundle\DQL\DatetimeFunction',
- ),
- ),
+ 'dql' => array(
+ 'string_functions' => array(
+ 'test_string' => 'Acme\HelloBundle\DQL\StringFunction',
+ 'second_string' => 'Acme\HelloBundle\DQL\SecondStringFunction',
+ ),
+ 'numeric_functions' => array(
+ 'test_numeric' => 'Acme\HelloBundle\DQL\NumericFunction',
+ ),
+ 'datetime_functions' => array(
+ 'test_datetime' => 'Acme\HelloBundle\DQL\DatetimeFunction',
),
),
),
diff --git a/cookbook/logging/index.rst b/cookbook/logging/index.rst
index dda7d7cafdd..2570b3d5627 100644
--- a/cookbook/logging/index.rst
+++ b/cookbook/logging/index.rst
@@ -6,5 +6,6 @@ Logging
monolog
monolog_email
+ monolog_console
monolog_regex_based_excludes
channels_handlers
diff --git a/cookbook/logging/monolog.rst b/cookbook/logging/monolog.rst
index 32e064598e1..c2c6559dd75 100644
--- a/cookbook/logging/monolog.rst
+++ b/cookbook/logging/monolog.rst
@@ -23,8 +23,7 @@ your controller::
}
The ``logger`` service has different methods for different logging levels.
-See :class:`Symfony\\Component\\HttpKernel\\Log\\LoggerInterface` for details
-on which methods are available.
+See LoggerInterface_ for details on which methods are available.
Handlers and Channels: Writing logs to different Locations
----------------------------------------------------------
@@ -351,3 +350,4 @@ using a processor.
handler level instead of globally.
.. _Monolog: https://github.com/Seldaek/monolog
+.. _LoggerInterface: https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php
diff --git a/cookbook/logging/monolog_console.rst b/cookbook/logging/monolog_console.rst
new file mode 100644
index 00000000000..3a22b7dcfbc
--- /dev/null
+++ b/cookbook/logging/monolog_console.rst
@@ -0,0 +1,183 @@
+.. index::
+ single: Logging; Console messages
+
+How to Configure Monolog to Display Console Messages
+====================================================
+
+.. versionadded:: 2.3
+ This feature was introduced to the MonologBundle in version 2.4, which
+ was first packaged with Symfony at version 2.4 (but compatible with Symfony 2.3).
+
+It is possible to use the console to print messages for certain :ref:`verbosity-levels`
+using the :class:`Symfony\\Component\\Console\\Output\\OutputInterface`
+instance that is passed when a command gets executed.
+
+When a lot of logging has to happen, it's cumbersome to print information
+depending on the verbosity settings (``-v``, ``-vv``, ``-vvv``) because the
+calls need to be wrapped in conditions. The code quickly gets verbose or dirty.
+For example::
+
+ use Symfony\Component\Console\Input\InputInterface;
+ use Symfony\Component\Console\Output\OutputInterface;
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
+ $output->writeln('Some info');
+ }
+
+ if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
+ $output->writeln('Some more info');
+ }
+ }
+
+Instead of using these semantic methods to test for each of the verbosity
+levels, `MonologBundle`_ 2.4 provides a `ConsoleHandler`_ that listens to
+console events and writes log messages to the console output depending on the
+current log level and the console verbosity.
+
+The example above could then be rewritten as::
+
+ use Symfony\Component\Console\Input\InputInterface;
+ use Symfony\Component\Console\Output\OutputInterface;
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ // assuming the Command extends ContainerAwareCommand...
+ $logger = $this->getContainer()->get('logger');
+ $logger->debug('Some info');
+
+ $logger->notice('Some more info');
+ }
+
+Depending on the verbosity level that the command is run in and the user's
+configuration (see below), these messages may or may not be displayed to
+the console. If they are displayed, they are timestamped and colored appropriately.
+Additionally, error logs are written to the error output (php://stderr).
+There is no need to conditionally handle the verbosity settings anymore.
+
+The Monolog console handler is enabled in the Monolog configuration. This is
+the default in Symfony Standard Edition 2.4 too.
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ monolog:
+ handlers:
+ console:
+ type: console
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension('monolog', array(
+ 'handlers' => array(
+ 'console' => array(
+ 'type' => 'console',
+ ),
+ ),
+ ));
+
+With the ``verbosity_levels`` option you can adapt the mapping between
+verbosity and log level. In the given example it will also show notices in
+normal verbosity mode (instead of warnings only). Additionally, it will only
+use messages logged with the custom ``my_channel`` channel and it changes the
+display style via a custom formatter. See also the :doc:`reference/configuration/monolog`
+for more information:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ monolog:
+ handlers:
+ console:
+ type: console
+ verbosity_levels:
+ VERBOSITY_NORMAL: NOTICE
+ channels: my_channel
+ formatter: my_formatter
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+ my_channel
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension('monolog', array(
+ 'handlers' => array(
+ 'console' => array(
+ 'type' => 'console',
+ 'verbosity_levels' => array(
+ 'VERBOSITY_NORMAL' => 'NOTICE',
+ ),
+ 'channels' => 'my_channel',
+ 'formatter' => 'my_formatter',
+ ),
+ ),
+ ));
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/services.yml
+ services:
+ my_formatter:
+ class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter
+ arguments:
+ - "[%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n"
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+ [%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/services.php
+ $container
+ ->register('my_formatter', 'Symfony\Bridge\Monolog\Formatter\ConsoleFormatter')
+ ->addArgument('[%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n')
+ ;
+
+.. _ConsoleHandler: https://github.com/symfony/MonologBridge/blob/master/Handler/ConsoleHandler.php
+.. _MonologBundle: https://github.com/symfony/MonologBundle
diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc
index 92c7bdc8957..64590e38e1d 100644
--- a/cookbook/map.rst.inc
+++ b/cookbook/map.rst.inc
@@ -101,6 +101,7 @@
* :doc:`/cookbook/logging/monolog`
* :doc:`/cookbook/logging/monolog_email`
+ * :doc:`/cookbook/logging/monolog_console`
* :doc:`/cookbook/logging/monolog_regex_based_excludes`
* :doc:`/cookbook/logging/channels_handlers`
@@ -128,6 +129,7 @@
* :doc:`/cookbook/security/entity_provider`
* :doc:`/cookbook/security/remember_me`
+ * :doc:`/cookbook/security/impersonating_user`
* :doc:`/cookbook/security/voters`
* :doc:`/cookbook/security/acl`
* :doc:`/cookbook/security/acl_advanced`
@@ -140,6 +142,7 @@
* :doc:`/cookbook/security/api_key_authentication`
* :doc:`/cookbook/security/custom_authentication_provider`
* :doc:`/cookbook/security/target_path`
+ * :doc:`/cookbook/security/csrf_in_login_form`
* **Serializer**
diff --git a/cookbook/security/csrf_in_login_form.rst b/cookbook/security/csrf_in_login_form.rst
new file mode 100644
index 00000000000..edc63ce1acb
--- /dev/null
+++ b/cookbook/security/csrf_in_login_form.rst
@@ -0,0 +1,171 @@
+.. index::
+ single: Security; CSRF in the Login Form
+
+Using CSRF in the Login Form
+============================
+
+When using a login form, you should make sure that you are protected against CSRF
+(`Cross-site request forgery`_). The Security component already has built-in support
+for CSRF. In this article you'll learn how you can use it in your login form.
+
+.. note::
+
+ Login CSRF attacks are a bit less well-known. See `Forging Login Requests`_
+ if you're curious about more details.
+
+Configuring CSRF
+----------------
+
+First, configure the Security component so it can use CSRF protection.
+The Security component needs a CSRF provider. You can set this to use the default
+provider available in the Form component:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/security.yml
+ security:
+ firewalls:
+ secured_area:
+ # ...
+ form_login:
+ # ...
+ csrf_provider: form.csrf_provider
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/security.php
+ $container->loadFromExtension('security', array(
+ 'firewalls' => array(
+ 'secured_area' => array(
+ // ...
+ 'form_login' => array(
+ // ...
+ 'csrf_provider' => 'form.csrf_provider',
+ )
+ )
+ )
+ ));
+
+The Security component can be configured further, but this is all information
+it needs to be able to use CSRF in the login form.
+
+Rendering the CSRF field
+------------------------
+
+Now that Security component will check for the CSRF token, you have to add
+a *hidden* field to the login form containing the CSRF token. By default,
+this field is named ``_csrf_token``. That hidden field must contain the CSRF
+token, which can be generated by using the ``csrf_token`` function. That
+function requires a token ID, which must be set to ``authenticate`` when
+using the login form:
+
+.. configuration-block::
+
+ .. code-block:: html+twig
+
+ {# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #}
+
+ {# ... #}
+
+
+ .. code-block:: html+php
+
+
+
+
+
+
+After this, you have protected your login form against CSRF attacks.
+
+.. tip::
+
+ You can change the name of the field by setting ``csrf_parameter`` and change
+ the token ID by setting ``intention`` in your configuration:
+
+ .. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/security.yml
+ security:
+ firewalls:
+ secured_area:
+ # ...
+ form_login:
+ # ...
+ csrf_parameter: _csrf_security_token
+ intention: a_private_string
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/security.php
+ $container->loadFromExtension('security', array(
+ 'firewalls' => array(
+ 'secured_area' => array(
+ // ...
+ 'form_login' => array(
+ // ...
+ 'csrf_parameter' => '_csrf_security_token',
+ 'intention' => 'a_private_string',
+ )
+ )
+ )
+ ));
+
+.. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery
+.. _`Forging Login Requests`: http://en.wikipedia.org/wiki/Cross-site_request_forgery#Forging_login_requests
\ No newline at end of file
diff --git a/cookbook/security/entity_provider.rst b/cookbook/security/entity_provider.rst
index 53142551e5a..a2ef0f2a6d2 100644
--- a/cookbook/security/entity_provider.rst
+++ b/cookbook/security/entity_provider.rst
@@ -171,7 +171,7 @@ focus on the most important methods that come from the
.. note::
- When implementing the
+ If you choose to implement
:class:`Symfony\\Component\\Security\\Core\\User\\EquatableInterface`,
you determine yourself which properties need to be compared to distinguish
your user objects.
@@ -198,14 +198,27 @@ interface forces the class to implement the five following methods:
For more details on each of these, see :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface`.
-.. note::
+.. sidebar:: What is the importance of serialize and unserialize?
The :phpclass:`Serializable` interface and its ``serialize`` and ``unserialize``
methods have been added to allow the ``User`` class to be serialized
to the session. This may or may not be needed depending on your setup,
- but it's probably a good idea. Only the ``id`` needs to be serialized,
- because the :method:`Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider::refreshUser`
- method reloads the user on each request by using the ``id``.
+ but it's probably a good idea. The ``id`` is the most important value
+ that needs to be serialized because the
+ :method:`Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider::refreshUser`
+ method reloads the user on each request by using the ``id``. In practice,
+ this means that the User object is reloaded from the database on each
+ request using the ``id`` from the serialized object. This makes sure
+ all of the User's data is fresh.
+
+ Symfony also uses the ``username``, ``salt``, and ``password`` to verify
+ that the User has not changed between requests. Failing to serialize
+ these may cause you to be logged out on each request. If your User implements
+ :class:`Symfony\\Component\\Security\\Core\\User\\EquatableInterface`,
+ then instead of these properties being checked, your ``isEqualTo`` method
+ is simply called, and you can check whatever properties you want. Unless
+ you understand this, you probably *won't* need to implement this interface
+ or worry about it.
Below is an export of the ``User`` table from MySQL with user ``admin`` and
password ``admin`` (which has been encoded). For details on how to create
diff --git a/cookbook/security/impersonating_user.rst b/cookbook/security/impersonating_user.rst
new file mode 100644
index 00000000000..c3bd0b708c6
--- /dev/null
+++ b/cookbook/security/impersonating_user.rst
@@ -0,0 +1,136 @@
+.. index::
+ single: Security; Impersonating User
+
+How to Impersonate a User
+=========================
+
+Sometimes, it's useful to be able to switch from one user to another without
+having to log out and log in again (for instance when you are debugging or trying
+to understand a bug a user sees that you can't reproduce). This can be easily
+done by activating the ``switch_user`` firewall listener:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/security.yml
+ security:
+ firewalls:
+ main:
+ # ...
+ switch_user: true
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/security.php
+ $container->loadFromExtension('security', array(
+ 'firewalls' => array(
+ 'main'=> array(
+ // ...
+ 'switch_user' => true
+ ),
+ ),
+ ));
+
+To switch to another user, just add a query string with the ``_switch_user``
+parameter and the username as the value to the current URL:
+
+.. code-block:: text
+
+ http://example.com/somewhere?_switch_user=thomas
+
+To switch back to the original user, use the special ``_exit`` username:
+
+.. code-block:: text
+
+ http://example.com/somewhere?_switch_user=_exit
+
+During impersonation, the user is provided with a special role called
+``ROLE_PREVIOUS_ADMIN``. In a template, for instance, this role can be used
+to show a link to exit impersonation:
+
+.. configuration-block::
+
+ .. code-block:: html+jinja
+
+ {% if is_granted('ROLE_PREVIOUS_ADMIN') %}
+ Exit impersonation
+ {% endif %}
+
+ .. code-block:: html+php
+
+ isGranted('ROLE_PREVIOUS_ADMIN')): ?>
+
+ Exit impersonation
+
+
+
+Of course, this feature needs to be made available to a small group of users.
+By default, access is restricted to users having the ``ROLE_ALLOWED_TO_SWITCH``
+role. The name of this role can be modified via the ``role`` setting. For
+extra security, you can also change the query parameter name via the ``parameter``
+setting:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/security.yml
+ security:
+ firewalls:
+ main:
+ # ...
+ switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/security.php
+ $container->loadFromExtension('security', array(
+ 'firewalls' => array(
+ 'main'=> array(
+ // ...
+ 'switch_user' => array(
+ 'role' => 'ROLE_ADMIN',
+ 'parameter' => '_want_to_be_this_user',
+ ),
+ ),
+ ),
+ ));
diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst
index e9cad89cb50..63bd29520b3 100644
--- a/cookbook/security/index.rst
+++ b/cookbook/security/index.rst
@@ -6,6 +6,7 @@ Security
entity_provider
remember_me
+ impersonating_user
voters
acl
acl_advanced
@@ -18,3 +19,4 @@ Security
api_key_authentication
custom_authentication_provider
target_path
+ csrf_in_login_form
diff --git a/cookbook/security/voters.rst b/cookbook/security/voters.rst
index 0d4e526c742..8798bcefa06 100644
--- a/cookbook/security/voters.rst
+++ b/cookbook/security/voters.rst
@@ -5,10 +5,10 @@ How to implement your own Voter to blacklist IP Addresses
=========================================================
The Symfony2 Security component provides several layers to authorize users.
-One of the layers is called a `voter`. A voter is a dedicated class that checks
-if the user has the rights to be connected to the application. For instance,
-Symfony2 provides a layer that checks if the user is fully authorized or if
-it has some expected roles.
+One of the layers is called a "voter". A voter is a dedicated class that checks
+if the user has the rights to connect to the application or access a specific
+resource/URL. For instance, Symfony2 provides a layer that checks if the user
+is fully authorized or if it has some expected roles.
It is sometimes useful to create a custom voter to handle a specific case not
handled by the framework. In this section, you'll learn how to create a voter
@@ -34,18 +34,18 @@ The ``supportsAttribute()`` method is used to check if the voter supports
the given user attribute (i.e: a role, an ACL, etc.).
The ``supportsClass()`` method is used to check if the voter supports the
-current user token class.
+class of the object whose access is being checked (doesn't apply to this entry).
The ``vote()`` method must implement the business logic that verifies whether
or not the user is granted access. This method must return one of the following
values:
-* ``VoterInterface::ACCESS_GRANTED``: The user is allowed to access the application
-* ``VoterInterface::ACCESS_ABSTAIN``: The voter cannot decide if the user is granted or not
-* ``VoterInterface::ACCESS_DENIED``: The user is not allowed to access the application
+* ``VoterInterface::ACCESS_GRANTED``: The authorization will be granted by this voter;
+* ``VoterInterface::ACCESS_ABSTAIN``: The voter cannot decide if authorization should be granted;
+* ``VoterInterface::ACCESS_DENIED``: The authorization will be denied by this voter.
In this example, you'll check if the user's IP address matches against a list of
-blacklisted addresses. If the user's IP is blacklisted, you'll return
+blacklisted addresses and "something" will be the application. If the user's IP is blacklisted, you'll return
``VoterInterface::ACCESS_DENIED``, otherwise you'll return
``VoterInterface::ACCESS_ABSTAIN`` as this voter's purpose is only to deny
access, not to grant access.
diff --git a/cookbook/session/locale_sticky_session.rst b/cookbook/session/locale_sticky_session.rst
index 5f3da5a5977..172930869d7 100644
--- a/cookbook/session/locale_sticky_session.rst
+++ b/cookbook/session/locale_sticky_session.rst
@@ -100,4 +100,9 @@ use the :method:`Request::getLocale getRequest()->getLocale();
+ use Symfony\Component\HttpFoundation\Request;
+
+ public function indexAction(Request $request)
+ {
+ $locale = $request->getLocale();
+ }
diff --git a/quick_tour/the_controller.rst b/quick_tour/the_controller.rst
index ce5f1331657..65e8e9e4da0 100644
--- a/quick_tour/the_controller.rst
+++ b/quick_tour/the_controller.rst
@@ -90,17 +90,22 @@ Getting information from the Request
------------------------------------
Besides the values of the routing placeholders, the controller also has access
-to the ``Request`` object::
+to the ``Request`` object. The framework injects the ``Request`` object in the
+controller if a variable is type hinted with
+`Symfony\Component\HttpFoundation\Request`::
- $request = $this->getRequest();
+ use Symfony\Component\HttpFoundation\Request;
- $request->isXmlHttpRequest(); // is it an Ajax request?
+ public function indexAction(Request $request)
+ {
+ $request->isXmlHttpRequest(); // is it an Ajax request?
- $request->getPreferredLanguage(array('en', 'fr'));
+ $request->getPreferredLanguage(array('en', 'fr'));
- $request->query->get('page'); // get a $_GET parameter
+ $request->query->get('page'); // get a $_GET parameter
- $request->request->get('page'); // get a $_POST parameter
+ $request->request->get('page'); // get a $_POST parameter
+ }
In a template, you can also access the ``Request`` object via the
``app.request`` variable:
@@ -122,16 +127,21 @@ by using native PHP sessions.
Storing and retrieving information from the session can be easily achieved
from any controller::
- $session = $this->getRequest()->getSession();
+ use Symfony\Component\HttpFoundation\Request;
- // store an attribute for reuse during a later user request
- $session->set('foo', 'bar');
+ public function indexAction(Request $request)
+ {
+ $session = $this->request->getSession();
- // in another controller for another request
- $foo = $session->get('foo');
+ // store an attribute for reuse during a later user request
+ $session->set('foo', 'bar');
- // use a default value if the key doesn't exist
- $filters = $session->get('filters', array());
+ // in another controller for another request
+ $foo = $session->get('foo');
+
+ // use a default value if the key doesn't exist
+ $filters = $session->get('filters', array());
+ }
You can also store small messages that will only be available for the very
next request::
diff --git a/reference/configuration/monolog.rst b/reference/configuration/monolog.rst
index 24365fbd682..1b09cbc020c 100644
--- a/reference/configuration/monolog.rst
+++ b/reference/configuration/monolog.rst
@@ -25,6 +25,13 @@ MonologBundle Configuration ("monolog")
action_level: WARNING
buffer_size: 30
handler: custom
+ console:
+ type: console
+ verbosity_levels:
+ VERBOSITY_NORMAL: WARNING
+ VERBOSITY_VERBOSE: NOTICE
+ VERBOSITY_VERY_VERBOSE: INFO
+ VERBOSITY_DEBUG: DEBUG
custom:
type: service
id: my_handler
@@ -84,6 +91,10 @@ MonologBundle Configuration ("monolog")
action-level="warning"
handler="custom"
/>
+ ` type:
These options inherit from the :doc:`form ` type:
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/invalid_message.rst.inc
.. include:: /reference/forms/types/options/invalid_message_parameters.rst.inc
diff --git a/reference/forms/types/button.rst b/reference/forms/types/button.rst
index 6e8cce6ed57..5c73b5f34e1 100644
--- a/reference/forms/types/button.rst
+++ b/reference/forms/types/button.rst
@@ -15,6 +15,7 @@ A simple, non-responsive button.
| Options | - `attr`_ |
| | - `disabled`_ |
| | - `label`_ |
+| | - `label_attr`_ |
| | - `translation_domain`_ |
+----------------------+----------------------------------------------------------------------+
| Parent type | none |
@@ -31,4 +32,6 @@ Options
.. include:: /reference/forms/types/options/button_label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
.. include:: /reference/forms/types/options/button_translation_domain.rst.inc
diff --git a/reference/forms/types/checkbox.rst b/reference/forms/types/checkbox.rst
index ddefd70ee06..adb6f8d1b24 100644
--- a/reference/forms/types/checkbox.rst
+++ b/reference/forms/types/checkbox.rst
@@ -16,6 +16,7 @@ if the box is unchecked, the value will be set to false.
| Inherited | - `data`_ |
| options | - `required`_ |
| | - `label`_ |
+| | - `label_attr`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -50,7 +51,7 @@ not affect the value that's set on your object.
.. caution::
- To make a checkbox checked by default, use the `data`_ option.
+ To make a checkbox checked by default, set the `data`_ option to ``true``.
Inherited options
-----------------
@@ -63,6 +64,8 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/choice.rst b/reference/forms/types/choice.rst
index 551db27c551..b69e48c32ed 100644
--- a/reference/forms/types/choice.rst
+++ b/reference/forms/types/choice.rst
@@ -22,6 +22,8 @@ option.
+-------------+------------------------------------------------------------------------------+
| Inherited | - `required`_ |
| options | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -116,6 +118,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/collection.rst b/reference/forms/types/collection.rst
index e5df85ec0f9..8c5adb11a1f 100644
--- a/reference/forms/types/collection.rst
+++ b/reference/forms/types/collection.rst
@@ -21,6 +21,7 @@ forms, which is useful when creating forms that expose one-to-many relationships
| | - `prototype_name`_ |
+-------------+-----------------------------------------------------------------------------+
| Inherited | - `label`_ |
+| | - `label_attr`_ |
| options | - `error_bubbling`_ |
| | - `error_mapping`_ |
| | - `by_reference`_ |
@@ -341,9 +342,7 @@ Not all options are listed here - only the most applicable to this type:
.. include:: /reference/forms/types/options/label.rst.inc
-.. include:: /reference/forms/types/options/mapped.rst.inc
-
-.. include:: /reference/forms/types/options/error_mapping.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
error_bubbling
~~~~~~~~~~~~~~
@@ -352,8 +351,12 @@ error_bubbling
.. include:: /reference/forms/types/options/_error_bubbling_body.rst.inc
+.. include:: /reference/forms/types/options/error_mapping.rst.inc
+
.. _reference-form-types-by-reference:
.. include:: /reference/forms/types/options/by_reference.rst.inc
.. include:: /reference/forms/types/options/empty_data.rst.inc
+
+.. include:: /reference/forms/types/options/mapped.rst.inc
diff --git a/reference/forms/types/country.rst b/reference/forms/types/country.rst
index 8d60cb91d98..ceb1f8385d8 100644
--- a/reference/forms/types/country.rst
+++ b/reference/forms/types/country.rst
@@ -33,6 +33,8 @@ you should just use the ``choice`` type directly.
| | - `error_mapping`_ |
| | - `required`_ |
| | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `mapped`_ |
@@ -76,6 +78,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/currency.rst b/reference/forms/types/currency.rst
index d921ce09a1b..b92d1a3e4d5 100644
--- a/reference/forms/types/currency.rst
+++ b/reference/forms/types/currency.rst
@@ -26,6 +26,8 @@ should just use the ``choice`` type directly.
| | - `error_bubbling`_ |
| | - `required`_ |
| | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `mapped`_ |
@@ -60,12 +62,16 @@ These options inherit from the :doc:`choice` type
.. include:: /reference/forms/types/options/error_bubbling.rst.inc
-These options inherit from the :doc:`date` type:
+These options inherit from the :doc:`form` type:
.. include:: /reference/forms/types/options/required.rst.inc
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/date.rst b/reference/forms/types/date.rst
index c2fe15c3c07..4e5d284e7cd 100644
--- a/reference/forms/types/date.rst
+++ b/reference/forms/types/date.rst
@@ -32,8 +32,9 @@ day, and year) or three select boxes (see the `widget`_ option).
| Overridden Options | - `by_reference`_ |
| | - `error_bubbling`_ |
+----------------------+-----------------------------------------------------------------------------+
-| Inherited | - `invalid_message`_ |
-| options | - `invalid_message_parameters`_ |
+| Inherited | - `data`_ |
+| options | - `invalid_message`_ |
+| | - `invalid_message_parameters`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `mapped`_ |
@@ -138,6 +139,8 @@ Inherited options
These options inherit from the :doc:`form ` type:
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/invalid_message.rst.inc
.. include:: /reference/forms/types/options/invalid_message_parameters.rst.inc
diff --git a/reference/forms/types/datetime.rst b/reference/forms/types/datetime.rst
index 1b59ddff52e..e607655f03e 100644
--- a/reference/forms/types/datetime.rst
+++ b/reference/forms/types/datetime.rst
@@ -31,8 +31,9 @@ data can be a ``DateTime`` object, a string, a timestamp or an array.
| | - `view_timezone`_ |
| | - `empty_value`_ |
+----------------------+-----------------------------------------------------------------------------+
-| Inherited | - `invalid_message`_ |
-| options | - `invalid_message_parameters`_ |
+| Inherited | - `data`_ |
+| options | - `invalid_message`_ |
+| | - `invalid_message_parameters`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `mapped`_ |
@@ -121,6 +122,8 @@ Inherited options
These options inherit from the :doc:`form ` type:
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/invalid_message.rst.inc
.. include:: /reference/forms/types/options/invalid_message_parameters.rst.inc
diff --git a/reference/forms/types/email.rst b/reference/forms/types/email.rst
index fb6ca9a2868..1ba1ec68d95 100644
--- a/reference/forms/types/email.rst
+++ b/reference/forms/types/email.rst
@@ -13,6 +13,8 @@ The ``email`` field is a text field that is rendered using the HTML5
| Inherited | - `max_length`_ |
| options | - `required`_ |
| | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `trim`_ |
| | - `read_only`_ |
| | - `disabled`_ |
@@ -36,6 +38,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/trim.rst.inc
.. include:: /reference/forms/types/options/read_only.rst.inc
diff --git a/reference/forms/types/entity.rst b/reference/forms/types/entity.rst
index ec1b2075320..69c2537e977 100644
--- a/reference/forms/types/entity.rst
+++ b/reference/forms/types/entity.rst
@@ -21,12 +21,14 @@ objects from the database.
| Overridden | - `choices`_ |
| Options | - `choice_list`_ |
+-------------+------------------------------------------------------------------+
-| Inherited | - `required`_ |
-| options | - `label`_ |
-| | - `multiple`_ |
-| | - `expanded`_ |
+| Inherited | - `multiple`_ |
+| options | - `expanded`_ |
| | - `preferred_choices`_ |
| | - `empty_value`_ |
+| | - `required`_ |
+| | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -195,6 +197,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/file.rst b/reference/forms/types/file.rst
index a33dae8d992..19abd57d0ae 100644
--- a/reference/forms/types/file.rst
+++ b/reference/forms/types/file.rst
@@ -11,6 +11,7 @@ The ``file`` type represents a file input in your form.
+-------------+---------------------------------------------------------------------+
| Inherited | - `required`_ |
| options | - `label`_ |
+| | - `label_attr`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -85,6 +86,8 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/form.rst b/reference/forms/types/form.rst
index b51fe597078..1357650086f 100644
--- a/reference/forms/types/form.rst
+++ b/reference/forms/types/form.rst
@@ -9,10 +9,16 @@ See :class:`Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType`.
The ``form`` type predefines a couple of options that are then available
on all fields.
+.. include:: /reference/forms/types/options/compound.rst.inc
+
.. include:: /reference/forms/types/options/data.rst.inc
.. include:: /reference/forms/types/options/required.rst.inc
+.. include:: /reference/forms/types/options/label.rst.inc
+
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
.. include:: /reference/forms/types/options/constraints.rst.inc
.. include:: /reference/forms/types/options/cascade_validation.rst.inc
diff --git a/reference/forms/types/integer.rst b/reference/forms/types/integer.rst
index fef0802fb7b..ba4a0760b25 100644
--- a/reference/forms/types/integer.rst
+++ b/reference/forms/types/integer.rst
@@ -21,6 +21,8 @@ integers. By default, all non-integer values (e.g. 6.78) will round down (e.g. 6
+-------------+-----------------------------------------------------------------------+
| Inherited | - `required`_ |
| options | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -79,6 +81,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/language.rst b/reference/forms/types/language.rst
index dc83dd0d903..8205045e6e4 100644
--- a/reference/forms/types/language.rst
+++ b/reference/forms/types/language.rst
@@ -34,6 +34,8 @@ you should just use the ``choice`` type directly.
| | - `error_mapping`_ |
| | - `required`_ |
| | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `mapped`_ |
@@ -77,6 +79,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/locale.rst b/reference/forms/types/locale.rst
index 6a5378c87dc..4d5dd32d621 100644
--- a/reference/forms/types/locale.rst
+++ b/reference/forms/types/locale.rst
@@ -36,6 +36,8 @@ you should just use the ``choice`` type directly.
| | - `error_mapping`_ |
| | - `required`_ |
| | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `mapped`_ |
@@ -79,6 +81,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/money.rst b/reference/forms/types/money.rst
index 06dfdb7c2c1..5e143c93570 100644
--- a/reference/forms/types/money.rst
+++ b/reference/forms/types/money.rst
@@ -21,6 +21,8 @@ how the input and output of the data is handled.
+-------------+---------------------------------------------------------------------+
| Inherited | - `required`_ |
| options | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -89,6 +91,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/number.rst b/reference/forms/types/number.rst
index dc5a113db10..74d35a4f61a 100644
--- a/reference/forms/types/number.rst
+++ b/reference/forms/types/number.rst
@@ -17,6 +17,8 @@ you want to use for your number.
+-------------+----------------------------------------------------------------------+
| Inherited | - `required`_ |
| options | - `label`_ |
+| | - `label_attr`_ |
+| | - `data`_ |
| | - `read_only`_ |
| | - `disabled`_ |
| | - `error_bubbling`_ |
@@ -75,6 +77,10 @@ These options inherit from the :doc:`form ` type:
.. include:: /reference/forms/types/options/label.rst.inc
+.. include:: /reference/forms/types/options/label_attr.rst.inc
+
+.. include:: /reference/forms/types/options/data.rst.inc
+
.. include:: /reference/forms/types/options/read_only.rst.inc
.. include:: /reference/forms/types/options/disabled.rst.inc
diff --git a/reference/forms/types/options/_error_bubbling_hint.rst b/reference/forms/types/options/_error_bubbling_hint.rst
new file mode 100644
index 00000000000..743da6f8d0e
--- /dev/null
+++ b/reference/forms/types/options/_error_bubbling_hint.rst
@@ -0,0 +1,7 @@
+.. tip::
+
+ By default the ``error_bubbling`` option is enabled for the
+ :doc:`collection Field Type `,
+ which passes the errors to the parent form. If you want to attach
+ the errors to the locations where they actually occur you have to
+ set ``error_bubbling`` to ``false``.
diff --git a/reference/forms/types/options/cascade_validation.rst.inc b/reference/forms/types/options/cascade_validation.rst.inc
index 60d1bd50593..f110e9087b2 100644
--- a/reference/forms/types/options/cascade_validation.rst.inc
+++ b/reference/forms/types/options/cascade_validation.rst.inc
@@ -11,6 +11,5 @@ the data from ``CategoryType`` to also be validated.
Instead of using this option, you can also use the ``Valid`` constraint in
your model to force validation on a child object stored on a property.
-
-
+.. include:: /reference/forms/types/options/_error_bubbling_hint.rst.inc
diff --git a/reference/forms/types/options/compound.rst.inc b/reference/forms/types/options/compound.rst.inc
new file mode 100644
index 00000000000..d8b07f65315
--- /dev/null
+++ b/reference/forms/types/options/compound.rst.inc
@@ -0,0 +1,8 @@
+compound
+~~~~~~~~
+
+**type**: ``boolean``
+
+This option specifies if a form is compound. This is independent of whether the
+form actually has children. A form can be compound but not have any children
+at all (e.g. an empty collection form).
diff --git a/reference/forms/types/options/data.rst.inc b/reference/forms/types/options/data.rst.inc
index 8b4b32c44be..ee92e82a2d3 100644
--- a/reference/forms/types/options/data.rst.inc
+++ b/reference/forms/types/options/data.rst.inc
@@ -12,4 +12,8 @@ an individual field, you can set it in the data option::
'data' => 'abcdef',
));
+.. note::
+ The default values for form fields are taken directly from the
+ underlying data structure (e.g. an entity or an array).
+ The ``data`` option overrides this default value.
diff --git a/reference/forms/types/options/label_attr.rst.inc b/reference/forms/types/options/label_attr.rst.inc
new file mode 100644
index 00000000000..de834c4ae1b
--- /dev/null
+++ b/reference/forms/types/options/label_attr.rst.inc
@@ -0,0 +1,22 @@
+label_attr
+~~~~~
+
+**type**: ``array`` **default**: ``array()``
+
+Sets the html attributes for the ``