Ошибки валидации что это
Автор этого материала — я — Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML — то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
заметки, сайтостроение, html, валидация
Держите данные под контролем
Не секрет, что пользовательским данным доверять нельзя. Поэтому однажды человек и придумал валидацию данных. Ну а я, интереса ради и пользы для, написал свою реализацию валидатора на PHP.
Kontrolio — «очередная библиотека валидации данных», спроектированная независимой от фреймворков, расширяемой и дружественной контейнерам сервисов. Альтернативы: Respect, Sirius Validation, Valitron и многие другие.
В идеале предполагается, что вы используете некую реализацию контейнера сервисов (напр., PHP-DI, PHP League Container и др.), поэтому для начала необходимо зарегистрировать Kontrolio в нём:
В тех ситуациях, когда внедрить контейнер в проект затруднительно, вы можете использовать старый-добрый (на самом деле нет) синглтон:
Возможно вы заметите, что процесс валидации похож на оный из Laravel. Действительно, мне понравилось то, как там это реализовано, поэтому я решил использовать подобное решение. $data, $rules и $messages — ассоциативные массивы, где $data — это просто массив из пар ключ-значение (может быть многомерным), в котором ключ это имя атрибута, который необходимо провалидировать. Самое интересное — в правилах валидации и сообщениях об ошибках.
Правила валидации и сообщения об ошибках
Правило валидации в Kontrolio может быть представлено объектом класса правила или замыканием. Замыкания — самый простой способ описания правила валидации:
Правила-замыкания при обработке валидатором оборачиваются в объект класса Kontrolio\Rules\CallbackRuleWrapper, поэтому они располагают всеми теми же опциями, что и классы-правила, и вы можете написать замыкание в таком виде:
Замыкания удобны для простых правил, которые не предназначены для многоразового использования. Но если вы планируете использовать правило в разных местах, то лучше написать отдельный класс правила и затем создать его объект:
На заметку: Kontrolio поставляется с множеством правил «из коробки».
Опции правил валидации
В записи правил в виде замыканий вы заметили несколько опций, которые поддерживает любое правило. Немного о каждой опции далее.
valid. Это непосредственно условие. Эквивалент для класса правила — метод isValid, принимающий один аргумент, валидируемое значение атрибута. Чтобы стало понятнее, я покажу, как можно задать правило валидации для некого атрибута:
Это самые простые способы задания правила к атрибуту.
name. Это имя или идентификатор правила. Главным образом, используется для формирования сообщений об ошибках валидации:
Если вы создаете правило на основе класса, то вам нет необходимости задавать имя/идентификатор правила вручную, потому что наследуясь от Kontrolio\Rules\AbstractRule вы получаете данную функциональность по умолчанию в методе getName. Тем не менее вы можете свободно менять имя правила просто переопределив этот метод.
empty_allowed. Эта опция полезна в ситуациях, когда вам необходимо применить правило валидации только в том случае, если значение атрибута присутствует. С замыканиями это выглядит так:
Используя класс-правило с данной опцией, вы можете применить его к атрибуту двумя способами:
В данном случае, валидатор ответит положительно, если в значении атрибута будет значение ‘foo’ или он будет пуст.
skip. Эта опция не похожа на предыдущую. Она позволяет вам указать такое условие, которое прикажет валидатору пропустить проверку атрибута так, как будто данного правила и не было вовсе.
Эквивалент для правила-класса — метод canSkipValidation, и работает он абсолютно так же:
violations. Я любезно позаимствовал данный термин из Symfony. С использованием «нарушений» пользователь может получить более точное сообщение об ошибке (которое вам необходимо задать), хотя сам валидатор, так же как и прежде, просто вернёт false:
Вы можете задавать столько «нарушений», сколько пожелаете, и каждое из них затем может быть использовано для более детального описания ошибок валидации: от самого общего сообщения до самого детализированного. Посмотрите, как пример, класс Kontrolio\Rules\Core\Email.
Применяем несколько правил к атрибутам
До этого все примеры показывали описание одного правила к одному атрибуту. Но, естественно, вы можете добавлять сколь угодно много правил к сколь угодно многим атрибутам 🙂 Более того, вы можете совмещать использование замыканий и классов:
Всё круто, конечно, но есть еще один интересный способ записи целого набора правил — в виде строки:
Здесь каждое правило отделяется вертикальной чертой. Эту идею я позаимствовал из Laravel, но разница в том, что любая такая строка «распаковывается» в обычный массив правил, который вы видели уже не раз в статье. Так что строка выше в данном случае — всего лишь сахарок для вот такого массива:
Обратите внимание, что всё, что вы пишете после двоеточия, прямиком попадает в аргументы конструктора правила-класса:
Так что тут надо быть осторожным.
Пропускаем валидацию атрибута целиком
Пропуска отдельного правила или позволения пустых значений было бы недостаточно, поэтому Kontrolio содержит специальное правило, названное по аналогии с Laravel — ‘sometimes’ и представленное классом Kontrolio\Rules\Core\Sometimes. Когда вы добавите это правило к атрибуту, оно укажет валидатору пропустить проверку атрибута, если он отсутствует в массиве данных, переданных в валидатор, или если его значение пусто. Данное правило необходимо всегда ставить первым в списке.
По аналогии с предыдущими примерами данный может быть записан и так:
Вывод ошибок валидации
Ошибки валидации хранятся в виде ассоциативного массива, где ключи это названия атрибутов, а значения — массивы с самими сообщениями:
Дамп ошибок будет выглядить следующим образом:
Поэтому если вы хотите просто вывести все ошибки подряд, используйте метод валидатора getErrorsList. Он вернет плоский массив с сообщениями:
Для более сложного вывода ошибок можно использовать метод getErrors. Он возвращает сообщения, сгруппированные по названиям атрибутов:
Завершая сей рассказ
Вот так вы можете использовать Kontrolio, еще одну библиотеку валидации данных на PHP. Во время написания статьи я задумался о том, что простого пересказа документации будет недостаточно. Поэтому я планирую написать статью, где попытаюсь сравнить свою библиотеку с другими решениями.
Что такое ошибки валидации
Ошибками валидации считаются выявленные при проверке кода веб-страниц несоответствия общеустановленным стандартам, которые могут влиять на корректность работы и отображения отдельных элементов или всего сайта в целом.
К часто встречающимся ошибкам валидации относятся:
- отсутствие тега Doctype, который нужен для того, чтобы браузер мог корректно определить тип загружаемого им документа;
- проблемы с конвертацией специальных символов;
- использование блочных элементов внутри строчных;
- незакрытые элементы (нарушение вложенности), неверное количество кавычек;
- отсутствие атрибута alt у присутствующих на странице изображений; -элемент в неправильном разделе;
- отсутствие обязательных тегов в структуре элементов;
- теги, которые должны быть в единичном виде в пределах отдельной веб-страницы, повторяются несколько раз.
Не все ошибки валидации являются критическими и требуют исправления. Корректно работающий сайт при проверке валидности кода вполне может получить десяток-другой замечаний, наличие которых вполне допустимо, если они не оказывают влияния на его отображение и уровень юзабилити.
Отображение ошибок в интерфейсе, часть 1 – Как возникают ошибки
Привет! На связи Настя Овсянникова, старший дизайнер Липтсофт. Это серия статей для дизайнеров про ошибки и их отображение в интерфейсе. Обсудим:
- почему они возникают, что означают;
- что происходит «под капотом», как это связать с элементами интерфейса и контентом;
- как описать правила отображения ошибок в дизайн-системе.
В общем, разберёмся в технической стороне. Это поможет грамотно «закрыть» дизайн-решениями все возможные ситуации возникновения ошибок. Технические штучки и примеры буду приводить для десктопного веб-сервиса. Но всё это можно с некоторыми поправками отнести к любому сайту или приложению на разных устройствах.
В этом материале я не даю советы по визуальному дизайну и формулировке ошибок. Только помогаю систематизировать их отображение и составить гайд для команды.
Все статьи серии
Копаем вглубь:
1. Как возникают ошибки (вы здесь)
Если вам интересно, что привело нашу команду к созданию подробного гайда по ошибкам, можно почитать в конце этой части.
Как возникают ошибки
На сайтах и в большинстве приложений происходит взаимодействие между тремя субъектами:
- Пользователь (человек)
- Клиент (интерфейс, «фронтенд»)
- Сервер («бэкенд»)
Они обмениваются данными и командами. Это обобщенное представление процесса. На деле Сервер может состоять из нескольких связанных систем, а данные могут кочевать туда-сюда в более сложном порядке.
Пользователь взаимодействует с Клиентом (интерфейсом): переходит по ссылкам, заполняет и отправляет формы. Эту информацию получает Сервер, обрабатывает и отправляет ответ. Ответ «говорит» Клиенту, что отобразить на экране для Пользователя.
Веб-сервисы работают по протоколу HTTP. Ответ от Сервера всегда приходит в виде трёхзначного кода состояния (status code) и краткого пояснения. Например: 404 Not Found, 500 Internal Server Error. Вместе с кодом состояния Сервер может передать какие-то данные и дальнейшие команды.
Всего есть 5 групп кодов состояния. Они начинаются на 1, 2, 3, 4 и 5 соответственно. Нас интересуют коды 4__ и 5__ – это ответы Сервера, которые указывают на ошибку. Коды 1__, 2__ и 3__ – условно «положительные». Они двигают процесс дальше.
У каждой ошибки есть смысл и обстоятельства появления. Если рассмотреть все комбинации этих характеристик, можно для каждой зафиксировать:
- в каком элементе интерфейса отображаем ошибку;
- как и в каком месте экрана он появляется;
- какой контент в нём отображается.
Что мы и сделаем дальше.
Виды ошибок
С точки зрения взаимодействия между субъектами Пользователь – Клиент – Сервер можно выделить такие виды ошибок:
- сбой Клиента;
- результат валидации данных на Клиенте и Сервере;
- результат обработки данных и команд;
- потеря связи с Сервером.
Разберём подробнее, что к чему.
Сбой Клиента
Какой бы мы ни получили ответ от Сервера, на Клиенте может произойти сбой отображения контента. Пользователь увидит пустую белую страницу. Как облегчить эту ситуацию, обсудим в следующей части.
Примечательно, что сбой Клиента «перекрывает» остальные ошибки. То есть, даже если Сервер прислал другую ошибку, Пользователь не сможет её увидеть.
Результат валидации данных
Допустим, Пользователь заполнил и отправил форму. Прежде чем передать введённые данные Серверу, нужно проверить, правильно ли они заполнены. Иначе Сервер не сможет их корректно обработать.
Такая проверка происходит на стороне Клиента: допустимые символы, количество символов, наличие обязательных данных.
Если всё в порядке, данные передаются Серверу.
На стороне Сервера часто ещё раз проверяется формат введённых данных. Также проводятся проверки, где надо сравнить введённые данные с теми, что уже существуют в системе. Так что могут обнаружиться новые валидационные ошибки.
Пример
Пользователь регистрируется в системе и создаёт логин. Можно использовать только латинские буквы и цифры, а Пользователь вводит leonid. После валидации на Клиенте отобразится ошибка «Используйте только латинские буквы и цифры».
Пользователь исправляет логин на leonid96. Теперь проверка формата будет пройдена. Только после валидации на Сервере появится ошибка «Пользователь с таким логином уже существует». Потому что для этого нужно было сравнить введённый логин с другими логинами, существующими на сайте.
Ошибки валидации обычно приходят в виде кода состояния 400 BadRequest или 409 Conflict и описания, в чём заключается ошибка.
Результат обработки данных и команд
Может случиться так, что Сервер принял данные, но не смог их обработать. Или есть конфликт между поступающими командами. Или возник сбой при передаче результата от Сервера Клиенту. Какая бы ни была проблема, Сервер отправляет код состояния, который на неё указывает. Даже если он сам «упал» – обязательно об этом сообщит.
Таких ситуаций много – это все коды состояния 4__ и 5__.
Потеря связи с Сервером
Это ситуация, когда от Сервера не пришёл ответ (код состояния) на действия Пользователя. Обычно это значит, что пропал интернет или есть проблемы с VPN. Но может быть и так, что Сервер просто не отвечает.
Хочу ещё раз обратить внимание: «Сервер упал» и «Нет связи с Сервером» – это разные ситуации. В первом случае у Сервера проблемы, но он сообщает об этом кодом состояния. Во втором случае от него вообще нет ответа.
Контексты появления ошибок
Из «юиксовых» обстоятельств, которые влияют на способ отображения ошибки, мы выделили 4. В вашем проекте могут быть свои особенности, но подход можно применить такой же.
Эти обстоятельства – суть процесса, во время которого обнаружилась ошибка:
- Приём данных от Пользователя
Например, заполнение и отправка формы. В этом контексте важно сохранить данные, которые Пользователь успел ввести. - Скачивание или подгрузка данных по инициативе Пользователя
Например, скачивание документов или раскрытие аккордеона. Контекст важен тем, что большая часть контента на экране уже есть. - Перенаправление на другую страницу
Просто переход по ссылке. - Перенаправление в модальное окно
Контекст похож на предыдущий, но мы решили его описать отдельно.
Итого
Мы выделили 4 вида ошибок и 4 контекста их появления. Выходит, что всего есть 16 ситуаций, которые нужно «закрыть» дизайн-решениями. Сделаем это в следующей части:
P.S. Почему мы сделали гайд по ошибкам
До недавнего времени положение дел в одном из наших проектов был таково:
- маленькая постоянная команда (< 20 человек), один дизайнер;
- продукт создан командой с нуля;
- группы схожих пользовательских сценариев;
- дизайн-процесс включал сборку всех возможных состояний экранов (в т.ч. с ошибками);
- некритично, но ощутимо мало дизайн-ресурса.
Изначально я хранила правила отображения ошибок в Фигме. Это не создавало проблем. Я хорошо ориентировалась в проекте, а в новых сценариях использовала паттерны из реализованных. Бывало, пропускала пару экранов с ошибкой – тогда разработчики писали в личку, и я собирала нужный макет. Думаю, благодаря тому, что постоянная маленькая команда делала продукт с самого начала, мы как бы «и так всё знали об ошибках».
Однажды проект быстро наполнился более сложными сценариями. Команда разработки увеличилась в два раза, появился ещё один дизайнер. Моё внимание начало рассеиваться. Разработчики и тестировщики стали задавать больше вопросов, особенно новоприбывшие. Я обнаружила проблемы, которые не видела раньше, и выделила новые:
- Команда по-разному говорит
«Сервер упал», «не получили контент», «связь прервалась» – неясно, об одном ли техническом процессе мы говорим. И корректно ли объясняем его пользователю – тоже неясно. Также мы, дизайнеры, не уверены, что обработали все возможные случаи ошибок. Нужно подобие чеклиста. - Всё больше багов в отображении ошибок
Либо на эти макеты нет времени, либо дизайнеры не успевают проверить, чтобы в соседних сценариях одна ошибка отображалась одинаково. В общем, ресурсная западня. Нужен способ быстро, однозначно, не отвлекая друг друга определиться, как отображается ошибка. - Тяжело погружать новичков
Пытаясь объяснить, как в продукте отображаются ошибки, я путаюсь и сомневаюсь, что знаю, о чём говорю. Нужно подтянуть технические знания и опереться на них.
Тогда мы собрались с фронтенд- и бэкенд-разработчиками. Они объяснили, как появляются ошибки. Мы собрали и систематизировали уже реализованные способы их отображения. Добавили недостающие ситуации. Связали технические процессы и суть ошибок с элементами интерфейса. Так получился гайд по отображению ошибок и библиотека текстов для них, которые мы занесли в дизайн-систему. Этим пользуются: