#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;
}
),
];
}