EasyAdminBundle: QueryBuilder in TypeOptions fails

Hey all,

Currently I’m using version 1.16.2 and the functionality described in #1145 fails with Expected argument of type "Doctrine\ORM\QueryBuilder or \Closure", "string" given.

The config looks like the following:

CampaignType:
        class: Bundle\Entity\CampaignType
        controller: Bundle\Controller\EasyAdmin\SomeController
        edit:
          fields:
            - { property: 'purposes', type_options: { query_builder: "Bundle\Repository\EasyAdmin\SomeRepo::getAccessible" } }

with the method getAccessible specified in the repository

public static function getAccessible(EntityRepository $er) {
        return ...
    }

Anyone got an idea, why this fails?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 18 (1 by maintainers)

Most upvoted comments

i can confirm that this works under EasyAdmin 1.17, Sf 3.3.13:

- { property: 'types', type_options: { 'expanded':false, 'multiple': true, 'query_builder': 'YourBundle\Repository\YourRepository::pubStaticFunction', 'group_by': 'category'} }

group_by is obviously optional but i needed it in my case.

however, it was hard to find for me the right syntax for the repository function, as it’s not the same as described in Symfony doc, so i paste an example here, in case it can help :

let’s say this is about Product and Categories :

use Doctrine\ORM\EntityRepository;

public static function getListOrderByCategory(EntityRepository $er){
        return $er->getEntityManager()->createQueryBuilder('p')
                ->select('p')
                ->from('BackendBundle\Entity\Product', 'p')
                ->leftJoin('p.category', 'c')
                ->orderBy('p.name, c.name', 'ASC')
                ;
    }

or a simple orderBy:

public static function getOrderedList(EntityRepository $er){
        return $er->createQueryBuilder('p')
            ->orderBy('p.name', 'ASC')
            ;
    }

@srosset81

as a simple dropdown menu instead of the select2 field

Try to add this:

    public function createEntityFormBuilder($entity, $view)
    {
        //...
        $options['attr'] = ['data-widget' => 'select2'];
        $formBuilder->add('impacts', EntityType::class, $options);

        //...
    }

the field gets displayed at the bottom

I don’t know why. It works for me. In my case, as I re-add this field at form builder level, I only declare it without any options at config level. Full code (css_class is used for javascript needs):

admin.yml

easy_admin:                   
        Event: 
            class : FBN\GuideBundle\Entity\Event
            form:
                fields:
                    # ...                
                    - { property: 'eventPast', css_class: 'col-xs-12 eventPast' }
                    # ...           

Custom AdminController

namespace FBN\GuideBundle\Controller;

use JavierEguiluz\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use FBN\GuideBundle\Entity\EventRepository;

class AdminController extends BaseAdminController
{
    public function createEventEntityFormBuilder($entity, $view)
    {
        $formBuilder = parent::createEntityFormBuilder($entity, $view);
        // stuff...

        $id = (null !== $entity->getId()) ? $entity->getId() : 0;
        $formBuilder->add('eventPast', EntityType::class, array(
            'class' => 'FBNGuideBundle:Event',
            'query_builder' => function (EventRepository $repo) use ($id) {
                return $repo->getEventsWithCoordinatesAndExcludedId($id);
                },
            'attr' => ['data-widget' => 'select2'],
            'placeholder' => 'label.form.empty_value',
            'required' => false,
            )
        );

        return $this->getFormBuilderForNonDefaultLocale($formBuilder, $entity, $view);
    }
}

In my case, I use what is proposed by Javier in #1145. I use a custom admin controller and I introduce the query_builder in options at form builder level.

Example with my Event entity:

use JavierEguiluz\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use FBN\GuideBundle\Entity\EventRepository;

class AdminController extends BaseAdminController
{

    public function createEventEntityFormBuilder($entity, $view)
    {
        $formBuilder = parent::createEntityFormBuilder($entity, $view);

        // stuff...

        $id = (null !== $entity->getId()) ? $entity->getId() : 0;
        $formBuilder->add('eventPast', EntityType::class, array(
            'class' => 'FBNGuideBundle:Event',
            'query_builder' => function (EventRepository $repo) use ($id) {
                return $repo->getEventsWithCoordinatesAndExcludedId($id);
                },
            // ...
            )
        );

        // stuff...
    }
}

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

@javiereguiluz probably the docs needs to be updated as passing a callable string syntax is feasible for query_builder option (see source):

This is working for me now (EA=1.17, SF=3.3.10):

... type: 'entity', type_options: { query_builder: 'Full\Qualified\ClassName::pubStaticFunc' } ...