EasyAdminBundle icon indicating copy to clipboard operation
EasyAdminBundle copied to clipboard

Issue with filters and bigint

Open mhbailly opened this issue 7 months ago • 1 comments

Describe the bug

  1. My IDs are bigint (Snowflake IDs - godruoyi/php-snowflake). They are all < PHP_INT_MAX.
  2. I want to build index views, filtered on those bigint columns
  3. The value in the filter gets "rounded" even if it's an int.
  4. Because of the "rounding" the filters don't work
  5. This affects also columns that are not PK or FK

To Reproduce

  1. Create an entity with a column
#[ORM\Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $entityId = null;
  1. Make the field available in the corresponding CRUD controller (in configureFields)
  2. Add a filter in the corresponding CRUD controller
public function configureFilters(Filters $filters): Filters
{
    return parent::configureFilters($filters)
        ->add('entityId');
}
  1. Create a record where entityId = 760934254250171757
  2. In the Index view, try to filter on "entity id" = "760934254250171757"
  3. No result should appear
  4. Open the filter settings, see that the value is displayed as "760934254250171776"
  5. 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

  1. 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
  1. The value is properly mapped in the request->query as an int
  2. The issue seems to be in the round method of /symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php
  3. Adding
if (is_int($number)) {
    return $number;
}

at the beginning of the method fixes the issue and seems legit to me 5. Illustration

Image

  1. 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;
    }

mhbailly avatar May 11 '25 23:05 mhbailly

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

mhbailly avatar May 11 '25 23:05 mhbailly

The issue was confirmed and is being fixed here https://github.com/symfony/symfony/issues/60947

mhbailly avatar Jul 07 '25 12:07 mhbailly