The [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
正则表达式仅适用于在某些特殊语法元素中直接使用名称的情况。一些例子:
$varName // <-- varName needs to satisfy the regex
$foo->propertyName // <-- propertyName needs to satisfy the regex
class ClassName {} // <-- ClassName needs to satisfy the regex
// and can't be a reserved keyword
请注意,此正则表达式按字节应用,不考虑编码。这就是为什么它也允许许多奇怪的 Unicode 名称 https://stackoverflow.com/questions/3417180/exotic-names-for-methods-constants-variables-and-fields-bug-or-feature.
但正则表达式限制only这些名称的“直接”使用。通过 PHP 提供的各种动态功能,几乎可以使用任意名称。
一般来说你不应做出任何假设关于 PHP 中的名称可以包含哪些字符。对于大多数部分来说,它们只是任意字符串。在 PHP 中,做“验证某个东西是否是有效的类名”之类的事情是没有意义的。
下面我将提供示例,说明如何为不同类别创建奇怪的名称。
变量
变量名可以是任意字符串:
${''} = 'foo';
echo ${''}; // foo
${"\0"} = 'bar';
echo ${"\0"}; // bar
常数
全局常量也可以是任意字符串:
define('', 'foo');
echo constant(''); // foo
define("\0", 'bar');
echo constant("\0"); // bar
据我所知,无法动态定义类常量,因此这些常量不能是任意的。创建奇怪的类常量的唯一方法似乎是通过扩展代码。
特性
属性不能是空字符串,也不能以 NUL 字节开头,但除此之外,它们是任意的:
$obj = new stdClass;
$obj->{''} = 'foo'; // Fatal error: Cannot access empty property
$obj->{"\0"} = 'foo'; // Fatal error: Cannot access property started with '\0'
$obj->{'*'} = 'foo';
echo $obj->{'*'}; // foo
Methods
方法名称是任意的,可以通过以下方式处理__call
magic:
class Test {
public function __call($method, $args) {
echo "Called method \"$method\"";
}
}
$obj = new Test;
$obj->{''}(); // Called method ""
$obj->{"\0"}(); // Called method "\0"
Classes
可以使用以下命令创建任意类名class_alias
空字符串除外:
class Test {}
class_alias('Test', '');
$className = '';
$obj = new $className; // Fatal error: Class '' not found
class_alias('Test', "\0");
$className = "\0";
$obj = new $className; // Works!
功能
我不知道从用户空间创建任意函数名称的方法,但在某些情况下内部代码仍然会产生“奇怪”的名称:
var_dump(create_function('',''));
// string(9) "\0lambda_1"