Skip to content

Commit 16e0849

Browse files
committed
minor #5184 Removing a section about Roles that I think has no real use-case (weaverryan)
This PR was merged into the 2.3 branch. Discussion ---------- Removing a section about Roles that I think has no real use-case Hi guys! | Q | A | ------------- | --- | Doc fix? | no | New docs? | no | Applies to | 2.3+ | Fixed tickets | n/a This came up after a conversation with someone on Twitter that got hung up on this section (they were also new to Doctrine, so the ManyToMany relationship was a bit challenging). But it occurred to me that this section is totally unnecessary for beginners, and maybe totally unnecessary for *everyone*. Is there a real-use case for this? It was added 4 years ago at sha: 5a2824b, and it's original purpose was to talk about Roles as domain objects. If this has a real-use case, then we should clarify what it is, and move it to its own cookbook. This is a details that beginners are trying to deal with, unnecessarily. Thanks! Commits ------- 6c9ce9c Removing a section about Roles that I think has no real use-case
2 parents 2948d6e + 6c9ce9c commit 16e0849

File tree

1 file changed

+0
-207
lines changed

1 file changed

+0
-207
lines changed

cookbook/security/entity_provider.rst

Lines changed: 0 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -525,213 +525,6 @@ This tells Symfony to *not* query automatically for the User. Instead, when
525525
someone logs in, the ``loadUserByUsername()`` method on ``UserRepository``
526526
will 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

737530
Understanding serialize and how a User is Saved in the Session

0 commit comments

Comments
 (0)