Ответ 1
Регулярное выражение [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
Обратите внимание, что это регулярное выражение применяется byte-by-byte без учета для кодирования. Именно поэтому он также допускает множество странных имен Unicode.
Но регулярное выражение ограничивает только эти "прямые" использования имен. Благодаря различным динамическим функциям 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
Методы
Имена методов произвольны и могут обрабатываться __call
magic:
class Test {
public function __call($method, $args) {
echo "Called method \"$method\"";
}
}
$obj = new Test;
$obj->{''}(); // Called method ""
$obj->{"\0"}(); // Called method "\0"
Классы
Произвольные имена классов могут быть созданы с помощью 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!
Функции
Я не знаю, как создать произвольные имена функций из userland, но есть еще некоторые случаи, когда внутренний код создает "странные" имена:
var_dump(create_function('',''));
// string(9) "\0lambda_1"