在 PHP 中作为数组键的数字字符串

有没有可能使用像 "123"这样的数字字符串作为 PHP 数组中的键,而不将其转换为整数?

$blah = array('123' => 1);
var_dump($blah);

prints

array(1) {
[123]=>
int(1)
}

我想

array(1) {
["123"]=>
int(1)
}
96219 次浏览

您可以将键类型转换为字符串,但由于 PHP 的松散类型,最终将其转换为整数。你自己看吧:

$x=array((string)123=>'abc');
var_dump($x);
$x[123]='def';
var_dump($x);

PHP 手册:

一个键可以是一个整数或者一个字符串。如果一个键是标准的 如果是整数的表示形式,则会将其解释为(即。 "8" will be interpreted as 8, while "08" will be interpreted as "08"). 键中的浮点数被截断为整数 数组类型在 PHP 中是相同的类型,它们都可以包含整数 和字符串索引。

不,不是的:

来自 手册:

键可以是整数或字符串。如果一个键是整数的标准表示形式,它将被解释为整数(即“8”将被解释为8,而“08”将被解释为“08”)。

附录

由于下面的注释,我认为指出行为是 相似而不是 一模一样 to JavaScript 对象键会很有趣。

foo = { '10' : 'bar' };


foo['10']; // "bar"
foo[10]; // "bar"
foo[012]; // "bar"
foo['012']; // undefined!

如果需要在 php 数据结构中使用数字键,那么对象就可以工作。对象保持顺序,因此可以进行迭代。

$obj = new stdClass();
$key = '3';
$obj->$key = 'abc';

I ran into this problem on an array with both '0' and '' as keys. It meant that I couldn't check my array keys with either == or ===.

$array=array(''=>'empty', '0'=>'zero', '1'=>'one');
echo "Test 1\n";
foreach ($array as $key=>$value) {
if ($key == '') { // Error - wrongly finds '0' as well
echo "$value\n";
}
}
echo "Test 2\n";
foreach ($array as $key=>$value) {
if ($key === '0') { // Error - doesn't find '0'
echo "$value\n";
}
}

解决办法是在使用前将数组键强制转换回字符串。

echo "Test 3\n";
foreach ($array as $key=>$value) {
if ((string)$key == '') { // Cast back to string - fixes problem
echo "$value\n";
}
}
echo "Test 4\n";
foreach ($array as $key=>$value) {
if ((string)$key === '0') { // Cast back to string - fixes problem
echo "$value\n";
}
}

我的解决办法是:

$id = 55;
$array = array(
" $id" => $value
);

空格字符(prepend)是一个很好的解决方案,因为保持 int 转换:

foreach( $array as $key => $value ) {
echo $key;
}

您将看到55作为 int。

我在试图合并同时包含字符串和整数键的数组时遇到了这个问题。重要的是,整数也将作为字符串处理,因为这些是输入字段的名称(如鞋码等)。.)

当我使用 $data = array_merge($data, $extra); PHP 会重新订购’的关键。在尝试进行排序时,整数键(我尝试用 6-'6'-"6"甚至 (string)"6"作为键)从0重命名为 n... ... 如果你仔细想想,在大多数情况下,这将是理想的行为。

您可以改用 $data = $data + $extra;来解决这个问题。 直截了当,但我一开始没想到。

我在尝试对一个数组排序时遇到了这个问题,因为我需要排序键为十六进制 sha1。当生成的 sha1值没有字母时,PHP 将键转换为整数。但是我需要根据字符串的相对顺序对数组进行排序。因此我需要找到一种方法,在不改变排序顺序的情况下强制键为字符串。

看看 ASCII 图表(https://en.wikipedia.org/wiki/ASCII) ,叹号的排序和空间差不多,当然比所有的数字和字母都要低。

所以我在钥匙串末尾加了一个叹号。

for(...) {


$database[$sha.'!'] = array($sha,$name,$age);
}


ksort($database);
$row = reset($database);
$topsha = $row[0];

是的,通过对 stdClass对象进行数组强制转换是可能的:

$data =  new stdClass;
$data->{"12"} = 37;
$data = (array) $data;
var_dump( $data );

这样您就可以(直到 PHP 7.1版本) :

array(1) {
["12"]=>
int(37)
}

(更新: 我的原始答案显示了一个更复杂的方法,使用 json_decode()json_encode(),这是不必要的。)

Note the comment: It's unfortunately not possible to reference the value directly: $data['12'] will result in a notice.

更新 :
从 PHP 7.2开始,也可以使用数字字符串作为键来引用值:

var_dump( $data['12'] ); // int 32

包含有效整数的字符串将转换为整数类型。例如,密钥“8”实际上会存储在8以下。另一方面,“08”不会被强制转换,因为它不是一个有效的十进制整数。

我有一个铸造函数可以处理关联数组铸造的顺序,

$array_assoc = cast($arr,'array_assoc');


$array_sequential = cast($arr,'array_sequential');


$obj = cast($arr,'object');


$json = cast($arr,'json');






function cast($var, $type){


$orig_type = gettype($var);


if($orig_type == 'string'){


if($type == 'object'){
$temp = json_decode($var);
} else if($type == 'array'){
$temp = json_decode($var, true);
}
if(isset($temp) && json_last_error() == JSON_ERROR_NONE){
return $temp;
}
}
if(@settype($var, $type)){
return $var;
}
switch( $orig_type ) {


case 'array' :


if($type == 'array_assoc'){


$obj = new stdClass;
foreach($var as $key => $value){
$obj->{$key} = $value;
}
return (array) $obj;


} else if($type == 'array_sequential'){


return array_values($var);


} else if($type == 'json'){


return json_encode($var);
}
break;
}
return null; // or trigger_error
}

关于@david 的解决方案,请注意当你尝试访问关联数组中的字符串值时,这些数字是不起作用的。我的猜测是,它们在后台被强制转换为整数(在访问数组时) ,而且没有找到值。以整数形式访问值也不起作用。但是可以使用 array _ shift ()获取值或迭代数组。

$data = new stdClass;
$data->{"0"} = "Zero";
$data->{"1"} = "One";
$data->{"A"} = "A";
$data->{"B"} = "B";


$data = (array)$data;


var_dump($data);
/*
Note the key "0" is correctly saved as a string:
array(3) {
["0"]=>
string(4) "Zero"
["A"]=>
string(1) "A"
["B"]=>
string(1) "B"
}
*/


//Now let's access the associative array via the values
//given from var_dump() above:
var_dump($data["0"]); // NULL -> Expected string(1) "0"
var_dump($data[0]); // NULL (as expected)
var_dump($data["1"]); // NULL -> Expected string(1) "1"
var_dump($data[1]); // NULL (as expected)
var_dump($data["A"]); // string(1) "A" (as expected)
var_dump($data["B"]); // string(1) "B" (as expected)

作为解决方案,您可以使用 JSON _ FORCE _ OBJECT 选项将 PHP 数组编码为 JSON 对象。

例如:

     $a = array('foo','bar','baz');
echo "RESULT: ", json_encode($a, JSON_FORCE_OBJECT);

会导致:

     RESULT: {"0" : "foo", "1": "bar", "2" : "baz"}