EasyAdminBundle: EntityFilter not working with UUIDs

Describe the bug I have entities identified by uuids, the EntityFilter is not filtering them properly and returns no result.

To Reproduce I’ve recreated a blank project and I’m able to reproduce the bug following those steps :

symfony new ea_uuids --full
cd ea_uuids
composer require easycorp/easyadmin-bundle #latest version then

Then I’m creating two simple entities identified by uuids with custom generators UuidV4, following this symfony blog post.

symfony console make:entity Book
symfony console make:entity Category

Configuring EA :

symfony console make:admin:dashboard
symfony console make:admin:crud # create Book crud (With EntityFilter on category field) 
symfony console make:admin:crud # create Category crud

Then I’m creating a category via EA crud, and a book with this category associated.

(OPTIONAL) Additional context

src/Entity/Book.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;

/**
 * @ORM\Entity(repositoryClass=BookRepository::class)
 */
class Book
{
    /**
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class=UuidV4Generator::class)
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $title;

    /**
     * @ORM\ManyToOne(targetEntity=Category::class, inversedBy="books")
     */
    private $category;

    public function getId()
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }

    public function getCategory(): ?Category
    {
        return $this->category;
    }

    public function setCategory(?Category $category): self
    {
        $this->category = $category;

        return $this;
    }
}

src/Entity/Category.php

<?php

namespace App\Entity;

use App\Repository\CategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;

/**
 * @ORM\Entity(repositoryClass=CategoryRepository::class)
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class=UuidV4Generator::class)
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity=Book::class, mappedBy="category")
     */
    private $books;

    public function __construct()
    {
        $this->books = new ArrayCollection();
    }

    public function __toString(): string
    {
        return $this->name;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|Book[]
     */
    public function getBooks(): Collection
    {
        return $this->books;
    }

    public function addBook(Book $book): self
    {
        if (!$this->books->contains($book)) {
            $this->books[] = $book;
            $book->setCategory($this);
        }

        return $this;
    }

    public function removeBook(Book $book): self
    {
        if ($this->books->removeElement($book)) {
            // set the owning side to null (unless already changed)
            if ($book->getCategory() === $this) {
                $book->setCategory(null);
            }
        }

        return $this;
    }
}

src/Controller/Admin/BookCrudController.php

<?php

namespace App\Controller\Admin;

use App\Entity\Book;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;

class BookCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return Book::class;
    }

    public function configureFields(string $pageName): iterable
    {
        return [
            TextField::new('title'),
            AssociationField::new('category'),
        ];
    }

    public function configureFilters(Filters $filters): Filters
    {
        return $filters->add(EntityFilter::new('category'));
    }
}

I’m not adding other files (DasboardController / CategoryCrudController) since their configuration is trivial.


I’ve investigated EA code and found that if I add those modifications to vendor/easycorp/easyadmin-bundle/src/Filter/EntityFilter.php

- ->setParameter($parameterName, $value);
+ ->setParameter($parameterName, $value->getId(), 'uuid');

The filtering works fine, I have no idea how to fix this “properly” in a backward compatible way with classical auto-increment strategies.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 21 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Anyone willing to investigate if we could “fix” (or “improve”) this in EasyAdmin? Maybe we can add some “isBinary()” check somewhere to transform UUIDs into strings, if needed, when performing some query. Thanks!

@javiereguiluz I will also take a look sone, as I am building a new project using symfony/uid 👍

In my project, I’ve solved the issue by creating a custom UuidEntityFilter that casts the parameter to its binary form.

@j0r1s what about adding a check to the EntityFilter so we have a generic entry point for this?

Can you try if this works in your project by modifiying the vendor code?

Ok yes this is working, but not using a Uid as object 👍🏻

Any updates? I’m currently working on a project with symfony/uid and could see the described behavior also on my side. I am trying to find a universal solution for the “isBinary()” check of the value