Как утверждает @Tirithen, проблема в том, что вы не получите пользователей с неявной ролью из-за иерархии ролей. Но есть способ обойти это!
Компонент безопасности Symfony предоставляет сервис, который предоставляет нам все дочерние роли для определенных родительских ролей. Мы можем создать службу, которая делает почти то же самое, только она дает нам все родительские роли для данной дочерней роли.
Создать новый сервис:
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 и добавьте в него иерархию ролей:
# 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». Запрос пользователей, у которых есть одна или несколько из этих ролей ... прибыль!
Например, когда вы используете MongoDB, вы можете добавить метод в свой репозиторий пользовательских документов:
/**
* Find all users with a specific role.
*/
public function fetchByRoles($roles = [])
{
return $this->createQueryBuilder('u')
->field('roles')->in($roles)
->sort('email', 'asc');
}
Я не в доктрине ORM, но я уверен, что она не будет такой особенной.