FOS bundle – Comment sélectionner des utilisateurs avec un rôle spécifique?

J’utilise le bundle FOS et je souhaite récupérer tous les utilisateurs avec un ROLE donné de la firebase database.

Quelle est la meilleure façon de procéder?

Ajoutez simplement ceci dans votre UserRepository ou remplacez $this->_entityName par YourUserBundle:User :

 /** * @param ssortingng $role * * @return array */ public function findByRole($role) { $qb = $this->_em->createQueryBuilder(); $qb->select('u') ->from($this->_entityName, 'u') ->where('u.roles LIKE :roles') ->setParameter('roles', '%"'.$role.'"%'); return $qb->getQuery()->getResult(); } 

Si vous utilisez des groupes FOSUser, vous devez utiliser:

 /** * @param ssortingng $role * * @return array */ public function findByRole($role) { $qb = $this->_em->createQueryBuilder(); $qb->select('u') ->from($this->_entityName, 'u') ->leftJoin('u.groups', 'g') ->where($qb->expr()->orX( $qb->expr()->like('u.roles', ':roles'), $qb->expr()->like('g.roles', ':roles') )) ->setParameter('roles', '%"'.$role.'"%'); return $qb->getQuery()->getResult(); } 

Eh bien, s’il n’y a pas de meilleure solution, je pense que je vais passer à une requête DQL:

 $query = $this->getDocsortingne()->getEntityManager() ->createQuery( 'SELECT u FROM MyBundle:User u WHERE u.roles LIKE :role' )->setParameter('role', '%"ROLE_MY_ADMIN"%'); $users = $query->getResult(); 

Si vous avez cette exigence et que votre liste d’utilisateurs sera étendue, vous aurez des problèmes de performances. Je pense que vous ne devriez pas stocker les rôles dans un champ en tant que tableau sérialisé. Vous devez créer une entité rôles et plusieurs à plusieurs relations avec la table des utilisateurs.

Comme l’indique @Tirithen, le problème est que vous n’obtiendrez pas les utilisateurs ayant un rôle implicite en raison de la hiérarchie des rôles. Mais il y a un moyen de contourner ce problème!

Le composant de sécurité Symfony fournit un service qui nous donne tous les rôles enfants pour un rôle parent spécifique. Nous pouvons créer un service qui fait presque la même chose, mais cela nous donne tous les rôles parent pour un rôle enfant donné.

Créez un nouveau service:

 namespace Foo\BarBundle\Role; use Symfony\Component\Security\Core\Role\RoleHierarchy; use Symfony\Component\Security\Core\Role\Role; /** * ReversedRoleHierarchy defines a reversed role hierarchy. */ class ReversedRoleHierarchy extends RoleHierarchy { /** * Constructor. * * @param array $hierarchy An array defining the hierarchy */ public function __construct(array $hierarchy) { // Reverse the role hierarchy. $reversed = []; foreach ($hierarchy as $main => $roles) { foreach ($roles as $role) { $reversed[$role][] = $main; } } // Use the original algorithm to build the role map. parent::__construct($reversed); } /** * Helper function to get an array of ssortingngs * * @param array $roleNames An array of ssortingng role names * * @return array An array of ssortingng role names */ public function getParentRoles(array $roleNames) { $roles = []; foreach ($roleNames as $roleName) { $roles[] = new Role($roleName); } $results = []; foreach ($this->getReachableRoles($roles) as $parent) { $results[] = $parent->getRole(); } return $results; } } 

Définissez votre service par exemple en yaml et insérez-y la hiérarchie des rôles:

 # Provide a service that gives you all parent roles for a given role. foo.bar.reversed_role_hierarchy: class: Foo\BarBundle\Role\ReversedRoleHierarchy arguments: ["%security.role_hierarchy.roles%"] 

Vous êtes maintenant prêt à utiliser la classe dans votre propre service. En appelant $injectedService->getParentRoles(['ROLE_YOUR_ROLE']); vous obtiendrez un tableau contenant tous les rôles parents qui mèneront à l’autorisation ‘ROLE_YOUR_ROLE’. Requête pour les utilisateurs qui ont un ou plusieurs de ces rôles … profit!

Par exemple, lorsque vous utilisez MongoDB, vous pouvez append une méthode à votre référentiel de documents utilisateur:

 /** * Find all users with a specific role. */ public function fetchByRoles($roles = []) { return $this->createQueryBuilder('u') ->field('roles')->in($roles) ->sort('email', 'asc'); } 

Je ne suis pas dans Docsortingne ORM mais je suis sûr que ce ne sera pas si différent.

Vous pouvez utiliser juste cela sur votre DQL:

 SELECT u FROM YourFavouriteBundle:User u WHERE u.roles [NOT] LIKE '%ROLE_YOUR_ROLE%' 

Bien sûr, avec QueryBuilder, c’est plus élégant:

 // $role = 'ROLE_YOUR_ROLE'; $qb->where('u.roles [NOT] LIKE :role') ->setParameter('role', "%$role%"); 

Finalement, je l’ai résolu, voici une solution exacte:

 public function searchUsers($formData) { $em = $this->getEntityManager(); $usersRepository = $em->getRepository('ModelBundle:User'); $qb = $usersRepository->createQueryBuilder('r'); foreach ($formData as $field => $value) { if($field == "roles"){ $qb->andWhere(":value_$field MEMBER OF r.roles")->setParameter("value_$field", $value); }else{ $qb->andWhere("r.$field = :value_$field")->setParameter("value_$field", $value); } } return $qb->getQuery()->getResult(); } 

À votre santé!

CETTE SOLUTION EST MAUVAISE mais ça marche

Étape 1: boucle à travers chaque utilisateur
Étape 2: Vérifiez si l’utilisateur a le rôle “roleadmin”
Étape 3: créez un nouveau tableau avec tous les utilisateurs du rôle admin:

 $allowedUsers = array(); $em = $this->getDocsortingne()->getEntityManager(); $entities = $em->getRepository('YourBundle:User')->findAll(); foreach($entities as $user){ foreach($user->getRoles() as $role){ if($role == "ROLE_ADMIN"){ $allowedUsers = $user; } } } return $allowedUsers; 

Une meilleure solution consiste à faire de la requête DQL comme écrit par olivierw