EasyAdminBundle
EasyAdminBundle copied to clipboard
Issue with filters and bigint
Describe the bug
- My IDs are bigint (Snowflake IDs - godruoyi/php-snowflake). They are all < PHP_INT_MAX.
- I want to build index views, filtered on those bigint columns
- The value in the filter gets "rounded" even if it's an int.
- Because of the "rounding" the filters don't work
- This affects also columns that are not PK or FK
To Reproduce
- Create an entity with a column
#[ORM\Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $entityId = null;
- Make the field available in the corresponding CRUD controller (in configureFields)
- Add a filter in the corresponding CRUD controller
public function configureFilters(Filters $filters): Filters
{
return parent::configureFilters($filters)
->add('entityId');
}
- Create a record where entityId = 760934254250171757
- In the Index view, try to filter on "entity id" = "760934254250171757"
- No result should appear
- Open the filter settings, see that the value is displayed as "760934254250171776"
- Open the Doctrine tab in the Profiler and see that the query contains the "rounded" value as well
SELECT DISTINCT a0_.id AS id_0, a0_.id AS id_1 FROM audit_log a0_ WHERE (a0_.entity_id = 760934254250171776) ORDER BY a0_.id DESC LIMIT 50;
Additional context
- Example of generated URL (in which the value of the filter is properly passed)
http://localhost/public/admin?crudAction=index&crudControllerFqcn=App%5CController%5CAdmin%5CAuditLogCrudController&filters%5BentityId%5D%5Bcomparison%5D=%3D&filters%5BentityId%5D%5Bvalue%5D=760934254250171757
- The value is properly mapped in the request->query as an int
- The issue seems to be in the round method of /symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php
- Adding
if (is_int($number)) {
return $number;
}
at the beginning of the method fixes the issue and seems legit to me 5. Illustration
- Complete round() method code after suggested change
private function round(int|float $number): int|float
{
if (is_int($number)) {
return $number;
}
if (null !== $this->scale) {
// shift number to maintain the correct scale during rounding
$roundingCoef = 10 ** $this->scale;
// string representation to avoid rounding errors, similar to bcmul()
$number = (string) ($number * $roundingCoef);
$number = match ($this->roundingMode) {
\NumberFormatter::ROUND_CEILING => ceil($number),
\NumberFormatter::ROUND_FLOOR => floor($number),
\NumberFormatter::ROUND_UP => $number > 0 ? ceil($number) : floor($number),
\NumberFormatter::ROUND_DOWN => $number > 0 ? floor($number) : ceil($number),
\NumberFormatter::ROUND_HALFEVEN => round($number, 0, \PHP_ROUND_HALF_EVEN),
\NumberFormatter::ROUND_HALFUP => round($number, 0, \PHP_ROUND_HALF_UP),
\NumberFormatter::ROUND_HALFDOWN => round($number, 0, \PHP_ROUND_HALF_DOWN),
};
$number = 1 === $roundingCoef ? (int) $number : $number / $roundingCoef;
}
return $number;
}
If someone with more experience than me could review this issue, confirm my cause analysis and confirm that my solution makes sense. Then, I could create a commit and a merge request in the Symfony project
Thanks in advance for your opinion
The issue was confirmed and is being fixed here https://github.com/symfony/symfony/issues/60947