Я разрабатываю плагин для CMS и имею непредвиденную проблему: поскольку плагин имеет многоязычную поддержку, вход может быть любого из наборов символов юникода. Плагин сохраняет данные в формате json и содержит объекты со value
свойств и lookup
. Для value
все в порядке, но свойство lookup
используется PHP для извлечения этих объектов и в определенных точках через регулярные выражения (фильтры содержимого). Проблемы:
\w
(word-char) в регулярном выражении ничего не соответствует. Есть ли способ распознавать кириллические символы как слова? Любые другие скрытые уловы? \u042D\u043A\u0441\u043F\u043E\u0440\u0442
. Безопасно ли это делать? (ограничения сервера и т. д.) И большой «дизайнерский» вопрос, который у меня возникает из предыдущих двух проблем:
Должен ли я либо разрешать пользователям с нелатинскими алфавитными языками использовать свои собственные символы для свойств lookup
либо я должен принуждать их к традиционным символам «слово», то есть символ a, b, c и т. Д. + Подчеркивание (таким образом, алфавит с другого языка )? Я бы поприветствовал технические рекомендации для руководства этим решением (а не UX).
Для не-латинских символов (например, Экспорт),
\w
(word-char) в регулярном выражении ничего не соответствует. Есть ли способ распознавать кириллические символы как слова? Любые другие скрытые уловы?
Вам просто нужно включить флаг u
:
preg_match("#^\w+$#u", $str);
Демо .
Документы PHP вводят в заблуждение:
u (
PCRE_UTF8
)
Этот модификатор включает дополнительные функции PCRE, которые несовместимы с Perl. Строка и предметные строки рассматриваются как UTF-8. Этот модификатор доступен с PHP 4.1.0 или выше в Unix и с PHP 4.2.3 на win32. UTF-8 справедливость шаблона и объекта проверяется с PHP 4.3.5. Недействительный объект приведет к тому, что функция preg_ * не будет соответствовать ничему; недопустимый шаблон вызовет ошибку уровня E_WARNING. Пять и шесть октетных последовательностей UTF-8 считаются недействительными с PHP 5.3.4 (соответственно PCRE 7.3 2007-08-28); ранее они считались действительными UTF-8.
Я говорю, что это вводит в заблуждение, потому что из вышеописанного ideone это не только позволяет PCRE_UTF8, но также PCRE_UCP ( свойства символов Unicode ), которое является поведением, которое вы хотите здесь.
Вот что говорят PCRE:
PCRE_UTF8
Этот параметр заставляет PCRE рассматривать как шаблон, так и объект как строки символов UTF-8 вместо однобайтовых строк. Тем не менее, он доступен только тогда, когда PCRE построен для поддержки UTF. Если нет, использование этой опции вызывает ошибку. Подробная информация о том, как эта опция изменяет поведение PCRE, приведена на странице pcreunicode.
PCRE_UCP
Этот параметр изменяет способ PCRE процессов\B
,\b
,\D
,\d
,\S
,\s
,\W
,\w
и некоторых классов символов POSIX. По умолчанию распознаются только символы ASCII, но если установлен параметрPCRE_UCP
, для классификации символов используются свойства Unicode. Более подробная информация приведена в разделе об общих типах символов на странице pcrepattern. Если вы установитеPCRE_UCP
, то сопоставление одного из элементов, на которые оно влияет, занимает гораздо больше времени. Этот параметр доступен только в том случае, если PCRE был скомпилирован с поддержкой свойств Unicode.
Если вы хотите сделать это очевидным с первого взгляда, флаг PCRE_UCP
будет установлен, вы можете вставить его в сам шаблон в начале, например:
preg_match("#(*UCP)^\w+$#u", $str);
Другая специальная последовательность, которая может появиться в начале шаблона, – это
(*UCP)
. Это имеет тот же эффект, что и параметрPCRE_UCP
: он вызывает последовательности, такие как\d
и\w
для использования свойств Unicode для определения типов символов вместо распознавания только символов с кодами менее 128 через таблицу поиска.
Формат данных, являющийся JSON, не латинскими символами, преобразуется в Юникоды JS, например, для вышеуказанного:
\u042D\u043A\u0441\u043F\u043E\u0440\u0442
. Безопасно ли это делать? (ограничения сервера и т. д.)
Безопасно не делать этого, пока заголовок Content-Type
определяет правильную кодировку.
Поэтому вы можете использовать что-то вроде:
header('Content-Type: application/json; charset=utf-8');
И убедитесь, что вы действительно отправляете его в UTF8.
Однако кодирование этих символов в escape-последовательностях делает все совместимым с ASCII, поэтому вы в основном устраняете проблему в целом таким образом.
Должен ли я либо разрешать пользователям с нелатинскими алфавитными языками использовать свои собственные символы для свойств
lookup
либо я должен принуждать их к традиционным символам «слово», то есть символ a, b, c и т. Д. + Подчеркивание (таким образом, алфавит с другого языка )? Я бы поприветствовал технические рекомендации для руководства этим решением (а не UX).
Технически, если весь ваш стек поддерживает Unicode (браузер, PHP, база данных и т. Д.), Я не вижу проблем с этим подходом. Просто убедитесь, что вы хорошо протестировали его и используете Unicode-совместимые типы столбцов в своей базе данных.
Будьте осторожны, PHP – это ужасный язык для поддержки строк, поэтому вам нужно убедиться, что вы используете правильные функции (избегайте использования не-Unicode, таких как strlen
т. Д., Если вы действительно не хотите подсчета байтов).
Может быть, немного больше работы, чтобы убедиться, что все работает так, как должно было, но если это то, что вы хотите поддержать, с этим нет никаких проблем.