core icon indicating copy to clipboard operation
core copied to clipboard

Doctrine ODM SearchFilter with embedded documents

Open yunicot opened this issue 1 year ago • 3 comments

API Platform version(s) affected: 3.3.3

Description
I have next structure: Distribution (ApiResource, Document) -> Participant (EmbeddedDocument) -> Employee (Document) When I try to search by "participants.employee" I get the exception: ApiPlatform\Doctrine\Odm\Filter\SearchFilter::getDoctrineFieldType(): Argument #1 ($property) must be of type string, null given, called in /srv/app/vendor/api-platform/core/src/Doctrine/Odm/Filter/SearchFilter.php on line 228

How to reproduce

#[ApiResource]
#[ODM\Document]
#[ApiFilter(SearchFilter::class, properties: [
    'participants.employee' => SearchFilterInterface::STRATEGY_EXACT,
])]
class Distribution
{
    #[ODM\EmbedMany(targetDocument: Participant::class)]
    private Collection $participants;
}

#[ODM\EmbeddedDocument]
class Participant
{
    #[ODM\ReferenceOne(storeAs: ClassMetadata::REFERENCE_STORE_AS_ID, targetDocument: Employee::class)]
    private ?Employee $employee = null;
}

#[ODM\Document]
class Employee implements GetProjectInterface
{
    #[ODM\Id(strategy: 'UUID')]
    private ?string $id = null;
}

The code is partial for understanding the structure

Possible Solution
After research I found that the problem in next code point:

// vendor/api-platform/core/src/Doctrine/Odm/Filter/SearchFilter.php
$associationResourceClass = $metadata->getAssociationTargetClass($field); //contains Employee class name
$associationFieldIdentifier = $metadata->getIdentifierFieldNames()[0]; // null
$doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass);

if (!$this->hasValidValues($values, $doctrineTypeField)) {
    $this->logger->notice('Invalid filter ignored', [
        'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $property)),
    ]);

    return;
}

$metadata contains the metadata of Participant class (embedded), but embedded should not contains the id I think about two ways to solve it:

  1. Don't check the ids values, but I am not sure that it is good idea
  2. Get metadata for Employee class and after check the ids

yunicot avatar May 19 '24 22:05 yunicot

do you think you can work on a fix?

soyuka avatar May 30 '24 21:05 soyuka

Yes, I already made fix in my project and it works properly I have choosen second variant cause I think better to keep the ids validation

yunicot avatar May 30 '24 21:05 yunicot

would you be able to submit your code in a pull request ? thanks!

soyuka avatar May 31 '24 09:05 soyuka