EasyAdminBundle icon indicating copy to clipboard operation
EasyAdminBundle copied to clipboard

Search not joining all related tables when association properties have same name

Open siggidiel opened this issue 2 years ago • 0 comments

Hey guys. Unfortunately, this fix hasn't solved another special case which I would like to introduce:

I have the following search fields in my GiroAccountCrudController:

->setSearchFields([
    'foreignId',
    'details.foreignId',
    'cards.foreignId',
    'cards.details.foreignId',
])

and I have the following Entity relation structure:

GiroAccount
    - int $foreignId
    - Collection<GiroAccountDetail> (oneToMany) $details
        - string $foreignId
    - Collection<GiroAccountCard> (oneToMany) $cards
        - string $foreignId
        - Collection<GiroAccountCardDetail> (oneToMany) $details
            - string $foreignId
            

As you can see, both entities GiroAccountCard and GiroAccount have an association field named $details. Both fields refer to completely different entities. This leads to the following QueryBuilder DQL:

SELECT 
    entity 
FROM 
    App\Entity\GiroAccount entity 
    LEFT JOIN entity.details details 
    LEFT JOIN entity.cards cards 
WHERE 
    LOWER(details.foreignId) LIKE :query_for_text_1 
    OR LOWER(cards.foreignId) LIKE :query_for_text_1 
    OR LOWER(details.foreignId) LIKE :query_for_text_1

You can see that there is no join on entity.cards.details entity and you can see that in the WHERE clause there is a redundant condition to details.foreignId.

When debugging, it seems like the method \EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository::getSearchablePropertiesConfig is ignoring JOINS when the condition !\in_array($associatedEntityName, $entitiesAlreadyJoined, true) is false because there is already a JOIN on the alias "details".

I hope it's somehow understandable and reproducable. A quick fix in my application is to provide unique property names. After renaming my property GiroAccountCard::$details to GiroAccountCard::$cardDetails, everything seems to work now. Even the DQL is correct:

SELECT 
    entity 
FROM 
    App\Entity\GiroAccount entity 
    LEFT JOIN entity.details details 
    LEFT JOIN entity.cards cards 
    LEFT JOIN cards.cardDetails cardDetails 
WHERE 
    LOWER(details.foreignId) LIKE :query_for_text_1 
    OR LOWER(cards.foreignId) LIKE :query_for_text_1 
    OR LOWER(cardDetails.foreignId) LIKE :query_for_text_1

siggidiel avatar Oct 25 '23 19:10 siggidiel