【问题标题】:Characters allowed in php array keys?php数组键中允许的字符?
【发布时间】:2012-05-28 14:12:30
【问题描述】:

我有一些 php 数组键,其中填充了很多奇怪的字符。

这是允许的吗?我不能使用的东西有什么限制吗?

【问题讨论】:

  • 约束:$a = (object) ['@km³' => 123]; error_log($a->@km³);

标签: php arrays key


【解决方案1】:

根据manual

键可以是整数或字符串。该值可以是任何 输入。

此外,还会发生以下关键转换:

  • 包含有效整数的字符串将被转换为整数类型。例如。键“8”实际上将存储在 8 之下。另一方面,“08”不会被强制转换,因为它不是有效的十进制整数。
  • 浮点数也被转换为整数,这意味着小数部分将被截断。例如。密钥 8.7 实际上将存储在 8 下。
  • Bools 也被转换为整数,即键 true 将实际存储在 1 下,而键 false 将存储在 0 下。
  • Null 将被强制转换为空字符串,即键 null 将实际存储在 "" 下。
  • 数组和对象不能用作键。这样做会导致警告:Illegal offset type。

手册again

字符串是一系列字符,其中一个字符与一个字节相同。这意味着 PHP 仅支持 256 个字符集,因此不提供原生 Unicode 支持。查看字符串类型的详细信息。

简而言之,任何字符串都可以是键。一个字符串可以包含任何二进制数据(最大 2GB)。因此,键可以是任何二进制数据(因为字符串可以是任何二进制数据)。

一些随机(有效)滥用数组键:

$w = array(chr(0) => 'null byte?', chr(rand(0, 255)) => 'random byte?');
var_dump($w);

【讨论】:

  • 澄清一下,这并不意味着您不能使用 Unicode 字符串作为数组键。事实上,any 二进制字符串工作得很好。我发现 PHP 自称缺乏 Unicode 支持很烦人,因为这不是真的。 :)
  • @deceze Unicode 属于“任何二进制数据”的类别:) (虽然我猜测手册的措辞,但我认为有必要进行澄清)。并且说“不提供本机 Unicode 支持”是真的。 PHP 核心不包括 Unicode 版本的 strlen、substr 等。虽然“不提供 Unicode 字符串的本机处理”可能更合适。
  • 当然,核心不包含任何操作 Unicode 字符串的工具。但只要您不想操作字符串,PHP 就可以很好地支持它们。实际上,默认情况下,几乎每个 PHP 安装都可以使用 MB 扩展,因此“核心支持”与否之间的区别主要是学术性的。 :)
  • @deceze 也许他们的注释应该是“不是本地的(参见 mb 扩展名)”或其他内容。不过你是对的。自 2005 年以来的任何 PHP 安装基本上都支持 Unicode,尽管我认为 PHP(带有扩展)对 Unicode 的支持仍然有点不愉快。
  • @Corbin,你为什么称它为 abuse 而不是 use
【解决方案2】:

键必须是字符串或整数。发生了一些演员表,但我认为手册很好地解释了:

键可以是整数或字符串。该值可以是任何 输入。

此外,还会发生以下关键转换:

  • 包含有效整数的字符串将被转换为整数类型。例如。密钥“8”实际上将存储在 8 下。另一方面 hand "08" 不会被强制转换,因为它不是有效的十进制整数。
  • 浮点数也被转换为整数,这意味着小数部分将被截断。例如。密钥 8.7 实际上将存储在 8.
  • Bools 也被转换为整数,即键 true 将实际存储在 1 下,而键 false 将存储在 0 下。
  • Null 将被强制转换为空字符串,即键 null 将实际存储在 "" 下。
  • 数组和对象不能用作键。这样做会导致警告:Illegal offset type。

【讨论】:

  • 资源类型现在可以转换为整数(不确定这是否是一项新功能),因此您可以通过将其转换为整数并使用它来间接使用文件句柄或 curl 句柄作为键作为关键。
【解决方案3】:

我找到这个答案是为了寻找有关我遇到的问题的更多信息。我使用的是带有 UTF-8 字符的字符串,它不能作为我拥有的数组的键。

类似

$str = "R&D - Solution";
$arr = array( "R&D - Solution" => "Research" );
echo $arr[$str];  // did not work

对我来说(不是大或聪明的)解决方案是这样做..

$str = md5("R&D - Solution");
$arr = array( md5("R&D - Solution") => "Research" );
echo $arr[$str];  // works!

【讨论】:

  • 我喜欢使用 md5() 来生成数组键。即使在这一点上不是完全必要的,它仍然感觉更安全。
  • 您使用的是旧版本的 PHP 吗?您的第一个示例在 PHP 7.1 中运行良好。
  • bin2hex 最好用作键,因为它可以保证是唯一的,这与 md5 不同,并且将始终使用 hex2bin 恢复为原始状态。可能也比md5 快得多。
  • 我的回答现在已经过时了——它是 PHP 的旧版本。加上 bin2hex 可能性能更高。尽管 md5 极有可能是唯一的,但在这种情况下,两者都不需要,因为最近的 PHP 版本中不存在该错误。
【解决方案4】:

PHP 数组键可以是整数或字符串。 PHP 字符串是字节数组,即字节序列。没有其他类型的字符串,PHP 不会对数组键字符串施加任何特殊限制。换句话说:只要是字符串,什么都可以。

【讨论】:

  • 我认为从字符串到整数键的隐式转换是一个重要的区别,因为如果键是否为整数,某些函数的操作方式会有所不同。例如,您可以使用任意字符串数字,只是为了发现数组函数稍后会从 0..n-1 重新索引它们。
  • 同意,但我认为它处于这个问题范围的边缘。 :)
【解决方案5】:

任何可以填充到 PHP 字符串中的东西都可以用作数组键。允许的字符没有限制。

$a = array();

$x = 'long string of random garage';
echo $a[$x]; // this is ok

$x = array();
echo $a[$x]; // not ok

【讨论】:

    【解决方案6】:

    如果复杂键导致“未定义索引”错误,您可能只是遇到了“修剪”问题。

    我快疯了,因为一个复杂的键正在吐出“未定义的索引”错误,我认为这可能是语法违规。导致错误的数组键是从 MySQL 数据库查询中的字段构建的,我将其转换为键并在新数组中使用。密钥看起来像这样:pl_1DNKoiJKwotCqAycickBVhTy,下面是代码的构造方式。

    //new array created from database query
    $new_array[$dbquery['fieldname']] = {some value};
    
    //key value found in field of second array
    $keyval = $array_two['fieldname'];
    
    //this produced the "undefined index" error
    echo $new_array[$keyval];
    

    事实上,$keyval$dbquery['fieldname'] 似乎是完美匹配(通过将两者都回显到浏览器进行视觉验证)。通过在第二个语句中简单地使用trim 就解决了这个谜团,如下所示:$keyval = trim($array_two['fieldname']); 一旦'修剪',php 不再抱怨。

    希望这可以帮助其他人摆脱一些令人沮丧的时刻......

    【讨论】:

      【解决方案7】:

      我个人对数组键中的异常字符没有任何问题。除了说密钥必须是标量之外,什么是合法的和不合法的都没有很好的记录。你最好的选择就是试一试看看。

      【讨论】:

      • 有点不一致,是的,但有据可查。
      【解决方案8】:

      除了所有正确的答案之外:您可以使用PSRs,它们是最好的程序员之间的某种规则,用于拥有良好和标准的编码风格。

      【讨论】:

        【解决方案9】:

        在 php 数组中不能使用键:2.3 或十进制数

        【讨论】:

          【解决方案10】:

          为了代码的和平:

          $a = (object) ['@km³' => 123];
          

          这个:

          error_log($a->@km³);
          

          产生这个错误:

          PHP Parse error: Syntax error, unexpected '@', expecting T_STRING or T_VARIABLE or '{' or '$' on line 1
          

          但这是有效的:

          error_log($a->{"@km³"});
          

          (与 {}

          【讨论】:

            【解决方案11】:

            将php页面编码成ANSI“é”就可以使用了(Cinéma不会显示为Cinéma)。 在 Notepad++ 中,只需使用菜单 Encode=>Convert ANSI and save

            【讨论】:

            • (这篇文章似乎没有为问题提供quality answer。请编辑您的答案,或者将其作为对问题的评论发布)。
            • 您能进一步解释一下吗?如果é 不存在怎么办,如果 OP 根本不使用 Notepad++ 怎么办?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-04-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多