Skip to content

Doctrine ODM SearchFilter with embedded documents #6376

Open
@yunicot

Description

@yunicot

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions