5

It said on the EasyAdminBundle doc

For example, the index() action calls to a method named createIndexQueryBuilder() to create the Doctrine query builder used to get the results displayed on the index listing. If you want to customize that listing, it’s better to override the createIndexQueryBuilder() method instead of the entire index() method.

So let's imagine I have in my user entity the field isDeleted set to true when the user is deleted. In the index page, I want to display only user with isDeleted = false. How to override the createIndexQueryBuilder() for this purpose?

Here is the method createIndexQueryBuilder


public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
    return $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
}

I tried to override it like this but it didn't work


public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
    $response = $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
    $response->where('isDeleted', true);
    return $response;
}
Nel
  • 454
  • 5
  • 14

7 Answers7

11

All you need is add entity. in where clause :)

public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
    parent::createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);

    $response = $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
    $response->where('entity.isDeleted = 1');

    return $response;
}
Scorpioniz
  • 1,421
  • 3
  • 16
  • 36
  • I would say the parent call is not necessary. – Kaizoku Gambare Sep 15 '20 at 10:06
  • 1
    Thanks, as @KaizokuGambare comment says the parent call did not change anything for me. However the search would crash when using `$response->where` setting this to `$response->andWhere` got everything to work properly. – Dennis de Best Dec 07 '20 at 15:26
9

This worked for me with EasyAdmin 4.x

use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository;

class CampaignCrudController extends AbstractCrudController
{
    public function __construct(EntityRepository $entityRepository)
    {
        $this->entityRepository = $entityRepository;
    }

    public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): ORMQueryBuilder
    {
        $response = $this->entityRepository->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
        $response->andWhere('entity.user = :user')->setParameter('user', $this->getUser());

        return $response;
    }
ghaliano
  • 396
  • 6
  • 10
2

EasyAdmin4 solution

Note: The keyword (alias) entity is important

use Doctrine\ORM\QueryBuilder;

class ArticleCrudController extends AbstractCrudController
{
     ...

     public function configureFields(string $pageName): iterable
     {
          return [
                ...
                AssociationField::new('author')->setQueryBuilder(
                fn (QueryBuilder $queryBuilder) => $queryBuilder
                   ->leftJoin('entity.article', 'a')
                   ->andWhere('entity.isActive = 1')
                   ->andWhere('a.author is NULL')
                  ),
                ...
            ]
      }

      ...
}
Theva
  • 873
  • 8
  • 15
  • This answers a different question I had about EA4. Did not know that you could do that for AssociationField - nice. Thanks. – Aries Jun 16 '22 at 20:34
1

Here is an exemple about how to replace the DQL FILTER in EasyAdmin v3.x

EasyAdmin v2.x DQL FILTER :

easy_admin:
  entities:
    User:
      class: App\Entity\User
      list:
        dql_filter: "entity.roles NOT LIKE '%%ROLE_SUPER_ADMIN%%'"

EasyAdmin v3.x inside UserCrudController :

public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
    $response = $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
    $response->where("entity.roles NOT LIKE '%%ROLE_SUPER_ADMIN%%'");

    return $response;
}
Kaizoku Gambare
  • 3,143
  • 3
  • 29
  • 41
  • I have this exact requirement where I only want to show a specific user role in an EasyAdminCrud. Is THIS the only way of doing it? A LIKE query? – Aries Jun 16 '22 at 20:32
1

For everyone getting following QueryException using the accepted answer and finding this through search:

QueryException 
Too many parameters: the query defines 1 parameters and you bound 3

EasyAdmin v3.x inside your EntityCrudController:

  • use ->andWhere() function
  • use entity. as prefix (really, use "entity", do not replace by your entity-name)
public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
    $response = $this->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
    $response->andWhere('entity.isDeleted = 1');   
    return $response;
}
Raphibauer
  • 19
  • 2
  • The problem is that when we are searching with the filter input, we have the following error : `Too few parameters: the query defines 4 parameters but you only bound 2`. Without the **createIndexQueryBuilder** customization, we haven't :/ – eronn Jun 22 '21 at 13:20
0

With EasyAdmin 4, i've found this solution, because I was having an error with get(EntityRepository). Since you get "parent", you get already your Entity and Repository.

$response = parent::createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);
$response->andWhere('entity.status = :status')->setParameter('status', $status);
J-Dev
  • 1
0

Here's another fictional example for EasyAdmin 3.x, adding a filter on entities loaded in an edit subfield. These entities are the target of a OneToMany relation (Showroom::gears), based on a join with the current Showroom entity's other attributes (Showroom::creator is the same Member entity as the owner of the Gear::inventory) :

class ShowroomCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return Showroom::class;
    }

    public function configureFields(string $pageName): iterable
    {
        
        return [
            IdField::new('id')->hideOnForm(),
            // relation to Member entity
            AssociationField::new('creator'),
            BooleanField::new('published')
                ->onlyOnForms()
                ->hideWhenCreating(),
            TextField::new('description'),
            AssociationField::new('gears')
                ->onlyOnForms()
                // we don't want to manage association between gears and the showroom upon showroom creation
                ->hideWhenCreating()
                ->setTemplatePath('admin/fields/inventory_gears.html.twig')
                // Only display gears that belong to the inventory of the showroom creator
                ->setQueryBuilder(
                    function (QueryBuilder $queryBuilder) {
                        // get current showroom instance
                        $currentShowroom = $this->getContext()->getEntity()->getInstance();
                        $creator = $currentShowroom->getCreator();
                        $memberId = $creator->getId();
                        // load the gears whose inventory owner is the showroom creator only
                        $queryBuilder->leftJoin('entity.inventory', 'i')
                            ->leftJoin('i.owner', 'm')
                            ->andWhere('m.id = :member_id')
                            ->setParameter('member_id', $memberId);    
                        return $queryBuilder;
                    }
                   ),
        ];
    }
Olivier Berger
  • 1,949
  • 1
  • 11
  • 7