@@ -525,213 +525,6 @@ This tells Symfony to *not* query automatically for the User. Instead, when
525525someone logs in, the ``loadUserByUsername() `` method on ``UserRepository ``
526526will be called.
527527
528- Managing Roles in the Database
529- ------------------------------
530-
531- The end of this tutorial focuses on how to store and retrieve a list of roles
532- from the database. As mentioned previously, when your user is loaded, its
533- ``getRoles() `` method returns the array of security roles that should be
534- assigned to the user. You can load this data from anywhere - a hardcoded
535- list used for all users (e.g. ``array('ROLE_USER') ``), a Doctrine array
536- property called ``roles ``, or via a Doctrine relationship, as you'll learn
537- about in this section.
538-
539- .. caution ::
540-
541- In a typical setup, you should always return at least 1 role from the ``getRoles() ``
542- method. By convention, a role called ``ROLE_USER `` is usually returned.
543- If you fail to return any roles, it may appear as if your user isn't
544- authenticated at all.
545-
546- .. caution ::
547-
548- In order to work with the security configuration examples on this page
549- all roles must be prefixed with ``ROLE_ `` (see
550- the :ref: `section about roles <book-security-roles >` in the book). For
551- example, your roles will be ``ROLE_ADMIN `` or ``ROLE_USER `` instead of
552- ``ADMIN `` or ``USER ``.
553-
554- In this example, the ``AppBundle:User `` entity class defines a
555- many-to-many relationship with a ``AppBundle:Role `` entity class.
556- A user can be related to several roles and a role can be composed of
557- one or more users. The previous ``getRoles() `` method now returns
558- the list of related roles. Notice that ``__construct() `` and ``getRoles() ``
559- methods have changed::
560-
561- // src/AppBundle/Entity/User.php
562- namespace AppBundle\Entity;
563-
564- use Doctrine\Common\Collections\ArrayCollection;
565- // ...
566-
567- class User implements AdvancedUserInterface, \Serializable
568- {
569- // ...
570-
571- /**
572- * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
573- *
574- */
575- private $roles;
576-
577- public function __construct()
578- {
579- $this->roles = new ArrayCollection();
580- }
581-
582- public function getRoles()
583- {
584- return $this->roles->toArray();
585- }
586-
587- // ...
588-
589- }
590-
591- The ``AppBundle:Role `` entity class defines three fields (``id ``,
592- ``name `` and ``role ``). The unique ``role `` field contains the role name
593- (e.g. ``ROLE_ADMIN ``) used by the Symfony security layer to secure parts
594- of the application::
595-
596- // src/AppBundle/Entity/Role.php
597- namespace AppBundle\Entity;
598-
599- use Symfony\Component\Security\Core\Role\RoleInterface;
600- use Doctrine\Common\Collections\ArrayCollection;
601- use Doctrine\ORM\Mapping as ORM;
602-
603- /**
604- * @ORM\Table(name="app_role")
605- * @ORM\Entity()
606- */
607- class Role implements RoleInterface
608- {
609- /**
610- * @ORM\Column(name="id", type="integer")
611- * @ORM\Id()
612- * @ORM\GeneratedValue(strategy="AUTO")
613- */
614- private $id;
615-
616- /**
617- * @ORM\Column(name="name", type="string", length=30)
618- */
619- private $name;
620-
621- /**
622- * @ORM\Column(name="role", type="string", length=20, unique=true)
623- */
624- private $role;
625-
626- /**
627- * @ORM\ManyToMany(targetEntity="User", mappedBy="roles")
628- */
629- private $users;
630-
631- public function __construct()
632- {
633- $this->users = new ArrayCollection();
634- }
635-
636- /**
637- * @see RoleInterface
638- */
639- public function getRole()
640- {
641- return $this->role;
642- }
643-
644- // ... getters and setters for each property
645- }
646-
647- For brevity, the getter and setter methods are hidden, but you can
648- :ref: `generate them <book-doctrine-generating-getters-and-setters >`:
649-
650- .. code-block :: bash
651-
652- $ php app/console doctrine:generate:entities AppBundle/Entity/User
653-
654- Don't forget also to update your database schema:
655-
656- .. code-block :: bash
657-
658- $ php app/console doctrine:schema:update --force
659-
660- This will create the ``app_role `` table and a ``user_role `` that stores
661- the many-to-many relationship between ``app_user `` and ``app_role ``. If
662- you had one user linked to one role, your database might look something like
663- this:
664-
665- .. code-block :: bash
666-
667- $ mysql> SELECT * FROM app_role;
668- +----+-------+------------+
669- | id | name | role |
670- +----+-------+------------+
671- | 1 | admin | ROLE_ADMIN |
672- +----+-------+------------+
673-
674- $ mysql> SELECT * FROM user_role;
675- +---------+---------+
676- | user_id | role_id |
677- +---------+---------+
678- | 1 | 1 |
679- +---------+---------+
680-
681- And that's it! When the user logs in, Symfony security system will call the
682- ``User::getRoles `` method. This will return an array of ``Role `` objects
683- that Symfony will use to determine if the user should have access to certain
684- parts of the system.
685-
686- .. sidebar :: What's the purpose of the RoleInterface?
687-
688- Notice that the ``Role `` class implements
689- :class: `Symfony\\ Component\\ Security\\ Core\\ Role\\ RoleInterface `. This is
690- because Symfony's security system requires that the ``User::getRoles `` method
691- returns an array of either role strings or objects that implement this interface.
692- If ``Role `` didn't implement this interface, then ``User::getRoles ``
693- would need to iterate over all the ``Role `` objects, call ``getRole ``
694- on each, and create an array of strings to return. Both approaches are
695- valid and equivalent.
696-
697- .. _cookbook-doctrine-entity-provider-role-db-schema :
698-
699- Improving Performance with a Join
700- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
701-
702- To improve performance and avoid lazy loading of roles when retrieving a user
703- from the custom entity provider, you can use a Doctrine join to the roles
704- relationship in the ``UserRepository::loadUserByUsername() `` method. This will
705- fetch the user and their associated roles with a single query::
706-
707- // src/AppBundle/Entity/UserRepository.php
708- namespace AppBundle\Entity;
709-
710- // ...
711-
712- class UserRepository extends EntityRepository implements UserProviderInterface
713- {
714- public function loadUserByUsername($username)
715- {
716- $q = $this
717- ->createQueryBuilder('u')
718- ->select('u, r')
719- ->leftJoin('u.roles', 'r')
720- ->where('u.username = :username OR u.email = :email')
721- ->setParameter('username', $username)
722- ->setParameter('email', $username)
723- ->getQuery();
724-
725- // ...
726- }
727-
728- // ...
729- }
730-
731- The ``QueryBuilder::leftJoin() `` method joins and fetches related roles from
732- the ``AppBundle:User `` model class when a user is retrieved by their email
733- address or username.
734-
735528.. _`cookbook-security-serialize-equatable` :
736529
737530Understanding serialize and how a User is Saved in the Session
0 commit comments