Symfony EasyAdminBundle 3 переопределяет createIndexQueryBuilder()

#php #symfony #easyadmin

#php #symfony #easyadmin

Вопрос:

В документе EasyAdminBundle сказано

Например, действие index() вызывает метод с именем createIndexQueryBuilder() для создания конструктора запросов Doctrine, используемого для получения результатов, отображаемых в списке индексов. Если вы хотите настроить этот список, лучше переопределить метод createIndexQueryBuilder() вместо всего метода index().

Итак, давайте представим, что у меня в моей пользовательской сущности для поля IsDeleted установлено значение true, когда пользователь удаляется. На индексной странице я хочу отобразить только пользователя с IsDeleted = false. Как переопределить createIndexQueryBuilder() для этой цели?

Вот метод createIndexQueryBuilder

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

Я пытался переопределить это следующим образом, но это не сработало

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

Комментарии:

1. Не вижу кода, надеюсь, у вас тоже все хорошо

2. Вы переопределили этот метод ? У меня такая же проблема. Введите свой код crud-контроллера.

Ответ №1:

Все, что вам нужно, это добавить entity. в предложение where 🙂

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

Комментарии:

1. Я бы сказал, что родительский вызов не является необходимым.

2. Спасибо, поскольку в комментарии @KaizokuGambare говорится, что родительский вызов для меня ничего не изменил. Однако при использовании $response->where настройки этого параметра на $response->andWhere , чтобы все работало должным образом, произошел сбой поиска.

Ответ №2:

У меня это сработало с EasyAdmin 4.x

 use EasyCorpBundleEasyAdminBundleOrmEntityRepository;

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

Ответ №3:

Решение EasyAdmin4

Примечание: Ключевое слово (псевдоним) entity важно

 use DoctrineORMQueryBuilder;

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')
                  ),
                ...
            ]
      }

      ...
}
  

Комментарии:

1. Это отвечает на другой вопрос, который у меня был о EA4. Не знал, что вы можете сделать это для AssociationField — nice. Спасибо.

Ответ №4:

Вот пример о том, как заменить ФИЛЬТР DQL в EasyAdmin v3.x

ФИЛЬТР EasyAdmin v2.x DQL :

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

EasyAdmin v3.x внутри пользовательского Crudcontroller :

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

Комментарии:

1. У меня есть точное требование, когда я хочу показать только определенную роль пользователя в EasyAdminCrud. Это единственный способ сделать это? ПОДОБНЫЙ запрос?

Ответ №5:

Для всех, кто получает следующее исключение QueryException, используя принятый ответ и находя это с помощью поиска:

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

EasyAdmin v3.x внутри вашего EntityCrudController:

  • используйте ->andWhere() функцию
  • используйте сущность. в качестве префикса (действительно, используйте «entity», не заменяйте своим именем объекта)
 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;
}
  

Комментарии:

1. Проблема в том, что при поиске с помощью фильтра ввода у нас появляется следующая ошибка : Too few parameters: the query defines 4 parameters but you only bound 2 . Без настройки createIndexQueryBuilder мы не :/

Ответ №6:

В EasyAdmin 4 я нашел это решение, потому что у меня была ошибка с get (EntityRepository). Поскольку вы получаете «родительский», вы уже получаете свою сущность и репозиторий.

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

Ответ №7:

Вот еще один вымышленный пример для EasyAdmin 3.x, добавляющий фильтр для объектов, загруженных в подполе редактирования. Эти объекты являются целью отношения OneToMany (Showroom::gears), основанного на объединении с другими атрибутами текущего объекта Showroom (Showroom::creator — это тот же объект-член, что и владелец 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;
                    }
                   ),
        ];
    }