после некоторой путаницы в комментариях к
I думал, что я превращаю в вопрос. Согласно руководству по PHP, допустимое имя класса должно совпадать с [a-zA-Z_ \ x7f- \ xff] [a-zA-Z0-9_ \ x7f- \ xff] *
. Но, видимо, это не соблюдается, и не относится ни к чему другому:
define('π', pi());
var_dump(π);
class ␀ {
private $␀ = TRUE;
public function ␀()
{
return $this->␀;
}
}
$␀ = new ␀;
var_dump($␀ );
var_dump($␀->␀());
работает нормально (хотя моя IDE не может отображать ␀). Может ли какой-нибудь эрудированный человек объяснить это мне? Можем ли мы использовать любой Unicode? И если да, то с каких пор? Не то чтобы я на самом деле хотел бы, чтобы использовал что-либо, кроме A-Za-z_
, но мне любопытно.
Пояснение: Я не после Regex для проверки класса имена, и я не знаю, использует ли PHP внутренне Regex, который он предлагает в руководстве. То, что меня смутило (и, по-видимому, других парней в связанном вопросе), заключается в том, почему такие вещи, как $ ☂ = 1
, могут вообще использоваться в PHP. Предполагалось, что PHP6 будет выпуском Unicode, но PHP6 находится в состоянии перерыва. Но если нет поддержки Unicode, почему я могу это сделать тогда?
Этот вопрос начинается с упоминания имен классов в заголовке, но затем переходит к примеру, который включает экзотические имена для методов, констант, переменных и полей. На самом деле для них существуют разные правила. Давайте начнем с тех, которые не чувствительны к регистру.
Общим руководством здесь является использование только печатаемых символов ASCII. Причина в том, что эти идентификаторы нормализуются к их строчной версии, однако, это преобразование зависит от локали. Рассмотрим следующий файл PHP, закодированный в ISO-8859-1:
<?php
function func_á() { echo "worked"; }
func_Á();
Будет ли этот скрипт работать? Возможно. Это зависит от того, что вернет tolower
(
193
)
, что зависит от локали:
$ LANG=en_US.iso88591 php a.php worked $ LANG=en_US.utf8 php a.php Fatal error: Call to undefined function func_Á() in /home/glopes/a.php on line 3
Поэтому не стоит использовать не ASCII символы. Однако даже символы ASCII могут вызвать проблемы в некоторых локалях. См. это обсуждение. Вполне вероятно, что в будущем это будет исправлено путем создания независимого от локали нижнего регистра, работающего только с символами ASCII.
В заключение, если мы используем многобайтовые кодировки для этих нечувствительных к регистру идентификаторов, нас ждут проблемы. Дело не только в том, что мы не сможем воспользоваться преимуществами нечувствительности к регистру. Мы можем столкнуться с неожиданными коллизиями, поскольку все байты, составляющие многобайтовый символ, по отдельности переводятся в нижний регистр с помощью правил локали. Возможно, что два разных многобайтовых символа отображаются в одно и то же модифицированное представление потока байтов после применения правил локали для каждого из байтов.
Здесь проблема менее серьезна, поскольку эти идентификаторы чувствительны к регистру. Однако они просто интерпретируются как байтовые потоки. Это означает, что если мы используем Unicode, мы должны последовательно использовать одно и то же представление байтов; мы не можем смешивать UTF-8 и UTF-16; мы также не можем использовать BOM.
Фактически, мы должны придерживаться UTF-8. За пределами диапазона ASCII, UTF-8 использует ведущие байты от 0xc0 до 0xfd, а последующие байты находятся в диапазоне от 0x80 до 0xbf, которые находятся в допустимом диапазоне согласно руководству. Теперь допустим, что мы используем символ "Ġ" в файле с кодировкой UTF-16BE. Он будет переведен как 0x01 0x20, поэтому второй байт будет интерпретирован как пробел.
То, что многобайтовые символы читаются как однобайтовые, конечно же, не является поддержкой Unicode вообще. PHP имеет некоторую поддержку многобайтовых символов в виде ключа компиляции "--enable-zend-multibyte" (начиная с PHP 5.4, поддержка многобайтовых символов компилируется по умолчанию, но отключена; вы можете включить ее с помощью zend.multibyte=On
в php.ini). Это позволяет вам объявлять кодировку скрипта:
<?php
declare(encoding='ISO-8859-1');
// code here
?>
Он также будет обрабатывать BOM, которые используются для автоматического определения кодировки и не становятся частью вывода. Однако есть несколько недостатков:
Наконец, существует проблема отсутствия нормализации - один и тот же символ может быть представлен разными кодовыми точками Unicode (независимо от кодировки). Это может привести к некоторым очень трудно отслеживаемым ошибкам.
Имя класса может быть любой допустимой меткой, при условии, что это не зарезервированное слово PHP. Допустимое имя класса начинается с буквы или символа подчеркивания, за которым следует любое количество букв, цифр или символов подчеркивания. В качестве регулярного выражения это будет выглядеть так:
^ [a-zA-Z_ \ x80- \ xff] [a-zA-Z0-9_ \ x80- \ xff] * $
.
Ваш символ закодирован как 0x80 0x90 0xe2
или что-то вроде этого, поэтому он соответствует вашему regexp, когда не интерпретирует юникод (работает на одиночных байтах).