Валидация запроса из формы в PHP
Доброго времени суток, сегодня я хочу рассказать Вам как можно быстро и просто проводить валидацию введенных пользователем данных в форму на стороне сервера.
Как известно при разработке сайтов частой задачей является получение каких-либо данных от пользователя и сохранение этих данных в базе. Однако, прежде чем эти данные сохранить, их надо проверить на валидность - или по другому на соответствие определенным заранее правилам.
Конечно, можно делать это по-старинке, в процедурном стиле, но, как только таких проверок становится относительно много эта задача превращается в рутину. Поэтому, желательно данную рутину как можно больше автоматизировать, для того, чтобы ускорить процесс разработки, упростить его и уменьшить количество ошибок.
Далее я покажу Вам пример на основе классов, который может быстро проверять данные на корректность. Обращаю Ваше внимание на то, что задача валидации - это настолько распространенная задача, что для ее решения уже придумано большое количество библиотек, которые можно найти в официальном реестре пакетов PHP - Composer.
Но, а мы с Вами будем рассматривать суть работы валидации в PHP, и примеры кода Вы можете, безусловно, дополнять самостоятельно в зависимости от Ваших потребностей.
Итак, код далее:
<?php # файл Validator.php
// базовый класс для всех валидаторов
abstract class Validator
{
protected $errors = [];
/**
* @var array
*/
private $data;
/**
* @var Model
*/
private $model;
// в конструктор передаем массив данных запроса из формы
public function __construct(array $data)
{
$this->data = $data;
}
// устанавливаем модель, если нам нужно будет обращаться к базе при проверке
public function setModel($model)
{
$this->model = $model;
}
// данный метод возвращает массив правил валидации, он разный для каждого валидатора
public abstract function rules(): array;
// добавляем ошибку (если поле не соответствует правилу) в список
// $field - название поля формы на английском (например, name - имя, age - возраст)
// $fieldName - локализованное название ( например, name - Имя, age - Возраст)
// $vars - массив заполнителей в формате [":переменная_1", ":переменная_2"],
// необходимы при выводе сообщений об ошибках
protected function addError($field, $fieldName, $message, $vars)
{
$replace = [];
$replace[':field'] = $fieldName;
$replace = array_merge($replace, $vars);
$this->errors[$field] = strtr($message, $replace);
}
// данный метод непосредственно проводит проверку
// возвращает массив ошибок, если таковые имеются
public function validate(): array
{
$rules = $this->rules();
$data = $this->data;
// локализованный список ошибок
$messages = require('./translations/ru_RU/validator.php');
// Todo: check for $rules and $data length equality
foreach( $data as $field => $value )
{
$rulesForParam = $rules[$field];
foreach ($rulesForParam as $rule ) {
if( !$rule->check($value) ) {
$this->addError(
$field,
$messages['field'][$field],
$messages['rule'][(string) $rule],
$rule->getVars()
);
}
}
}
return $this->errors;
}
}
Далее код класса PostValidator
<?php # файл PostValidator.php
class PostValidator extends Validator
{
public function __construct(array $data)
{
parent::__construct($data);
$this->data = $data;
}
public function rules(): array
{
// список правил-объектов проверяющих значение
return [
'author' => [ new NotBlank ], // не должно быть пустое
'category_id' => [ new NotBlank ],
'section_id' => [ new NotBlank ],
'title' => [ new Length(10, 50) ], // длина от 10 до 50
'url' => [ new NotBlank, new Slug ],
'image' => [ new NotBlank ],
'exerpt' => [ new Length(50, 550) ],
'content' => [ new Length(50, 1550) ],
'description' => [ new NotBlank ],
'keywords' => [ new NotBlank ],
'show_post' => [ new NotBlank ],
'published_at' => [ new NotBlank ]
];
}
}
Код правил, Вы можете добавлять свои правила
<?php
// каждое правило должно реализовывать данный интерфейс
interface IRule
{
/**
* Если правило пройдено успешно возвращаем true иначе ложь
*
*
* @param mixed $value
*
* @return bool
*/
function check($value): bool;
}
// правило - длина значения должна быть в промежутке
class Length implements IRule
{
public $minLen;
public $maxLen;
public function __construct(int $minLen, int $maxLen)
{
$this->minLen = $minLen;
$this->maxLen = $maxLen;
}
public function check($value): bool
{
$len = mb_strlen(trim($value));
if( $len < $this->minLen ) {
return false;
}
if( $len > $this->maxLen ) {
return false;
}
return true;
}
// массив заполлителей с значениями
public function getVars()
{
return [
':min' => $this->minLen,
':max' => $this->maxLen
];
}
public function __toString()
{
return 'length';
}
}
// правило - значение не должно быть пустым
class NotBlank implements IRule
{
public function check($value): bool
{
return mb_strlen(trim($value)) > 0;
}
public function getVars()
{
return [];
}
public function __toString()
{
return 'notblank';
}
}
<?php # файл переводов - validator.php
return [
'rule' => [
'notblank' => 'Поле \':field\' не может быть пустым!',
'length' => 'Длина поля \':field\' не может быть меньше :min или больше :max символов!',
'slug' => 'Поле \':field\' может состоять только из букв и тире'
],
'field' => [
'author' => 'Автор',
'category_id' => 'Категория',
'section_id' => 'Раздел',
'title' => 'Заголовок',
'url' => 'URL-адрес',
'image' => 'Изображение',
'exerpt' => 'Выдержка',
'content' => 'Текст',
'description' => 'Описание',
'keywords' => 'Ключевые слова',
'show_post' => 'Показать на сайте',
'published_at' => 'Опубликовано'
]
];
Используем следующим образом:
<?php
function controller()
{
// данные формы из массива $_POST
$formData = $_POST;
//
$validator = new PostValidator($formData);
$errors = $validator->validate();
if( $errors ) {
return $this->render('post.html.twig', ['errors' => $errors])
}
return return $this->render('post.html.twig', ['success' => 'Статья добавлена!']);
}
Вот так можно проводить валидацию формы в PHP, при этом вы можете добавить столько правил, сколько Вам самим необходимо в Вашем проекте.
-
- Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.