FOS包 – 如何select具有特定angular色的用户?
我正在使用FOS包,我想从数据库中检索具有给定ROLE的所有用户。
什么是最好的方法来做到这一点?
只需将其添加到UserRepository中,或者使用YourUserBundlereplace$this->_entityName
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(); }
如果你正在使用FOSUser组,你应该使用:
/** * @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(); }
那么,如果没有更好的解决scheme,我想我会去一个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();
如果你有这个要求,你的用户列表将是广泛的,你将有性能问题。 我认为你不应该把这个angular色作为一个序列化数组存储在一个字段中。 您应该创build一个实体angular色,并与users表build立多对多的关系。
正如@Tirithen所述,问题在于,由于angular色层次结构,您将无法获得具有隐式angular色的用户。 但有一种方法可以解决这个问题!
Symfony安全组件提供的服务为我们提供了特定父angular色的所有子angular色。 我们可以创build一个几乎完全相同的服务,只有它给了我们给定子angular色的所有父angular色。
创build一个新的服务:
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; } }
在yaml中定义你的服务并注入angular色层次:
# 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%"]
现在你已经准备好在你自己的服务中使用这个类。 通过调用$injectedService->getParentRoles(['ROLE_YOUR_ROLE']);
你将得到一个包含所有将导致“ROLE_YOUR_ROLE”权限的父angular色的数组。 查询具有一个或多个angular色的用户…获利!
例如,当你使用MongoDB的时候,你可以在你的用户文档库中添加一个方法:
/** * Find all users with a specific role. */ public function fetchByRoles($roles = []) { return $this->createQueryBuilder('u') ->field('roles')->in($roles) ->sort('email', 'asc'); }
我没有进入主义的ORM,但我相信它不会如此不同。
你可以在你的DQL上使用这个:
SELECT u FROM YourFavouriteBundle:User u WHERE u.roles [NOT] LIKE '%ROLE_YOUR_ROLE%'
当然,QueryBuilder更优雅:
// $role = 'ROLE_YOUR_ROLE'; $qb->where('u.roles [NOT] LIKE :role') ->setParameter('role', "%$role%");
最后我解决了它,下面是一个确切的解决scheme:
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(); }
干杯!
这个解决scheme是坏的,但它的工作原理
第1步:循环访问每个用户
第2步:检查用户是否具有“roleadmin”angular色
第3步:创build一个新的arrays与所有用户angular色pipe理员:
$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;
更好的解决办法是让DQL查询如olivierw所写