Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doctrine ODM SearchFilter with embedded documents #6376

Open
yunicot opened this issue May 19, 2024 · 3 comments
Open

Doctrine ODM SearchFilter with embedded documents #6376

yunicot opened this issue May 19, 2024 · 3 comments

Comments

@yunicot
Copy link

yunicot commented May 19, 2024

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
@soyuka
Copy link
Member

soyuka commented May 30, 2024

do you think you can work on a fix?

@yunicot
Copy link
Author

yunicot commented May 30, 2024

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

@soyuka
Copy link
Member

soyuka commented May 31, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants