tutorial instalar español symfony

instalar - symfony español



Paquete de FOS: ¿cómo seleccionar usuarios con un rol específico? (7)

Bueno, si no hay una mejor solución, creo que iré a una consulta DQL:

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

Estoy usando el paquete de FOS y quiero recuperar todos los usuarios con un ROL dado de la base de datos.

¿Cuál es la mejor manera de hacer esto?


Como afirma @Tirithen, el problema es que no obtendrá los usuarios que tienen un rol implícito debido a la jerarquía de roles. ¡Pero hay una manera de evitarlo!

El componente de seguridad de Symfony proporciona un servicio que nos proporciona todas las funciones secundarias para roles principales específicos. Podemos crear un servicio que haga casi lo mismo, solo que nos da todos los roles principales para un rol secundario dado.

Crea un nuevo servicio:

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 strings * * @param array $roleNames An array of string role names * * @return array An array of string 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; } }

Defina su servicio, por ejemplo, en yaml e inserte la jerarquía de funciones en él:

# 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%"]

Ahora está listo para usar la clase en su propio servicio. Llamando a $injectedService->getParentRoles([''ROLE_YOUR_ROLE'']); obtendrá una matriz que contiene todos los roles principales que darán lugar al permiso "ROLE_YOUR_ROLE". Consulta de usuarios que tienen uno o más de esos roles ... ¡aprovecha!

Por ejemplo, cuando usa MongoDB puede agregar un método a su repositorio de documentos de usuario:

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

No estoy en Doctrine ORM, pero estoy seguro de que no será tan diferente.


ESTA SOLUCIÓN ES MALA pero funciona

Paso 1: Pasa por cada usuario
Paso 2: comprueba si el usuario tiene el rol "roleadmin"
Paso 3: crea una nueva matriz con todos los usuarios, el administrador del rol:

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

La mejor solución es hacer consultas DQL como escribió Olivierw


Finalmente lo resolví, siguiendo es una solución exacta:

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(); }

¡Aclamaciones!


Puedes usar solo esto en tu DQL:

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

Por supuesto, con QueryBuilder es más elegante:

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


Si tiene este requisito y su lista de usuarios será extensa, tendrá problemas de rendimiento. Creo que no debería almacenar los roles en un campo como una matriz serializada. Debe crear una entidad de roles y una relación muchos a muchos con la tabla de usuarios.


Simplemente agregue esto en su UserRepository o reemplace $this->_entityName por YourUserBundle:User :

/** * @param string $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 está utilizando FOSUser Groups, debería usar:

/** * @param string $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(); }