Ответ 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 (независимо от кодировки). Это может привести к очень сложному отслеживанию ошибок.