Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Как лучше производить валидацию?
Форумы портала PHP.SU » » Вопросы новичков » Как лучше производить валидацию?

Страниц (1): [1]
 

1. Doox911 - 16 Июля, 2018 - 17:51:28 - перейти к сообщению
Добрый вечер. Сегодня созрел интересный вопрос. А как лучше проводить валидацию input?
Например мне необходимо чтобы остались только русские буквы и всё. Варианты:
1. Регуляркой;
2. По символьно (массив символов).
Что из этого быстрее и качественнее? Может есть ещё способ менее затратный по ресурсам?
Поделитесь опытом.
2. andrewkard - 16 Июля, 2018 - 18:06:17 - перейти к сообщению
Любым удобным для Вас способом. Нужно сделать на клиенте и на сервере. На сервере обязательно.
3. Doox911 - 17 Июля, 2018 - 07:11:14 - перейти к сообщению
andrewkard пишет:
Любым удобным для Вас способом. Нужно сделать на клиенте и на сервере. На сервере обязательно.

Это то понятно) Просто у меня друг хранит в массиве весь алфавит и разрешенные символы и входящую строку сравнивает. Регулярка требовательна к ресурсам.
4. Мелкий - 17 Июля, 2018 - 10:03:23 - перейти к сообщению
Берите профилировщик и сравните. Что быстрее, вызов скомпилированной libpcre или userspace реализация. Замечательное место где можно сильно просесть алгоритмически и не заметить - как выбирается следующий символ сравниваемой строки.
5. Doox911 - 18 Июля, 2018 - 07:34:46 - перейти к сообщению
Мелкий пишет:
Берите профилировщик и сравните. Что быстрее, вызов скомпилированной libpcre или userspace реализация. Замечательное место где можно сильно просесть алгоритмически и не заметить - как выбирается следующий символ сравниваемой строки.


Не совсем понял, в каком месте просесть можно алгоритмически?
6. Мелкий - 18 Июля, 2018 - 11:05:56 - перейти к сообщению
Для UTF8 как представителя кодировки с переменной шириной символа в принципе нет возможности взять произвольный i-тый символ строки без просмотра всех символов от 0 до i, что ожидаемо даёт замедление алгоритма.

Поясню как раз на замечательном примере из другой вашей темы: http://forum.php.su/topic.php?fo...87399#1531887399
Ваш алгоритм некорректно обрабатывает символы utf8. Но сама идея байтового обхода исходной строки при этом корректна.
Пример armancho7777777 получит замедление потому что в принципе невозможно получать offset в mb_substr без полного просмотра этого самого offset. На каждой итерации цикла.

Корректно обходить кодировки переменной длины - это взять следующий байт строки, если это не полный символ кодировки - брать следующие байты. Когда собрали символ - сверять полученный символ с заданной символьной маской. Если есть совпадение, то берём следующий байт и собираем новый символ и проверяем уже его. Если не совпали - ура, выходим, под шаблон строка не подпадает. Именно так работает PCRE и вообще конечные автоматы регулярных выражений.

В возможность корректно обойти utf8 в userspace php и обогнать элементарную регулярку - я не верю. Проверять лениво, много граблей обходить надо. А производительность libpcre в PHP ещё и весьма непросто корректно проверять из-за кеша регулярок в нескромные 4096 штук. Ёпт, а там ещё и JIT включен уже может быть. Это без вариантов, по крайней мере пока для userspace не прикрутят JIT.
7. Doox911 - 18 Июля, 2018 - 11:23:58 - перейти к сообщению
Мелкий пишет:
Для UTF8 как представителя кодировки с переменной шириной символа в принципе нет возможности взять произвольный i-тый символ строки без просмотра всех символов от 0 до i, что ожидаемо даёт замедление алгоритма.

Поясню как раз на замечательном примере из другой вашей темы: http://forum.php.su/topic.php?fo...87399#1531887399
Ваш алгоритм некорректно обрабатывает символы utf8. Но сама идея байтового обхода исходной строки при этом корректна.
Пример armancho7777777 получит замедление потому что в принципе невозможно получать offset в mb_substr без полного просмотра этого самого offset. На каждой итерации цикла.

Корректно обходить кодировки переменной длины - это взять следующий байт строки, если это не полный символ кодировки - брать следующие байты. Когда собрали символ - сверять полученный символ с заданной символьной маской. Если есть совпадение, то берём следующий байт и собираем новый символ и проверяем уже его. Если не совпали - ура, выходим, под шаблон строка не подпадает. Именно так работает PCRE и вообще конечные автоматы регулярных выражений.

В возможность корректно обойти utf8 в userspace php и обогнать элементарную регулярку - я не верю. Проверять лениво, много граблей обходить надо. А производительность libpcre в PHP ещё и весьма непросто корректно проверять из-за кеша регулярок в нескромные 4096 штук. Ёпт, а там ещё и JIT включен уже может быть. Это без вариантов, по крайней мере пока для userspace не прикрутят JIT.


т.е. когда я беру символ и сравниваю именно как символ и знаю что символ в utf-8 php всё равно не понимает его код? Он всегда сравнивает по битно? И что значит utf-8, что резиновая? utf-16 2 я так понимаю строго 2 байта = 16 бит.
8. Мелкий - 18 Июля, 2018 - 11:40:33 - перейти к сообщению
Doox911 пишет:
т.е. когда я беру символ и сравниваю именно как символ и знаю что символ в utf-8 php всё равно не понимает его код?

Не понял вопроса.

Doox911 пишет:
Он всегда сравнивает по битно?

Побайтово.
zend движок я не знаю, не покажу место в исходнике.

Doox911 пишет:
И что значит utf-8, что резиновая?

Да, от 1 до 4 байт на символ. Есть ли следующий байт для этого символа определяется по крайнему биту каждого байта.
По старому стандарту в UTF8 было от 1 до 6 байт, потом отпилили до 4 байт максимум.

Doox911 пишет:
utf-16 2 я так понимаю строго 2 байта = 16 бит.

Нет. Бывает 16 или 32 бита на символ.
Постоянную ширину из UTF имеет только UTF32, где символ всегда занимает 4 байта.

Кстати, 4 байт юникода вполне используется в жизни всякими смартфонами под смайлики. От чего интересные грабли собирали пользователи mysql, где utf8 кодировка не может хранить 4 байт, только максимум 3 на символ. Поэтому в mysql появилась utf8mb4, в 5.5 помнится.
9. Doox911 - 18 Июля, 2018 - 11:51:14 - перейти к сообщению
Мелкий пишет:

Не понял вопроса.


Как происходит сравнения символов? Например вот так:


Unicod это не кодировка, а стандарт?
10. Мелкий - 18 Июля, 2018 - 12:31:49 - перейти к сообщению
Эх, сейчас соберу.

Строгое сравнение IS_IDENTICAL опкода приходит сюда: https://github[dot]com/php/php-src/b[dot][dot][dot]perators[dot]c#L2112
Что видим:
- проверка на типы в самом начале
- если обе строки показывают в одно место в памяти - то они идентичны и можно не сравнивать
- иначе сравниваем их длины в байтах
- если длина идентичная, то дёргаем стандартную C функцию memcmp по байтовому сравнению участка памяти двух указателей с указанной длиной.

Unicode - да, стандарт.
Кодировки UTF8, UTF16, UTF32 - возможные представления этого стандарта.

 

Powered by ExBB FM 1.0 RC1