我发现PHP语言中似乎是一个可以滥用的错误。在创建变量变量时,只要您继续将其作为变量变量访问,就可以声明并处理看似非法的变量。 例如:
${'0'} = 1; //I am an illegal variable called $0
${'0'}++; //I can be accessed and manipulated.
var_dump(${'0'}); //Output: int(2)
这种行为看起来很奇怪。在SimpleXml的官方文档中简要提到了创建包含连字符的变量名称的方法,但是我的示例显示它可能会被滥用得非常糟糕。
我想知道为什么这种行为是可行的并且在解析代码时可以容忍?
答案 0 :(得分:3)
内部PHP stores variables(zend_array* symbol_table
)位于用于arrays的相同数据结构中。这允许您使用与数组键相同的约束来使用变量名。
EG。 Zend API函数zend_set_local_var
使用zend_hash_update
为符号表设置一个值,这是一个用于操作PHP数组类型的函数。
但是我们不能在PHP源代码中允许变量名中的每个字符。这是因为词法分析必须将标签与其他标记区分开来。变量为此提供了一种解决方法。
这不是一个错误,也不是滥用任何东西的方法。话虽如此,documentation声明所有标签(包括变量)必须具有正则表达式[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
,因此我不会依赖变量名中的任意字符。
${'0'} = 1;
实际上做了什么,它将值1设置为键0
处的当前范围的符号表。
您可以使用get_defined_vars
函数获取该特定表。
查看source code,我们会看到该函数只复制当前符号表并将其返回给调用者。
PHP extract
函数(src)实际检查密钥是否具有有效的标签格式(通过调用php_valid_var_name
),因此您无法使用它生成带有时髦名称的变量。
无论如何,即使可以使用变量语法(甚至是没有名称${''}
的变量)创建任何名称的变量,我认为这是不好的做法。更糟糕的是,如果图书馆期望或强制执行此操作。说它的解决方法实际上可能有点夸大其词。也许它应该被视为一个实现细节和一个未记录的功能。
答案 1 :(得分:0)
@Nadav我对此并不完全了解,但有点想法,
请记住,花括号({})字面意思是“评估花括号内的内容”,所以,你可以像你一样挤压变量创建$ {'0'} = 1 从http://php.net/manual/en/language.variables.php#73373
中提到了它PHP以数组形式存储变量,如果要检查然后使用$ GLOBALS(数组)是超全局变量,它具有脚本中存在的变量的所有引用,它将变量名称存储为键和值作为变量值,假设如下:
<?php
${'0'} = 1; // here php stores it as 0th index in the array
${'1'} = 2; // here php stores it as 1th index in the array
$b = "I am b"; // here php stores it as bth index in the array
echo "<pre>";
print_r($GLOBALS);
输出:
Array
(
[_GET] => Array
(
)
[_POST] => Array
(
)
[_COOKIE] => Array
(
)
[_FILES] => Array
(
)
[GLOBALS] => Array
*RECURSION*
[0] => 1
[1] => 2
[b] => I am b
)