Подтвердить что ты не робот

Экзотические имена методов, констант, переменных и полей - ошибка или функция?

после некоторой путаницы в комментариях к

Я думал, что задаюсь вопросом. Согласно руководству 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 отсутствует, почему я могу это сделать?

4b9b3361

Ответ 1

Этот вопрос начинает упоминать имена классов в заголовке, но затем идет пример, который включает в себя экзотические имена для методов, констант, переменных и полей. Для них существуют разные правила. Начнем с нечувствительных к регистру.

Идентификаторы, нечувствительные к регистру (имена классов и функций/методов)

Общим ориентиром здесь будет использование только печатных символов ASCII. Причина в том, что эти идентификаторы нормализуются до их младшей версии, однако это преобразование зависит от локали. Рассмотрим следующий файл PHP, закодированный в ISO-8859-1:

<?php
function func_á() { echo "worked"; }
func_Á();

Будет ли работать этот script? Может быть. Это зависит от того, что 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.

В заключение, если мы используем многобайтовые кодировки для этих нечувствительных к регистру идентификаторов, мы ищем проблемы. Это не только то, что мы не можем воспользоваться нечувствительностью к делу. Мы могли бы столкнуться с неожиданными столкновениями, потому что все байты, составляющие многобайтовый символ, индивидуально преобразуются в строчные буквы с использованием правил локали. Возможно, что два разных многобайтных символа сопоставляются с одним и тем же измененным представлением байтового потока после применения правил нижнего регистра языка к каждому из байтов.

Идентификаторы с учетом регистра (переменные, константы, поля)

Проблема здесь менее серьезная, поскольку эти идентификаторы чувствительны к регистру. Однако они просто интерпретируются как bytestreams. Это означает, что если мы используем Unicode, мы должны последовательно использовать одно и то же представление байта; мы не можем смешивать UTF-8 и UTF-16; мы также не можем использовать спецификации.

На самом деле мы должны придерживаться 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). Это позволяет declare кодировать script:

<?php
declare(encoding='ISO-8859-1');
// code here
?>

Он также будет обрабатывать спецификации, которые используются для автоматического определения кодировки и не становятся частью вывода. Однако есть несколько недостатков:

  • Достижение эффективности, как памяти, так и процессора. Он хранит представление script во внутреннем многобайтовом кодировании, которое занимает больше места (и, похоже, также сохраняет в памяти исходную версию), а также тратит некоторое количество процессоров, преобразующих кодировку.
  • Поддержка нескольких байтов обычно не компилируется, поэтому она менее проверена (больше ошибок).
  • Проблемы с переносимостью между установками, в которых есть скомпилированная поддержка, и теми, которые этого не делают.
  • Относится только к этапу синтаксического анализа; не решает проблему, описанную для идентификаторов без учета регистра.

Наконец, существует проблема отсутствия нормализации - один и тот же символ может быть представлен разными кодами Unicode (независимо от кодировки). Это может привести к очень сложному отслеживанию ошибок.

Ответ 2

Ваш символ кодируется как 0x80 0x90 0xe2 или что-то в этом роде, поэтому он соответствует вашему регулярному выражению, когда не интерпретирует unicode (работает в одиночных байтах).

Ответ 3

Из официальной документации:

Имя класса может быть любой допустимой меткой, если это не зарезервированное слово PHP. Допустимое имя класса начинается с буквы или подчеркивания, за которым следует любое количество букв, цифр или подчеркивания. Как регулярное выражение, оно будет выражаться так: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$.

Ответ 4

С моей точки зрения, текущие версии PHP имеют некоторую поддержку Unicode, но это противоречиво. Как и другие, это было рассмотрено в PHP6, который был отменен (не отложен). В конце дня некоторые "экзотические" персонажи будут работать, а другие не будут; и, очевидно, как вы предположили, лучше придерживаться A-Za-z0-9_.

В то же время я слышал слухи о том, что обсуждение unicode было недавно перезапущено, предположительно с нуля, поскольку первоначальное предложение для UTF-16 в PHP6 включало массу усилий с очень небольшим возвратом.

Боковое примечание: Из того, что я прочитал, следующей основной версией PHP будет PHP 5.4, который может содержать горизонтальную интеграцию (черты), сокращение строк, встроенный HTTP-сервер и некоторые другие очень необходимая функциональность.

http://www.mail-archive.com/[email protected]/msg35720.html