@@ -525,213 +525,6 @@ This tells Symfony to *not* query automatically for the User. Instead, when
525
525
someone logs in, the ``loadUserByUsername() `` method on ``UserRepository ``
526
526
will be called.
527
527
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
-
735
528
.. _`cookbook-security-serialize-equatable` :
736
529
737
530
Understanding serialize and how a User is Saved in the Session
0 commit comments