Это действительно солидный старт. У меня есть только несколько предложений.
Вместо определения правил за пределами Validator класса, это может быть хорошей идеей для подклассов Validator и устанавливать правила внутри конструктора.
Создать общедоступные методы специально для каждого вида валидатора.
Некоторые псевдо-код, чтобы получить основную идею:
валидатор.PHP
class Validator { private $rule_collection = array(); public function __construct() { } public function ruleFor($ property) { if (!isset( $this->rule_collection[$ property])) $this->rule_collection[$ property] = new RuleBuilder( $property); return$ this->rule_collection[ $property]; } public function validate($ model) { $valid = true; foreach ($ this->rule_collection as $property =>$ rule_builder) { foreach ( $rule_builder->rules as$ rule) { if (! $rule->validate($ model-> $property))$ valid = false; } } return $valid; } }
rule_builder.php
interface IRule { public validate($ value); public get_message(); } class RuleBuilder { private $property; public$ rules = array(); public function __construct( $property) {$ this->property = $property; } public function isRequired() { return$ this->addRule(new RequiredRule()); } public function length( $min,$ max = -1) { return $this->addRule(new LengthRule($ min, $max)); } public function addRule(IRule$ rule) { $this->rules[] =$ rule; return $this; } }
И ваш конкретный валидатор:
class UserValidator extends Validator { public function __construct() {$ this->ruleFor('name') ->isRequired() ->length(20); } }
Чтобы использовать его:
$user = new User();$ user->name = "Foo"; $validator = new UserValidator(); if ($ validator->validate($user)) // save else // redraw form and show errors
Таким образом, все ваши классы правил скрыты. Все правила проверки являются переносимыми, поскольку они создаются внутри класса, специфичного для модели, и легко использовать функцию автообновления IDE, чтобы обнаружить, какие правила доступны, поскольку класс RuleBuilder имеет строго типизированные методы, инкапсулирующие каждое правило.
Кроме того, интерфейс IRule просто принимает значение, а не модель, что делает каждую единицу правила пригодной для обеспечения правильной работы вашей библиотеки проверки.
И для тех, кто занимается разработкой .NET/C#, этот шаблон, вероятно, выглядит знакомым, если вы использовали пакет NuGet FluentValidation для Visual Studio. Скажите, что вам нужно для разработки .NET, но есть некоторые драгоценности. Мне нравится шаблон, используемый FluentValidation.
codereview.stackovernet.com
В предыдущем уроке, мы получали данные от формы, а теперь мы будем проверять на корректность вводимых данных, так как если создать форму без такой проверки, то «плохие» пользователи могут навредить вашему сайту.
1. Давайте используем ту часть кода, где мы получили данные из формы:
Здесь, мы использовали функцию trim для удаления пробелов из начала и конца строки. Функция stripslashes нужна для удаления экранированных символов («Ваc зовут O’reilly?» => «Вас зовут O’reilly?»). Функция strip_tags нужна для удаления HTML и PHP тегов. Последня функция — htmlspecialchars преобразует специальные символы в HTML-сущности (‘&’ преобразуется в ‘&’ и т.д.)
Дальше, создадим функцию для проверки длинны строки:
Здесь, мы использовали функцию mb_strlen для проверки длинны строки. Первый параметр, $value это строка, которую нужно проверить, второй параметр $min минимально допустимая длинна строки, третий параметр $max — максимально допустимая длинна. Если длинна строки будет удовлетворительна, то функция вернет TRUE иначе FALSE.
3. Нам нужно «прогнать» переменные через эти функции:
Если длинна значений переменных нас устраивает, то можем продолжать. Также, мы использовали функцию filter_var с параметром FILTER_VALIDATE_EMAIL для валидации электронного адреса.
4. Давайте добавим сообщение об успешности операции, если данные прошли все проверки.
Если все произошло успешно, то мы увидим сообщение «Спасибо за сообщение»
Эта проверка не идеальна, так как не указывает на поля, которые заполнены не правильно, также сообщения об ошибках очень общие
Посмотреть исходники
php720.com
Необходимые для заполнения поля
Некоторые поля просто необходимо заполнять – нам не нужны отосланные пустые формы. Имя, почтовый адрес и основная информация – хорошие примеры необходимых полей, но, конечно, все зависит от цели заполнения формы.
В целях удобства пользователей для обозначения необходимого поля всегда используйте звездочку (*) красного цвета, если позволяет фон. Можно показать сообщения, отмеченные звездочкой, хотя многие пользователи сети понимают их автоматически. Это — самый последовательный и ненавязчивый способ обозначить, что требуется обязательно, а что нет.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
Совпадающие поля
Два самых привычных поля, требующих проверки совпадения – это поля ввода пароля и электронного адреса. Всегда необходимо дважды проверять поле пароля, потому что: 1) пользователь не видит пароль при его написании, поэтому может допустить ошибку и 2) позже мы потребуем от пользователя войти в систему (что он не сможет сделать, если запишет неверный пароль).
Однако двойная проверка поля с электронным адресом – спорный предмет. На самом деле это зависит от необходимости е-мейла на вебсайте. Для регистрации, которая требует постоянного обновления электронного адреса или системы обратной связи, требующей отклика, лучше проверить дважды, чтобы удостовериться, что е-мейл правильный. Однако для других чувствительных к е-мейлу случаев двойная проверка все же может оказаться слишком навязчивой. Для таких простых вещей, как подписка на рассылку новостей, обычно можно пропустить двойную проверку, и вместо этого «подтвердить» е-мейл другими способами, например, в форме страницы подтверждения.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
Правильный формат электронной почты
Правильный формат е-мейла включает знак @, точку (.) и разрешает только определенные символы. Более того, эти символы должны располагаться в верном порядке. Ниже есть несколько отрывков кода, как для стороны клиента, так и сервера, которыми можно пользоваться для подтверждения электронной почты.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
Правильный формат телефонного номера (США)
Для проверки правильности телефонного номера можно использовать регулярные выражения. Нижеприведенные фрагменты предназначены для обычного телефонного номера США, которые под другие образцы нужно будет переделать.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
Правильный формат почтового индекса (США и Канада)
Следующие отрывки кода – для подтверждения почтового индекса только США и Канады, но, скорее всего, в любом случае эти форматы самые распространенные. Если нужен формат для другой страны, можно использовать похожий вариант другого типа цифр индекса или почтового адреса.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
Что-то действительно выбираемое/подбираемое
Иногда вам требуется нечто с имеющимся по умолчанию значением. Тут мы не можем просто проверить, пустое ли поле, потому, что оно не может таким оставаться.
Внизу приведен пример, где у пользователя в выпадающем списке есть опции, а значение, выбранное по умолчанию — "Select One" (выберите из списка). Конечно, нам не нужно, чтобы пользователь выбрал "Select One", потому что так он не даст нам никакой ценной информации. Похожие ситуации могут использоваться для кнопок выбора опций или предопределенных полей ввода.
Валидация не потребуется, если на первом месте не будет находиться опция «Выберите из списка» ("Select One"), но для того, чтобы убедиться, что пользователь что-то деятельно выбирал вместо того, чтобы пропустить эту часть формы, нам следует создать эту «пустую» опцию.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
В диапазоне
Другая обычная форма валидации, заслуживающая фрагмента кода, это проверка того, находятся ли номер или дата в каком-либо диапазоне. Хороший пример тому – дата рождения, где человек не может быть младше или старше определенного возраста. Прочие образцы использования диапазона могут включать оценку доходов, подсчет расстояния или другие данные, где нужно выбрать точное число, но в каких-то пределах.
Другой способ работы с датами и диапазонами – постоянно использовать объект даты (как в JavaScript, так и в PHP и других языках программирования). На самом деле, это будет более верный способ все сделать, особенно если при выборе диапазона были важны точные день и месяц. Однако, чтобы сделать это решение более универсальным, мы скомпилировали нижеприведенный код.
Аналогичную технику можно применить ко многим пользовательским решениям.
Клиентская сторона (JavaScript)
Серверная сторона (PHP)
Captcha
Наконец, когда все уже сказано и сделано, а форма заполнена, вы, по меньшей мере, хотели бы убедиться, что данные в форму вводит человек. Для избегания спам-ботов и хакерских атак всегда перед отправкой формы включайте полностью автоматизированный открытый тест Тьюринга по распознаванию людей и машин, т.н. captcha. Это легко сделать на клиентской стороне, а времени он занимает всего секунду.
Некоторые разработчики предпочитают создавать свой собственный captcha через серию изображений, простых вопросов (Какого цвета яблоко?) или несложной арифметики. Хотя использовать готовый сервис captcha типа reCAPTCHA тоже удобно.
if(empty($_POST[‘posta’])) { $status = «Вы не указали свой E-mail!»; } elseif (!preg_match(«/^[0-9a-z_.]+@[0-9a-z_^.]+.[a-z]{2,6}$/i», $mail)) { $status = «Вы ввели некорректный E-mail!»; } else { $headers = «MIME-Version: 1.0rn»; $headers .= «Content-Type: «.$content.» charset=».$charset.»rn»; $headers .= «From: «».$name.»» <«.$mail.»>rn»; $headers .= «Bcc: vashe_milo2@yaya.rurn»; $headers .= «X-Mailer: E-mail from my super-site rn»; $sendmessage = «<html><body> <p><b>E-mail для связи:</b> «.$mail.»</p> <p><b>Сообщение:</b> «.$message.»</p> </body></html>»; if (mail($mailto,$subject,$sendmessage,$headers)) { unset($name, $mail, $message); $status = «Ваше сообщение отправлено!»; } else { $status = «По техническим причинам сообщение не было отправлено. Попробуйте снова, а если не получится, обратитесь к разработчикам»; } } } ?> <form method=’post’ name=’formname’> <p> <label for=»imko»>Контактное лицо:</label><br> <input name=»imko» maxlength=»50″ type=»text» size=»10″> </p> <p> <label for=»posta»>Почта для связи:</label><br> <input name=»posta» type=»text» size=»10″ value=»»> </p> <p> <label for=»tikstik»>Сообщение:</label><br> <textarea rows=»5″ cols=»14″ name=»tikstik»></textarea> </p> <p> <input name=»submit» type=»submit» value=»Отправить»> </p> </form> <?=$status;?>
shublog.ru
1. интеграция проходит достаточно легко. все недочеты исправляются на "раз-два" 1.1 привязки нет — опционально есть возможность передавать значение параметром или брать из post/get, что достаточно удобно. 1.2 привязки нет 1.3 "магических" строк и чисел внутри класса достаточно мало. из них только разбиение результата по <br />. мелочь в принципе, учитывая компактность самого класса. 1.4 только момент с <br />. тоже мелочь
2. достаточно просто расширить 2.1 правила едины — каждый метод валидации получает одни и те же параметры, возвращаемое значение обрабатывается одинаково. 2.2 механизм валидации есть, поэтому чтобы добавить правило валидации нужно добавить один метод в нужный класс (знаешь как сделать так, чтобы метод брался из класса?) или глобальную функцию, реализующие только логику валидации без реализации остального.
— именования методов не очень в тему. create_error по всей видимости должен создавать/генерировать ошибку или еще черт пойми что делать с ней. а он по сути добавляет критерий валидации. — значение обрабатывается с какой-то радости htmlspecialchars перед отдачей. это не задача валидатора. экранирование может не требоваться и его следует делать вне этого класса. — одно правило для каждого элемента формы — сравнивать значение с другим из набора переданных представляется возможным — у валидаторов не может быть параметров (длина — сколько символов) — передача в валидаторы значения по ссылке некорректна. изменению внутри функции переменная не подвергается.
Итого: 3
2. Безопасность = ставить нечего, что касается валидатора вообще.
Итого: 0
3. Оптимальность — смешаны системные ошибки и ошибки формы. это все таки совершенно разные вещи и фатальность у них разная
+ все сделано достаточно просто — про внутреннее использование всякого рода фильтраций и обработки вывода говорил уже (htmlspecialchars, implode <br />)
Итого: 4
4. Качество проверки данных 1. валидация даты = несколько нахардкожено, но в целом все корректно
2. email = ок
3. файлы — проверка изображений. если проверка на размер проходит, то файл пройдет валидацию. и опять же размер не параметром передается
4. числа — чего нето, того нет
5. номера телефонов = ок
реализовано 3 и 1 не полностью
Итого: 3
5. Оформление кода + phpdoc по делу + все достаточно хорошо структурировано и комментировано + именования в одном стиле — отступы местами не сходятся в стиле.
Итого: 4
6. Дополнительная оценка на усмотрение + 2 за короткий листинг — 1 за то, что из своей "короткости" он не решает ряд очень важных проблем (несколько правил на поле, сравнение полей) + 1 за E_ALL | E_STRICT
Итого: 2
Сумма: 16
phpforum.su
Всем здравствуйте! Помогите, пожалуйста, разобраться с корректной валидацией email. Есть HTML форма (в примере представлена часть формы для email) :
, которая обрабатывается PHP. // пример обработки поля email. другие поля обрабатываются таким же образом: ... if (empty($_POST["email"])) { $errors['email'] = "Не заполнено обязательное поле"; } else { $email = test_input($_POST["email"]); } ...
Понимаю, что надо использовать FILTER_VALIDATE_EMAIL , но куда именно нужно вписать «образец», по которому будет происходить дальнейшее сравнение внесенных в форму данных? Есть мысль оформить общий подход к валидации email так: 1 вариант: Если в данное поле формы было что-то введено if(isset($_POST[«email»])), то начинаем осуществлять проверку на корректность вносимых данных, а именно: использовать if(!filter_var($_POST[’email’], FILTER_VALIDATE_EMAIL)). Если введенные данные корректны (то есть соответствуют изначально заданному шаблону, например $var = «anyword@domain.ru»;), то продолжаем работу по другим полям формы. А Если введенные данные некорректны, то отправляем значение в массив ошибок ($errors) и выводим предупреждение об этом ( $errors[’email’] = «Не валидный email»;). А если никакие данные не были введены, то «пустое» значение тоже отправляется в этот же массив ошибок ($errors) , для него установлено уже свое сообщение ($errors[’email’] = «Не заполнено обязательное поле»;).
2 вариант: Если было отправлено пустое поле email, то присваеваем полученное значение в массив ошибок и выдаем сообщение «Не заполнено обязательное поле» (как это есть в части представленного кода), иначе если поле email было не пустым (какие-то данные все же были введены), то начинаем проверку: Если внесенные данные некорректны (то есть соответствуют изначально заданному шаблону, например $var = «anyword@domain.ru»;), значит полученный результат отправлять в массив ошибок с выдачей сообщения «Не валидный email». Иначе (если полученный результат корректен), то продолжаем двигаться по проверке других форм.
Самый главный вопрос: в каком месте кода необходимо задать этот шаблон/образец ($var = «anyword@domain.ru),по которому будет происходить сравнение введенной почты на ее корректность; чтобы все работало так как нужно, и чтоб этот образец нигде в браузере не всплывал ?
Заранее благодарю за помощь!
toster.ru
Речь пойдет о валидации POST или GET данных, хотя принципе это можно отнести и к данным полученным другими способами, например куки. По мере разработки какого либо веб приложения требуется писать интерфейс взаимодействия с пользователями и естественно создавать различные формы для отправки пользователями данных на сервер. например это могут быть комментарии. Думаю всем понятно и очевидно, что пришедшие данные нужно проверять, соответствуют ли они типу, размеру, заданному диапазону. В первую очередь это требуется для безопасности системы, сайта или базы данных, т.к. неправильно переданные данные или умышленно не правильно сформированный запрос может открыть доступ для злоумышленника.
Во вторых непроверенные данные, будучи неправильными могут вызвать нестабильную работу скрипта, системы или всего сервера. Поэтому все данные нужно проверять и перепроверять, возможно кто-то скажет, что излишняя паранойя ни к чему, я же считаю, что в этом вопросе её излишней просто не может быть.
Не доверяйте данным пришедшим от пользователей, не под каким предлогом, не при каких обстоятельствах. Бывает такое, что лишний раз написать код проверяющий пришедшие данные просто лень или же мы надеяться, что существующих методов проверки достаточно, в результате чего делаем сами себе поблажки.
Немного отступления от темы: Работа над проектами, разработка и программирование сайтов, скриптов, прочих систем занимает практически всё мое свободное время (по мимо рабочего), иными словами я занимаюсь этим делом максимально возможное количество часов в сутки. Время от времени возникает потребность в тестировании чего либо, ради забавы или просто любопытства. В итоге подобными тестируемыми лабораторными крысами становятся сайты сделанные на скорую руку, на самописных движках или на CMS древних версий. разумеется всё перечисленное страдает от криво написанного кода, нехватки котроля за данными и просто кишит различными багами. Собственно, в большинстве случаем за час моих экспериментов над такими сайтами мне удается найти несколько серьезных уязвимостей и большинство из них кроется в недостаточной валидации пришедших данных. В последнее время часто это встречается в скриптах обрабатывающих POST данные пришедших от JavaScript + Ajax.
Видимо программисты писавшие эти скрипты с использованием Ajax, считают, что раз все запросы происходят фоново, без ведома пользователя или просто без перезагрузки страницы, то и данные можно особо сильно не проверять.
как правило не малая часть таких скриптов оказывается на столько дырявой, что без особых усилий удается пробить брешь большего размера и залить свой шелл. разумеется исключительно с целью эксперимента и не более того (администрация таких сайтов всегда ставится в известность о имеющихся уязвимостях).
Думаю важность валидации всем понятна. На протяжении длительно времени я писал каждый раз один и тот же кусок кода, затем использовал собственные функции проверки данных, многие из которых были весьма примитивны и как правило разбросаны в разных частях (прииклюденных) файлов. В скором я начал знакомится с PHP фреймворками Zend, CI, Kohana, в каждом из был реализован свой класс для валидации данных, которые я заимствовал для своих проектов. В конце концов я решил заточить один из классов CI под свои нужды, но оказалось, что об этом уже позаботился автор одного из блогов по программированию. Далее делюсь его трудами, а именно модифицированной библиотекой CodeIgniter.
Разберем следующий код:
Как видно из примера, первой строкой мы подключаем файл класса validator.calss.php к нашем скрипту. Далее создаем экземпляр класса и сохраняем объект в переменную $validator. Затем используя метод $validator->set_rules($field, $label, $rules) задаем поля для валидации.
Данный метод принимает 3 параметра:
$field — имя поля валидации (значение атрибута name в теге <input name=»name» />)
$label — название поля валидации, будет подставляться в сообщения об ошибках
$rules — массив правил валидации, у которого в качестве ключа используется правило валидации, а в качестве значения — сообщение об ошибке для этого правила
После того, как все поля для валидации установлены, запускаем валидатор используя метод $validator->run(). Если валидация прошла успешно, то данный метод вернет значение TRUE, иначе, если есть хоть какие-то ошибки, вернет FALSE.
Для того чтобы получить сообщения об ошибках существует три метода:
get_string_errors() — возвращает все сообщения об ошибках в виде строки
get_array_errors() — возвращает все сообщения в виде массива, где в качестве ключа используется имя поля, а в качестве значения — описание ошибки для этого поля.
form_error($field) — возвращает сообщение об ошибке для поля, переданного в качестве параметра $field
По умолчанию сообщения об ошибках оборачиваются в тег <p></p>. Для того чтобы задать свое оформление используйте метод set_error_delimiters($prefix, $suffix). Например так:
Теперь сообщения об ошибках будут оборачиваться в div с классом «error»
Как видите все очень просто.
Для установки правил валидации Вы можете методу set_rules($fields) передать многомерный ассоциативный массив. Давайте посмотрим на пример:
Как видите я записал те же самые правила валидации, что и в первом примере, только в виде многомерного ассоциативного массива. Вы можете использовать любой из способов, который Вам больше подходит в той или иной ситуации.
Итак, какие же правила валидации поддерживает данный класс?
Я вынес в этот класс наиболее распространенные правила валидации, с которыми сталкивается каждый. Вот полный список этих правил:
required
Возвращает FALSE если поле не заполнено
integer
Возвращает FALSE если значение не является целым числом
float
Возвращает FALSE если значение не числового вида
valid_url
Возвращает FALSE если значения не является корректным URL адресом
valid_email
Возвращает FALSE если значения не является корректным e-mail адресом
valid_ip
Возвращает FALSE если IP-адрес не является действительным
matches[field]
Возвращает FALSE если элемент не соответствует значению другого элемента field
alpha
Возвращает FALSE если элемент содержит не только буквы
valid_captcha[field]
Возвращает FALSE если значение в сессии field не равно значению поля формы
valid_date
Возвращает FALSE если элемент содержит не корректную дату
Большинство этих правил используют фильтры, которые стали доступны в PHP 5.
При желании вы всегда можете расширить набор правил для валидации, дописав нужные функции в класс Validator.
Для того чтобы получить обработанное значение POST данных используется метод:
Вместо $field подставляется нужный ключ POST данных.
А для того, чтобы очистить все значения POST данных используется метод:
Обычно данный метод вызываетя для очистки формы, при успешной обработке формы.
Часть данного поста я все же скопипастил, т.к. всё переписывать нет желания да и смысла. Возможно кто-то скажет, а зачем же вообще писать заново пост и приводить в нем частично копипаст если можно просто поделиться ссылкой? Дело в то, что данный PHP класс взят за основу класса валидации для Rche CMS над которой я веду работы уже несколько месяцев.