EasyAdminBundle: [3.2] Using reserved names as fields causes a crash when searching

Describe the bug Somewhat related to #3073 An entity containing a reserved keyword name for doctrine will crash the search when configured in configureCrud -> setSearchFields

To Reproduce Create 2 entities with an associations Foo, containing a field called $order (valid for field name, but needs JoinColumn(name=“order_id”) which is an association to another entity called Order (let’s say it just contains the id), needs a special table name like @ORM\Table(name=“sale_order”) to function properly (in my case it’s just sale__order, so it’s not a SQL keyword.)

Create a CrudController for Foo and add

public function configureCrud(
    Crud $crud
}: Crud {
    return $crud
        ->setSearchFields(['order.id']);
}

Then try to search anything, you’ll get

[Syntax Error] line 0, col 844: Error: Expected StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression, got 'order'

This is not really because it’s a forbidden thing, but because the QueryBuilder passed to EasyCorp\Bundle\EasyAdminBundle\Factory\PaginatorFactory::create already contains a ready DQL that contains the left join for order as an alias. This issue can be resolved if the following check is made when creating aliases by the QueryBuilder used in this function

        $name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($string);
        if (defined($name)) {
            $type = constant($name);

            if ($type > 100) {
                return self::SAFE_PREFIX.$string; // fix keyword aliases
            }
        }

        return $string;

where self::SAFE_PREFIX is just a prefix added to left joins when using entities with funky field names and can be anything (ea_reserved_prefix_ or similar suggested), alternatively the prefix could be added to all joins, eliminating the need for the lookup in the first place. This is an issue which can be resolved directly in EA, as I’ve resolved it in another bundle using this trick, but it doesn’t apply to table names, only to join aliases which can be anything. I’m not quite sure how the result fetching works yet, so I can’t say if it’ll be needed to resolve the aliases back to something sensible if needed or if it’s done automatically via Doctrine.

(OPTIONAL) Additional context Symfony 4.4.20, EA 3.2.8

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 15 (10 by maintainers)

Commits related to this issue

Most upvoted comments

This is fixable if you simply assume that each join must have a prefix. So

$qb->leftJoin('entity.order', 'order')

would change into

$qb->leftJoin('entity.order', 'ea_order')

then the subsequent search on that field instead of being order.text LIKE :whatever would be ea_order.text LIKE :whatever This however could be a breaking change for people that modify these queries, though the fix is rather simple and shouldn’t take too much time. If you’ll tell me where to look (for joins mostly and where they are used later) I could probably look into creating a PR for this

I think that’s the best approach too

Well I guess escaping it is another choice, I kinda forgot about it since all I see is ORM and I kinda got used to it’s limitations. If you’d like I can let you know if your PR fixes the issue on monday morning, if tests pass and everything seems to be working there’s probably no harm in merging it if you’re planning a new release sometime soon, regardless I’ll try to get back to you with this.