With EasyAdmin 3.x a filter can built to select by user role for the list view of a User entity. For example, if the role is ROLE_REP
, a RepresentativeCrudController using the App\Entity\Person
entity may contain this:
public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
$role = serialize(["ROLE_REP"]);
$qb = $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
$qb->andWhere('entity.roles = :role');
$qb->setParameter('role', $role);
return $qb;
}
The problem arises if a differently named CrudController using the same App\Entity\Person
entity tries to filter using $role = serialize(["ROLE_SOMETHING_ELSE"]);
the query for ROLE_REP
is applied. It is also true that the URI for the list view of the differently named controller is identical to the one for ROLE_REP
.
It is not at all clear how to dig out of this hole. While similar to this SO answer, it does not apply here. Nor is it clear how to apply the related comments at EasyCorp's github issues.
Edit: If the QueryBuilder
to select based on roles is placed in a CrudController that is extended (e.g., RepresentativeCrudController extends RoleRepCrudController
) then the initial display for Representative is correct Using the menu to list a second role provides a correct list. However, using the menu to return to the previous crud controller uses the same uri, thus changing the list so that original Representative selection is gone.
Here's the dashboard:
class DashboardController extends AbstractDashboardController
{
/**
* @Route("/admin", name="admin")
*/
public function index(): Response
{
$routeBuilder = $this->get(CrudUrlGenerator::class)->build();
return $this->redirect($routeBuilder->setController(RepresentativeCrudController::class)->generateUrl());
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToCrud('Representative', 'fa fa-home', Person::class);
yield MenuItem::linkToCrud('Volunteer', 'fa fa-home', Person::class);
yield MenuItem::linktoRoute('Dashboard', 'fas fa-folder-open', 'dashboard');
yield MenuItem::linktoRoute('Home', 'fas fa-folder-open', 'home_page');
}
...
}
and a CrudController:
class RepresentativeCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Person::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud
->setPageTitle(Crud::PAGE_INDEX, 'Representative')
->setHelp('index', 'Replacing removes current staff.')
->setSearchFields(['id', 'roles', 'email', 'fname', 'sname', 'confirmationToken', 'replacementStatus']);
}
public function configureActions(Actions $actions): Actions
{
return $actions
->disable('new', 'edit', 'delete');
}
public function configureFields(string $pageName): iterable
{
...
}
}
public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
$role = serialize(["ROLE_REP"]);
$qb = $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
$qb->andWhere('entity.roles = :role');
$qb->setParameter('role', $role);
return $qb;
}
...}
It is actually relatively simple. For each role, create a crud controller with a querybuilder
to filter based on roles. In the dashboard, configureMenuItems()
, explicitly add the controller. For example:
yield MenuItem::linkToCrud('Representative', 'fa fa-home', Person::class)
->setController(RepresentativeCrudController::class);
Now the Person entity is filtered by role.