Экзотические имена для методов, констант, переменных и полей - Bug или Feature? - PullRequest
35 голосов
/ 05 августа 2010

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

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

Ответы [ 4 ]

44 голосов
/ 06 августа 2010

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

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

Общее руководство здесь заключается в использовании только печатных символов 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;мы также не можем использовать спецификации.

На самом деле, мы должны придерживаться 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
?>

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

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

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

5 голосов
/ 05 августа 2010

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

2 голосов
/ 05 августа 2010

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

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

1 голос
/ 30 июня 2011

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

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

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

http://www.mail-archive.com/internals@lists.php.net/msg35720.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...