@@ -167,21 +167,6 @@ interface forces the class to implement the five following methods:
167
167
168
168
For more details on each of these, see :class: `Symfony\\ Component\\ Security\\ Core\\ User\\ UserInterface `.
169
169
170
- .. code-block :: php
171
-
172
- // src/Acme/UserBundle/Entity/User.php
173
-
174
- namespace Acme\UserBundle\Entity;
175
-
176
- use Symfony\Component\Security\Core\User\EquatableInterface;
177
-
178
- // ...
179
-
180
- public function isEqualTo(UserInterface $user)
181
- {
182
- return $this->id === $user->getId();
183
- }
184
-
185
170
.. note ::
186
171
187
172
The :phpclass: `Serializable ` interface and its ``serialize `` and ``unserialize ``
@@ -191,24 +176,32 @@ For more details on each of these, see :class:`Symfony\\Component\\Security\\Cor
191
176
because the :method: `Symfony\\ Bridge\\ Doctrine\\ Security\\ User\\ EntityUserProvider::refreshUser `
192
177
method reloads the user on each request by using the ``id ``.
193
178
194
- Below is an export of my ``User `` table from MySQL. For details on how to
195
- create user records and encode their password, see :ref: `book-security-encoding-user-password `.
179
+ .. tip ::
180
+
181
+ To generate missing setters and getters for your ``User `` entity, you
182
+ can use ``php app/console doctrine:generate:entities Acme/UserBundle/Entity/User ``.
183
+ For more details, see Doctrine's :ref: `book-doctrine-generating-getters-and-setters `.
184
+
185
+ Below is an export of my ``User `` table from MySQL with user `admin `
F438
186
+ and password `admin `. For details on how to create user records and
187
+ encode their password, see :ref: `book-security-encoding-user-password `.
196
188
197
189
.. code-block :: bash
198
190
199
- $ mysql> select * from user;
200
- +----+----------+----------------------------------+------------------------------------------+--------------------+-----------+
201
- | id | username | salt | password | email | is_active |
202
- +----+----------+----------------------------------+------------------------------------------+--------------------+-----------+
203
- | 1 | hhamon | 7308e59b97f6957fb42d66f894793079 | 09610f61637408828a35d7debee5b38a8350eebe | hhamon@example.com | 1 |
204
- | 2 | jsmith | ce617a6cca9126bf4036ca0c02e82dee | 8390105917f3a3d533815250ed7c64b4594d7ebf | jsmith@example.com | 1 |
205
- | 3 | maxime | cd01749bb995dc658fa56ed45458d807 | 9764731e5f7fb944de5fd8efad4949b995b72a3c | maxime@example.com | 0 |
206
- | 4 | donald | 6683c2bfd90c0426088402930cadd0f8 | 5c3bcec385f59edcc04490d1db95fdb8673bf612 | donald@example.com | 1 |
207
- +----+----------+----------------------------------+------------------------------------------+--------------------+-----------+
208
- 4 rows in set (0.00 sec)
209
-
210
- The database now contains four users with different usernames, emails and
211
- statuses. The next part will focus on how to authenticate one of these users
191
+ $ mysql> select * from acme_users;
192
+ +----+----------+------+------------------------------------------+--------------------+-----------+
193
+ | id | username | salt | password | email | is_active |
194
+ +----+----------+------+------------------------------------------+--------------------+-----------+
195
+ | 1 | admin | | d033e22ae348aeb5660fc2140aec35850c4da997 | admin@example.com | 1 |
196
+ +----+----------+------+------------------------------------------+--------------------+-----------+
197
+
198
+ .. tip::
199
+
200
+ To generate database table from your ` ` User` ` entity, you can run
201
+ ` ` php app/console doctrine:schema:update --force` ` .
202
+ For mor details, see Doctrine' s :ref:`book-doctrine-creating-the-database-tables-schema`.
203
+
204
+ The next part will focus on how to authenticate one of these users
212
205
thanks to the Doctrine entity user provider and a couple of lines of
213
206
configuration.
214
207
@@ -323,9 +316,8 @@ entity user provider to load User entity objects from the database by using
323
316
the ` ` username` ` unique field. In other words, this tells Symfony how to
324
317
fetch the user from the database before checking the password validity.
325
318
326
- This code and configuration works but it' s not enough to secure the application
327
- for ** active** users. As of now, you can still authenticate with ` ` maxime` ` . The
328
- next section explains how to forbid non active users.
319
+ This code is not enough to secure the application for ** active** users.
320
+ The next section explains how to forbid non active users.
329
321
330
322
Forbid non Active Users
331
323
-----------------------
@@ -355,10 +347,10 @@ For this example, the first three methods will return ``true`` whereas the
355
347
// src/Acme/UserBundle/Entity/User.php
356
348
namespace Acme\UserBundle\Entity;
357
349
358
- // ...
350
+ use Doctrine\ORM\Mapping as ORM;
359
351
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
360
352
361
- class User implements AdvancedUserInterface
353
+ class User implements AdvancedUserInterface, \Serializable
362
354
{
363
355
// ...
364
356
@@ -383,10 +375,8 @@ For this example, the first three methods will return ``true`` whereas the
383
375
}
384
376
}
385
377
386
- If you try to authenticate as ``maxime``, the access is now forbidden as this
387
- user does not have an enabled account. The next session will focus on how
388
- to write a custom entity provider to authenticate a user with his username
389
- or his email address.
378
+ The next session will focus on how to write a custom entity provider
379
+ to authenticate a user with his username or his email address.
390
380
391
381
Authenticating Someone with a Custom Entity Provider
392
382
----------------------------------------------------
@@ -428,8 +418,7 @@ The code below shows the implementation of the
428
418
->where(' u.username = :username OR u.email = :email' )
429
419
->setParameter(' username' , $username)
430
420
->setParameter(' email' , $username)
431
- ->getQuery()
432
- ;
421
+ ->getQuery();
433
422
434
423
try {
435
424
// The Query::getSingleResult() method throws an exception
@@ -537,10 +526,11 @@ about in this section.
537
5
10000
26
authenticated at all.
538
527
539
528
In this example, the ` ` AcmeUserBundle:User` ` entity class defines a
540
- many-to-many relationship with a ` ` AcmeUserBundle:Group` ` entity class. A user
541
- can be related to several groups and a group can be composed of one or
542
- more users. As a group is also a role, the previous ``getRoles ()` ` method now
543
- returns the list of related groups::
529
+ many-to-many relationship with a ` ` AcmeUserBundle:Role` ` entity class.
530
+ A user can be related to several roles and a role can be composed of
531
+ one or more users. The previous ``getRoles ()` ` method now returns
532
+ the list of related roles.
533
+ Notice that methods ``__construcotor ()` ` and ``getRoles ()` ` had changed::
544
534
545
535
// src/Acme/UserBundle/Entity/User.php
546
536
namespace Acme\U serBundle\E ntity;
@@ -550,63 +540,46 @@ returns the list of related groups::
550
540
551
541
class User implements AdvancedUserInterface, \S erializable
552
542
{
543
+ //...
544
+
553
545
/**
554
- * @ORM\M anyToMany(targetEntity=" Group " , inversedBy=" users" )
546
+ * @ORM\M anyToMany(targetEntity=" Role " , inversedBy=" users" )
555
547
*
556
548
* /
557
- private $groups ;
549
+ private $roles ;
558
550
559
551
public function __construct()
560
552
{
561
- $this -> groups = new ArrayCollection ();
553
+ $this -> roles = new ArrayCollection ();
562
554
}
563
555
564
- // ...
565
-
566
556
public function getRoles()
567
557
{
568
- return $this->groups->toArray ();
569
- }
570
-
571
- /**
572
- * @see \S erializable::serialize()
573
- * /
574
17AE
- public function serialize()
575
- {
576
- return serialize(array(
577
- $this -> id,
578
- ));
558
+ return $this->roles->toArray ();
579
559
}
560
+
561
+ // ...
580
562
581
- /**
582
- * @see \S erializable::unserialize()
583
- * /
584
- public function unserialize($serialized)
585
- {
586
- list (
587
- $this -> id,
588
- ) = unserialize($serialized );
589
- }
590
563
}
591
564
592
- The ` ` AcmeUserBundle:Group ` ` entity class defines three table fields (` ` id` ` ,
565
+ The ` ` AcmeUserBundle:Role ` ` entity class defines three table fields (` ` id` ` ,
593
566
` ` name` ` and ` ` role` ` ). The unique ` ` role` ` field contains the role name used by
594
567
the Symfony security layer to secure parts of the application. The most
595
- important thing to notice is that the ` ` AcmeUserBundle:Group ` ` entity class
568
+ important thing to notice is that the ` ` AcmeUserBundle:Role ` ` entity class
596
569
extends the :class:` Symfony\\ Component\\ Security\\ Core\\ Role\\ Role` ::
597
570
598
- // src/Acme/Bundle/UserBundle/Entity/Group .php
571
+ // src/Acme/Bundle/UserBundle/Entity/Role .php
599
572
namespace Acme\U serBundle\E ntity;
600
573
601
- use Symfony\C omponent\S ecurity\C ore\R ole\R ole ;
574
+ use Symfony\C omponent\S ecurity\C ore\R ole\R oleInterface ;
602
575
use Doctrine\C ommon\C ollections\A rrayCollection;
603
576
use Doctrine\O RM\M apping as ORM;
604
577
605
578
/**
606
- * @ORM\T able(name=" acme_groups " )
579
+ * @ORM\T able(name=" acme_roles " )
607
580
* @ORM\E ntity()
608
581
* /
609
- class Group extends Role
582
+ class Role implements RoleInterface
610
583
{
611
584
/**
612
585
* @ORM\C olumn(name=" id" , type=" integer" )
@@ -626,7 +599,7 @@ extends the :class:`Symfony\\Component\\Security\\Core\\Role\\Role`::
626
599
private $role ;
627
600
628
601
/**
629
- * @ORM\M anyToMany(targetEntity=" User" , mappedBy=" groups " )
602
+ * @ORM\M anyToMany(targetEntity=" User" , mappedBy=" roles " )
630
603
* /
631
604
private $users ;
632
605
@@ -635,21 +608,27 @@ extends the :class:`Symfony\\Component\\Security\\Core\\Role\\Role`::
635
608
$this -> users = new ArrayCollection ();
636
609
}
637
610
638
- // ... getters and setters for each property
639
-
640
611
/**
641
612
* @see RoleInterface
642
613
* /
643
614
public function getRole()
644
615
{
645
616
return $this -> role;
646
617
}
618
+
619
+ // ... getters and setters for each property
647
620
}
648
621
649
- To improve performances and avoid lazy loading of groups when retrieving a user
650
- from the custom entity provider, the best solution is to join the groups
622
+ .. tip::
623
+
624
+ To generate missing setters and getters for your ` ` Role` ` entity, you
625
+ can use ` ` php app/console doctrine:generate:entities Acme/UserBundle/Entity/User` ` .
626
+ For more details, see Doctrine' s :ref:`book-doctrine-generating-getters-and-setters`.
627
+
628
+ To improve performances and avoid lazy loading of roles when retrieving a user
629
+ from the custom entity provider, the best solution is to join the roles
651
630
relationship in the ``UserRepository::loadUserByUsername()`` method. This will
652
- fetch the user and his associated roles / groups with a single query::
631
+ fetch the user and his associated roles with a single query::
653
632
654
633
// src/Acme/UserBundle/Entity/UserRepository.php
655
634
namespace Acme\UserBundle\Entity;
@@ -662,8 +641,8 @@ fetch the user and his associated roles / groups with a single query::
662
641
{
663
642
$q = $this
664
643
->createQueryBuilder(' u' )
665
- -> select(' u, g ' )
666
- -> leftJoin(' u.groups ' , ' g ' )
644
+ ->select(' u, r ' )
645
+ ->leftJoin(' u.roles ' , ' r ' )
667
646
->where(' u.username = :username OR u.email = :email' )
668
647
->setParameter(' username' , $username)
669
648
->setParameter(' email' , $username)
@@ -675,6 +654,29 @@ fetch the user and his associated roles / groups with a single query::
675
654
// ...
676
655
}
677
656
678
- The ``QueryBuilder::leftJoin ()` ` method joins and fetches related groups from
657
+ The ``QueryBuilder::leftJoin()`` method joins and fetches related roles from
679
658
the ``AcmeUserBundle:User`` model class when a user is retrieved with his email
680
659
address or username.
660
+
661
+ To re-generate all database tables, you can run ``php app/console doctrine:schema:update --force``.
662
+ This will also create additional table ``user_role`` what holds
663
+ relations between users and roles.
664
+ For mor details, see Doctrine' s :ref:` book-doctrine-creating-the-database-tables-schema` .
665
+
666
+ Below is an export of my ` ` Roles` ` and ` ` user_role` ` tables from MySQL:
667
+
668
+ .. code-block:: bash
669
+
670
+ $ mysql> select * from acme_users;
671
+ +----+-------+------------+
672
+ | id | name | role |
673
+ +----+-------+------------+
674
+ | 1 | admin | ROLE_ADMIN |
675
+ +----+-------+------------+
676
+
677
+ mysql> select * from user_role;
678
+ +---------+---------+
679
+ | user_id | role_id |
680
+ +---------+---------+
681
+ | 1 | 1 |
682
+ +---------+---------+
0 commit comments