【发布时间】:2016-01-03 07:46:05
【问题描述】:
我偶然发现了一个奇怪的错误/问题。
我有一个 MySQL 表,其中有一列填充了数字 (BIGINT)。这些数字对于常规的 32 位整数来说太大了,因此 PHP 会将它们转换为 32 位的字符串。这每次都会给出正确的结果。
在 64 位 PHP 上运行且不强制转换为带有 $variable = (string)$variable 的字符串时,结果有时会减 1,这样 1293203059233 之类的数字就会变成 1293203059232。这不好明显地。奇怪的是我看不到任何图案。
这不是随机发生的,MySQL 中的一行有时会递减,有时不会,而是相同的整数/行总是递减,并且总是递减 1。
是什么原因造成的?我使用json_encode 将stdClass-objects 或arrays() 转换为文本,然后通过常规HTTP 响应发送它们。
mysqli 使用准备好的语句检索行,例如:
$stmt = $sql->prepare->("SELECT BIGNUMBER FROM table WHERE SOMEID = ?");
$stmt->bind_result($bignumber);
$stmt->bind_param("i",$someid);
$stmt->execute();
$stmt->fetch();
$stmt->close();
$obj = new stdClass();
$obj->number = $bignumber;
echo json_encode($obj);
我在浏览数据库表时验证了所有整数都是正确的。
一些例子(这些是实际值):
不强制转换为字符串:
10205160559939609 -> 10205160669939608 // bad
与:
10205160559939609 -> "10205160559939609" // good
不强制转换为字符串:
10154493437278508 -> 10154493437278508 // good (?)
与:
10154493437278508 -> "10154493437278508" // good
编辑:我做了一个error_log测试pre-json_encode来测试,结果:
as Strng: (used error_log((string)$number);)
10205160559939609
as int: (used error_log($number);)
10205160559939609
这表明 php 确实得到了正确的值,并且错误发生在 php json_encode 或浏览器的 decode 方法中。
【问题讨论】:
-
@Martin
PHP_INT_MAX对于 64 位 PHP 是9223372036854775807,大于10205150669939609。 -
我的猜测是它与known issue with json_encode and large integers有关...你能用一个特定的整数和json_encode重现它吗?
-
@MattGibson 这些数字似乎也比 PHP_MAX_INT 大。至少在您链接的问题中。
-
我可以将它们转换为字符串。幸运的是,在我的情况下,结果很好。它只是让我担心,如果我在某个时候遇到一个大整数,我的一些数学会出错。给我一分钟,我会从 json_encode 测试中得到一些结果。