37

以下代码运行良好:

${0x0} = 'test';
echo ${0x0}; // prints "test"

但我不知道为什么。0x0(或者0,正如非十六进制的人所说的那样)是一个随机容器,它可以是任何数字,但 php 变量不能以数字开头。这里使用的有什么特别之处{ },它们的局限性是什么?

4

5 回答 5

31

首先,0x0它只是一个0十六进制表示的正则,在'0'与变量变量语法一起使用时被转换为字符串:

var_dump(0x0===0); // prints "bool(true)"

${0x0} = 'test';
echo ${0x0}; // prints "test"
echo ${'0'}; // prints "test" as well
var_dump(get_defined_vars()); // contains ["0"] => string(4) "test"

你是对的,你说它不是一个有效的变量名

变量名称遵循与 PHP 中其他标签相同的规则。有效的变量名称以字母或下划线开头,后跟任意数量的字母、数字或下划线。作为正则表达式,它会这样表达:'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

这就是$0foo = 'Test';触发解析错误的原因。

对变量变量语法的一些快速测试表明,事实上,PHP 似乎并不真正关心变量名称,因为它们是字符串:

${'123 abc xyz    '} = 'Test';
echo ${'123 abc xyz    '}; // Test
echo ${'123 abc xyz   '}; // PHP Notice:  Undefined variable: 123 abc xyz    in ...
var_dump(get_defined_vars()); // ["123 abc xyz    "] => string(4) "Test"

我的猜测是上述命名限制是由源代码解析器而不是语言核心施加的。在分析 PHP 代码时,它需要这样的规则来区分变量。在内部,支持 PHP 的 Zend 引擎将变量作为哈希映射处理:

PHP 变量通常由两部分组成:标签,例如,可能是符号表中的条目,以及实际的变量容器。

因此,只要它接收到标签的有效字符串,它就会很高兴。

于 2013-03-07T12:20:11.827 回答
25

文档中:

也可以使用花括号来明确界定属性名称。当访问包含数组的属性中的值时,当属性名称由多个部分组成时,或者当属性名称包含在其他方面无效的字符时(例如,来自 json_decode() 或 SimpleXML),它们最有用。

对我来说,这意味着如果您使用${...},则对于变量名中可以使用的字符没有任何限制。然而你是否应该...

于 2013-03-07T12:01:28.420 回答
4

PHP 解析器提供了一种特殊的语法来从任何返回字符串(或可以转换为字符串)的表达式创建变量名,例如:

<?php

define('A', 'aaa');

${'    _   '} = 'blah';
${'test' . A . (2 + 6)} = 'var';

echo ${'    _   '}; // blah
echo ${'testaaa8'}; // var

${'123'} = 'blah';
echo ${100 + 23}; // blah

function returnVarName() {
    return 'myVar';
}

$myVar = 12;
echo ${returnVarName()}; // 12

此语法也可用于对象属性:

$object->{' some property    ... with strage name'};

0x0只是0文字的十六进制表示。

于 2013-03-07T12:02:48.440 回答
4

换句话说,在这种情况下,花括号内的所有内容都是字符串!

所以 s0x0确实是十六进制版本,0但这里都是字符串!这就是为什么${0x0}${0}工作,在哪里$0$0x0不会!

于 2013-03-07T12:09:04.020 回答
3

除了@Michael Robinson 所说的之外,在您的示例中,这也是有效的:

${0x0} = 'test';
$var = "0";
echo $$var; // prints "test"
于 2013-03-07T12:03:52.903 回答