-
-
Notifications
You must be signed in to change notification settings - Fork 874
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
Integer denormalizer is numeric #2323
Integer denormalizer is numeric #2323
Conversation
Looks legit to me, but let's wait for @soyuka's review. It should target 2.3 as it's a bug fix. |
@soullivaneuh Do you still have the issue if your ItemProvider implements the DenormalizedIdentifiersAwareItemDataProviderInterface ? |
@soullivaneuh : This fixes my issue (#2116) |
The issue here is that the IMHO this use case is wrong, you can't use two different types for a given identifier. Use a custom operation if you want to fetch by Or, you can always add another |
Actually thought a bit more about this and I'm okay (if we can avoid it it's better) to use Also please check out #2126 which would be a better way of fixing this. Then again, please don't do the following:
The |
OFC, I didn't see the master target using the link from the git command line, sorry. @antograssiot Using @soyuka I agree it's not very clean, but the use case isn't clean neither. On the server resource, I need the identifier to be the id OR the name for every opertion. Using custom operations will be overkill. Do you have more details about the And, as you said on the last comment, in any case a IntegerDenormalizer should not denormalize something that does not look like an integer at all, so I think this PR is still valuable. 👍 |
understood, it looks okish to me 👍
|
Hmm... it is not an integer either. :D Maybe use this instead? http://php.net/manual/fr/function.ctype-digit.php |
cdf219d
to
82731dd
Compare
Updated the PR with |
https://api-platform.com/docs/core/identifiers/#custom-identifier-normalizer |
@@ -31,6 +31,8 @@ public function testSupportsDenormalization() | |||
$normalizer = new IntegerDenormalizer(); | |||
$this->assertTrue($normalizer->supportsDenormalization('1', 'int')); | |||
$this->assertFalse($normalizer->supportsDenormalization([], 'int')); | |||
$this->assertFalse($normalizer->supportsDenormalization('kdunglas', 'int')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so untrue :|. How can an identifier be a string but typed as an integer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stop me if I'm wrong, but I think the identified type come from PHPDoc parsing and class reflection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's linked to the property in your class. This is why it's wrong because if you typed id
as int
there are no reasons it should be a string ^^.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dirty solution, but works easier than the proper one. Maybe an issue may be open about OR conditions on identifier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the identifier should be unique, there should not be any or
imho.
@soyuka I read this documentation, but the sample show a single identifier related to an object. I just want to check on two field, one int and one string. I don't see how to achieve it this way. |
For example: <?php
namespace App\Identifier;
use ApiPlatform\Core\Exception\InvalidIdentifierException;
// assumes you indeed typed your property with
// * @IntOrString
use App\Type\IntOrString;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
final class IntOrStringNormalizer implements DenormalizerInterface
{
public function denormalize($data, $class, $format = null, array $context = [])
{
return is_numeric($data) ? (int) $data : $data;
}
public function supportsDenormalization($data, $type, $format = null)
{
// you could also check if the $data is implementing an interface or just return `true` to override default normalizers
return is_a($type, IntOrString::class, true);
}
} |
@soyuka Your solution will not work for me because I have two field. Here, you assume I have one field with the |
Where do you have 2 fields? It'll work as a workaround because the normalizer above won't denormalize your identifier.
And you can then do (even though the following is bad design :p):
Or even better now that you're sure that the string will be an integer:
|
See #2324 (comment) @soyuka At final, it the same thing, looking for two field with the same value. You just advise me to create a special type with a custom normalizer just to make string and integer working. Here, the integer normalizer does not work as excpected as it should not convert anything that does not looks like an integer. Otherwise, you may accept any value. And if nothing is able to be normalized, then I'll have the raw value. And that works for a string. ;-) |
Yes.
|
So the result is the same. Having one type allowing int or string, placed on a property that should be an int, and search for a name. Same ugly thing. 😉
Well, in that case, why do we have this test: $this->assertFalse($normalizer->supportsDenormalization([], 'int')); And why we already check value to be a string? 🤔 With this PR, I'm looking at the normalizer itself and nothing else. It's an integer normalizer, so it should convert intergers only. Or, rename it to Do you better see my point of view? |
I think @soyuka has explained it pretty well. So I'm -1 on this. |
I really don't understand here. In any case, why an integer normalizer should normalize something that does not represent an integer at all? Even if my final needs does not fit your best practice, it's still an issue, and not related. |
Concrete case:
This permit to try find a server by it's name if nothing is found with the id.
But in the current stable version, the string value will always be
0
because it's converted into string by the denormalizer.Current workaround with a decorated service: