Решение о дизайне: соответствие кириллических символов в JSON с PHP

Я разрабатываю плагин для CMS и имею непредвиденную проблему: поскольку плагин имеет многоязычную поддержку, вход может быть любого из наборов символов юникода. Плагин сохраняет данные в формате json и содержит объекты со value свойств и lookup . Для value все в порядке, но свойство lookup используется PHP для извлечения этих объектов и в определенных точках через регулярные выражения (фильтры содержимого). Проблемы:

  1. Для не-латинских символов (например, Экспорт), \w (word-char) в регулярном выражении ничего не соответствует. Есть ли способ распознавать кириллические символы как слова? Любые другие скрытые уловы?
  2. Формат данных, являющийся JSON, не латинскими символами, преобразуется в Юникоды JS, например, для вышеуказанного: \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 т. Д., Если вы действительно не хотите подсчета байтов).

Может быть, немного больше работы, чтобы убедиться, что все работает так, как должно было, но если это то, что вы хотите поддержать, с этим нет никаких проблем.