【问题标题】:What is the PHP numeric array key limit什么是 PHP 数字数组键限制
【发布时间】:2013-07-31 00:34:07
【问题描述】:

我遇到了一个改变我身上键值的数组的问题。在下面我提供的示例中,它开始正常,但在某些时候 php 将我的字符串转换为整数并在将其作为键插入另一个数组时更改该整数。

Code
-----------------
$fund = '01';
$division = '1';
$gl_transactions[$fund] = array();
$glint = array($division=>array('gl_cash_account'=>'1800001040000000')); 
print chr(10).'1:'.chr(10); 
print_r($glint); 
$gl = $glint[$division]['gl_cash_account']; 
print chr(10).'2:'.chr(10); 
print $gl;
$gl_transactions[$fund][$gl]['description'] = 'MTS DISBURSEMENTS'; 
print chr(10).'3:'.chr(10);
print_r($gl_transactions);

Expected output 
--------------- 
1:Array([1] => Array([gl_cash_account] => 1800001040000000 ))
2:1800001040000000  
3:Array([01] => Array([1800001040000000] => Array([description] => MTS DISBURSEMENTS))) 

Actual output 
--------------- 
1:Array([1] => Array([gl_cash_account] => 1800001040000000 ))
2:1800001040000000  
3:Array([01] => Array([1721082880] => Array([description] => MTS DISBURSEMENTS))) 

注意索引从 1800001040000000 变为 1721082880

障碍物

这些大数字是总账科目编号,不能更改为较小的数字。我们的产品中有数以万计的代码,超过一百万行代码,并且无法通过每一点来找到可能存在问题的地方并重写它。这只是我们在许多地方所做的事情的一个通用示例,使用数据库中的数据构建多维数组。我可以在插入数组时简单地将变量转换为字符串来修复上述示例,但回填 1M+ 行代码不是一个可行的选择。

在我的开发机器上,我运行 php 5.3 MSSQL、Windows 和 IIS。上面的代码我没有得到这个错误,但是当我简单地将一个变量设置为一个整数然后将它作为一个键插入到一个数组中时,我确实得到了它。即 $gl = 1800001040000000; $ar[$gl] = 1; print_r($ar);现在我们不会在我们的软件中将变量转换为整数,但在第一个示例中,当 PHP 在我们的某些客户端系统上运行时构建最后一个数组时,它会在某个时刻自行转换它。

所以我的问题是:

  1. 数字数组键的确切限制是多少。
  2. 有没有办法增加这个。
  3. 在 5.2 之后的更高版本的 php 中是否已修复或增加此问题

其他说明

我们的软件适用于多种数据库、多种浏览器、window 和 linux、apache 和 IIS。我们有数百名客户在使用该软件,他们都有自己独特的设置。我们的大多数客户目前使用的是 php 5.2,由于我们的软件中使用了已弃用的功能,因此目前无法升级它们。

【问题讨论】:

  • 将数字字符串指定为数组键将触发 PHP 松散输入。在这里很容易解决:使用 64 位 PHP 二进制文件。或者在数字键前面加上另一个字符。

标签: php arrays key limit numeric


【解决方案1】:

我的猜测是您受到整数最大值的限制,因为 PHP 会自动将具有有效整数值的字符串转换为整数的数组键。 PHP 手册指出整数的限制会因系统而异,但最大的问题是 32 位系统与 64 位系统在确定上限方面。

http://php.net/manual/en/language.types.integer.php

系统上的最大整数值可以从PHP_INT_MAX常量中读取。

【讨论】:

  • @mario 我知道没有“支持”的 64 位 PHP 二进制文件,我们必须升级所有客户(他们通常不想这样做),所以不容易完全修复。预先设置索引需要审查/更改数千个程序,因此也不是一件容易的事情。
  • @ChristianMauro 不确定是否有适合您的快速解决方案,从一开始就应该是设计考虑因素,因为如果您想要它们,使用具有整数值的字符串作为键通常是不好的形式表现得像字符串。
  • 您完全正确,因为整数限制是数字数组键限制。我还对几种不同的设置进行了进一步的测试,并在 Linux Centos5 32 位设置中发现了问题。我在设置数组时尝试转换变量,即 $ar[$fund][(string)$gl] = $data;并使用双引号,即 $ar[$fund]["$gl"] = $data;两者都不能解决问题。也不是所有的数字都会触发错误,帐户 1800001040000000 会触发错误,而 1800002180000100 不会。
【解决方案2】:

我看到这里没有公认的答案,当然 OP 已经从这个开始了。我在这样的数组中丢失了我的密钥(来自Snowmed CT):

static function getNemsisProcedures() {
  $nemsis[445828009] = 'Assessment  Advanced Spinal Assessment (i.e.,  spinal clearance)';
  $nemsis[425058005] = 'Assessment  Orthostatic Vital Signs';
  // etc....
  $nemsis[89666000] = 'Cardiac  CPR, Manual';
  $nemsis[450661000124102] = 'Cardiac  Defibrillation, AED'; // TAKE NOTE
  $nemsis[426220008] = 'Cardiac  Defibrillation, Manual';
  // a lot more etc...

问题在于“心脏除颤,AED”,因为整数形式的密钥 450661000124102 大于 PHP_MAX_INT(在我的情况下为 2147483647)。

解决方案:在适用的情况下使用字符串键。

在我的例子中,我不要求键是整数,并且为了防止在 git 中的大量提交,我只是通过引用它们来提供类型为 string 的受影响的 Snowmed CT 过程值键:

static function getNemsisProcedures() {
  $nemsis[445828009] = 'Assessment  Advanced Spinal Assessment (i.e.,  spinal clearance)';
  $nemsis[425058005] = 'Assessment  Orthostatic Vital Signs';
  // etc....
  $nemsis[89666000] = 'Cardiac  CPR, Manual';

  // KEY IS GREATER THAN PHP_MAX_INT - USE QUOTES:
  $nemsis['450661000124102'] = 'Cardiac  Defibrillation, AED';

  $nemsis[426220008] = 'Cardiac  Defibrillation, Manual';
  // a lot more etc...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-31
    • 2018-03-06
    • 2012-03-18
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多