Doctrine Parameter Converter injecting first collection member when no value is provided #47166
-
I tripped over a peculiar behaviour involving the SensioFrameworkExtraBundle's DoctrineParamConverter, and now also Entity Argument Resolver in #43854. In a common controller URL parameter conversion scenario, it goes like this:
The root cause of this is the piece of code I linked above: if (null === $mapping = $options->mapping) {
$keys = $request->attributes->keys();
$mapping = $keys ? array_combine($keys, $keys) : [];
}
// ...
$metadata = $objectManager->getClassMetadata($class); // Child entity metadata
foreach ($mapping as $attribute => $field) {
if (!$metadata->hasField($field) && (!$metadata->hasAssociation($field) || !$metadata->isSingleValuedAssociation($field))) {
continue;
}
$criteria[$field] = $request->attributes->get($attribute);
}
// ...
try {
return $objectManager->getRepository($class)->findOneBy($criteria);
} catch (NoResultException|ConversionException) {
return null;
}
I think the original idea is not bad - the end effect is that if there are multiple related entities, they are guaranteed to belong together, because the The problem I see is that if the This behaviour can be suppressed by providing the |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments · 4 replies
-
Only you can know this so I don’t think the default behavior will change!
There are options like Your route’s pattern is also weird because you can get the parent from the child so only one parameter would be needed? |
Beta Was this translation helpful? Give feedback.
-
Fixed by #47242 from @MatTheCat 🙏 |
Beta Was this translation helpful? Give feedback.
-
Thanks @MatTheCat FYI the real-world scenario for my weird routes: I have multi-tenant app where I prefix every URL with tenant's slug. Say there was Child entity owned by a Tenant. In my routes, I used Since Child had ManyToOne relation to Tenant, the param converter always tried to find the first child when the ID was null. I'm using the Tenant entity in the URL for access control. One of my early event subscribers (kernel.controller with 4096 priority) figures out what organisation is the user accessing, checks permission to do so for the user in session, and activates row level security in PostgreSQL so that data of other tenants does no longer show up, and then lets the lest of the request go trhough, incl. other route parameter conversion etc. I decided I have the tenant present in every tenant-aware route instead of session, where it created some complexities that were not worth the hassle. |
Beta Was this translation helpful? Give feedback.
Fixed by #47242 from @MatTheCat 🙏