@@ -561,8 +561,8 @@ In this example, the ``AcmeUserBundle:User`` entity class defines a
561561many-to-many relationship with a ``AcmeUserBundle:Role`` entity class.
562562A user can be related to several roles and a role can be composed of
563563one or more users. The previous ``getRoles()`` method now returns
564- the list of related roles.
565- Notice that methods``__construcotor()`` and ``getRoles()`` had changed::
564+ the list of related roles. Notice that ``__construct()`` and ``getRoles()``
565+ methodshave changed::
566566
567567 // src/Acme/UserBundle/Entity/User.php
568568 namespace Acme\UserBundle\Entity;
@@ -572,7 +572,7 @@ Notice that methods ``__construcotor()`` and ``getRoles()`` had changed::
572572
573573 class User implements AdvancedUserInterface, \Serializable
574574 {
575- //...
575+ // ...
576576
577577 /**
578578 * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
@@ -594,11 +594,10 @@ Notice that methods ``__construcotor()`` and ``getRoles()`` had changed::
594594
595595 }
596596
597- The ``AcmeUserBundle:Role`` entity class defines three table fields (``id``,
598- ``name`` and ``role``). The unique ``role`` field contains the role name used by
599- the Symfony security layer to secure parts of the application. The most
600- important thing to notice is that the ``AcmeUserBundle:Role`` entity class
601- extends the :class:`Symfony\\Component\\Security\\Core\\Role\\Role`::
597+ The ``AcmeUserBundle:Role`` entity class defines three fields (``id``,
598+ ``name`` and ``role``). The unique ``role`` field contains the role name
599+ (e.g. ``ROLE_ADMIN``) used by the Symfony security layer to secure parts
600+ of the application::
602601
603602 // src/Acme/Bundle/UserBundle/Entity/Role.php
604603 namespace Acme\UserBundle\Entity;
@@ -651,14 +650,63 @@ extends the :class:`Symfony\\Component\\Security\\Core\\Role\\Role`::
651650 // ... getters and setters for each property
652651 }
653652
654- .. tip::
653+ For brevity, the getter and setter methods are hidden, but you can
654+ :ref:`generate them <book-doctrine-generating-getters-and-setters>`:
655+
656+ .. code-block:: bas
657+
658+ $ php app/console doctrine:generate:entities Acme/UserBundle/Entity/User
659+
660+ Don' t forget also to update your database schema:
661+
662+ .. code-block:: bash
663+
664+ php app/console doctrine:schema:update --force
665+
666+ This will create the` ` acme_role` ` table and a` ` user_role` ` that stores
667+ the many-to-many relationship between` ` acme_user` ` and` ` acme_role` ` . If
668+ you had one user linked to one role, your database might look something like
669+ this:
670+
671+ .. code-block:: text
672+
673+ $ mysql> select * from acme_users;
674+ +----+-------+------------+
675+ | id| name| role|
676+ +----+-------+------------+
677+ | 1| admin| ROLE_ADMIN|
678+ +----+-------+------------+
679+
680+ mysql> select * from user_role;
681+ +---------+---------+
682+ | user_id| role_id|
683+ +---------+---------+
684+ | 1| 1|
685+ +---------+---------+
686+
687+ And that' s it! When the user logs in, Symfony security system will call the
688+ ``User::getRoles`` method. This will return an array of ``Role`` objects
689+ that Symfony will use to determine if the user should have access to certain
690+ parts of the system.
691+
692+ .. sidebar:: What' s the purpose of the RoleInterface?
655693
656- To generate missing setters and getters for your ``Role`` entity, you
657- can use ``php app/console doctrine:generate:entities Acme/UserBundle/Entity/User``.
658- For more details, see Doctrine' s :ref:` book-doctrine-generating-getters-and-setters` .
694+ Notice that the` ` Role` ` class implements
695+ :class:` Symfony\\ Component\\ Security\\ Core\\ Role\\ RoleInterface` . This is
696+ because Symfony' s security system requires that the ``User::getRoles`` method
697+ returns an array of either role strings or objects that implement this interface.
698+ If ``Role`` didn' t implement this interface,then ` ` User::getRoles` `
699+ would need to iterate over all the` ` Role` ` objects, call` ` getRole` `
700+ on each, and create an array of strings to return. Both approaches are
701+ valid and equivalent.
659702
660- To improve performances and avoid lazy loading of roles when retrieving a user
661- from the custom entity provider, the best solution is to join the roles
703+ .. _cookbook-doctrine-entity-provider-role-db-schema:
704+
705+ Improving Performance with a Join
706+ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
707+
708+ To improve performance and avoid lazy loading of roles when retrieving a user
709+ from the custom entity provider, you can use a Doctrine join to the roles
662710relationshipin the``UserRepository::loadUserByUsername ()` ` method. This will
663711fetch the user and his associated roles with a single query::
664712
@@ -689,26 +737,3 @@ fetch the user and his associated roles with a single query::
689737The``QueryBuilder::leftJoin ()` ` method joins and fetches related roles from
690738the` ` AcmeUserBundle:User` ` model class when a user is retrieved with his email
691739address or username.
692-
693- To re-generate all database tables, you can run` ` php app/console doctrine:schema:update --force` ` .
694- This will also create additional table` ` user_role` ` what holds
695- relations between users and roles.
696- For mor details, see Doctrine' s :ref:`book-doctrine-creating-the-database-tables-schema`.
697-
698- Below is an export of my ``Roles`` and ``user_role`` tables from MySQL:
699-
700- .. code-block:: bash
701-
702- $ mysql> select * from acme_users;
703- +----+-------+------------+
704- | id | name | role |
705- +----+-------+------------+
706- | 1 | admin | ROLE_ADMIN |
707- +----+-------+------------+
708-
709- mysql> select * from user_role;
710- +---------+---------+
711- | user_id | role_id |
712- +---------+---------+
713- | 1 | 1 |
714- +---------+---------+