Валидация

Composer предлагает множество валидаторов, которые можно использовать прямо из коробки, например:

top-think/think-validate

respect/validation

Валидация top-think/think-validate

Описание

Официальный валидатор ThinkPHP

Адрес проекта

https://github.com/top-think/think-validate

Установка

composer require topthink/think-validate

Быстрый старт

Создайте файл app/index/validate/User.php

<?php
namespace app\index\validate;

use think\Validate;

class User extends Validate
{
    protected $rule =   [
        'name'  => 'require|max:25',
        'age'   => 'number|between:1,120',
        'email' => 'email',    
    ];

    protected $message  =   [
        'name.require' => 'Имя обязательно',
        'name.max'     => 'Имя не должно превышать 25 символов',
        'age.number'   => 'Возраст должен быть числом',
        'age.between'  => 'Возраст должен быть между 1 и 120',
        'email'        => 'Неверный формат электронной почты',    
    ];

}

Использование

$data = [
    'name'  => 'thinkphp',
    'email' => 'thinkphp@qq.com',
];

$validate = new \app\index\validate\User;

if (!$validate->check($data)) {
    var_dump($validate->getError());
}

Внимание
В webman не поддерживается метод Validate::rule() из think-validate.

Валидация workerman/validation

Описание

Проект является китайской версией https://github.com/Respect/Validation

Адрес проекта

https://github.com/walkor/validation

Установка

composer require workerman/validation

Быстрый старт

<?php
namespace app\controller;

use support\Request;
use Respect\Validation\Validator as v;
use support\Db;

class IndexController
{
    public function index(Request $request)
    {
        $data = v::input($request->post(), [
            'nickname' => v::length(1, 64)->setName('Ник'),
            'username' => v::alnum()->length(5, 64)->setName('Имя пользователя'),
            'password' => v::length(5, 64)->setName('Пароль')
        ]);
        Db::table('user')->insert($data);
        return json(['code' => 0, 'msg' => 'ok']);
    }
}  

Доступ через jQuery

  $.ajax({
      url : 'http://127.0.0.1:8787',
      type : "post",
      dataType:'json',
      data : {nickname:'Том', username:'tom cat', password: '123456'}
  });

Результат:

{"code":500,"msg":"Имя пользователя должно содержать только буквы (a-z) и цифры (0-9)"}

Объяснение:

v::input(array $input, array $rules) используется для валидации и сбора данных. Если валидация данных не прошла, выбрасывается исключение Respect\Validation\Exceptions\ValidationException; если валидация успешна, возвращаются проверенные данные (массив).

Если бизнес-логика не перехватила исключение валидации, фреймворк webman автоматически перехватит его и вернет данные в формате JSON (например, {"code":500, "msg":"xxx"}) либо обычную страницу с ошибкой, в зависимости от заголовков HTTP-запроса. Если формат ответа не соответствует требованиям бизнес-логики, разработчик может самостоятельно перехватить исключение ValidationException и вернуть необходимые данные, как в следующем примере:

<?php
namespace app\controller;

use support\Request;
use Respect\Validation\Validator as v;
use Respect\Validation\Exceptions\ValidationException;

class IndexController
{
    public function index(Request $request)
    {
        try {
            $data = v::input($request->post(), [
                'username' => v::alnum()->length(5, 64)->setName('Имя пользователя'),
                'password' => v::length(5, 64)->setName('Пароль')
            ]);
        } catch (ValidationException $e) {
            return json(['code' => 500, 'msg' => $e->getMessage()]);
        }
        return json(['code' => 0, 'msg' => 'ok', 'data' => $data]);
    }
}

Руководство по функциональности Validator

use Respect\Validation\Validator as v;

// Валидация с одним правилом
$number = 123;
v::numericVal()->validate($number); // true

// Множественная валидация с цепочкой правил
$usernameValidator = v::alnum()->noWhitespace()->length(1, 15);
$usernameValidator->validate('alganet'); // true

// Получение первой причины неудачной валидации
try {
    $usernameValidator->setName('Имя пользователя')->check('alg  anet');
} catch (ValidationException $exception) {
    echo $exception->getMessage(); // Имя пользователя должно содержать только буквы (a-z) и цифры (0-9)
}

// Получение всех причин неудачной валидации
try {
    $usernameValidator->setName('Имя пользователя')->assert('alg  anet');
} catch (ValidationException $exception) {
    echo $exception->getFullMessage();
    // Будет напечатано
    // -  Имя пользователя должно соответствовать следующим правилам
    //     - Имя пользователя должно содержать только буквы (a-z) и цифры (0-9)
    //     - Имя пользователя не может содержать пробелы

    var_export($exception->getMessages());
    // Будет напечатано
    // array (
    //   'alnum' => 'Имя пользователя должно содержать только буквы (a-z) и цифры (0-9)',
    //   'noWhitespace' => 'Имя пользователя не может содержать пробелы',
    // )
}

// Пользовательские сообщения об ошибках
try {
    $usernameValidator->setName('Имя пользователя')->assert('alg  anet');
} catch (ValidationException $exception) {
    var_export($exception->getMessages([
        'alnum' => 'Имя пользователя может содержать только буквы и цифры',
        'noWhitespace' => 'Имя пользователя не должно иметь пробелы',
        'length' => 'length соответствует правилам, поэтому это сообщение не будет отображаться'
    ]));
    // Будет напечатано 
    // array(
    //    'alnum' => 'Имя пользователя может содержать только буквы и цифры',
    //    'noWhitespace' => 'Имя пользователя не должно иметь пробелы'
    // )
}

// Валидация объекта
$user = new stdClass;
$user->name = 'Александр';
$user->birthdate = '1987-07-01';
$userValidator = v::attribute('name', v::stringType()->length(1, 32))
                ->attribute('birthdate', v::date()->minAge(18));
$userValidator->validate($user); // true

// Валидация массива
$data = [
    'parentKey' => [
        'field1' => 'value1',
        'field2' => 'value2',
        'field3' => true,
    ]
];
v::key(
    'parentKey',
    v::key('field1', v::stringType())
        ->key('field2', v::stringType())
        ->key('field3', v::boolType())
    )
    ->assert($data); // также можно использовать check() или validate()

// Условная валидация
v::alpha()->validate(''); // false 
v::alpha()->validate(null); // false 
v::optional(v::alpha())->validate(''); // true
v::optional(v::alpha())->validate(null); // true

// Отрицательные правила
v::not(v::intVal())->validate(10); // false

Различия между методами validate(), check(), assert()

validate() возвращает логическое значение и не выбрасывает исключений.

check() выбрасывает исключение при неудаче валидации; можно получить первую причину неудачи через $exception->getMessage().

assert() выбрасывает исключение при неудаче валидации; можно получить все причины неудачи через $exception->getFullMessage().

Список распространённых правил валидации

Alnum() только буквы и цифры

Alpha() только буквы

ArrayType() массив

Between(mixed $minimum, mixed $maximum) проверяет, находится ли ввод в пределах двух значений.

BoolType() проверяет, является ли ввод булевым значением

Contains(mixed $expectedValue) проверяет, содержит ли ввод определенные значения

ContainsAny(array $needles) проверяет, содержит ли ввод хотя бы одно из определенных значений

Digit() проверяет, состоит ли ввод только из цифр

Domain() проверяет, является ли введенное значение действительным доменом

Email() проверяет, является ли введенное значение действительным адресом электронной почты

Extension(string $extension) проверяет расширение

FloatType() проверяет, является ли введенное значение действительным числом с плавающей точкой

IntType() проверяет, является ли ввод целым числом

Ip() проверяет, является ли ввод адресом IPv4 или IPv6

Json() проверяет, является ли ввод данными JSON

Length(int $min, int $max) проверяет, находится ли длина в пределах заданного диапазона

LessThan(mixed $compareTo) проверяет, меньше ли длина заданного значения

Lowercase() проверяет, состоит ли ввод из строчных букв

MacAddress() проверяет, является ли введенное значение MAC-адресом

NotEmpty() проверяет, не пусто ли значение

NullType() проверяет, является ли значение null

Number() проверяет, является ли ввод числом

ObjectType() проверяет, является ли ввод объектом

StringType() проверяет, является ли ввод строкой

Url() проверяет, является ли ввод URL

Больше правил валидации можно найти по адресу https://respect-validation.readthedocs.io/en/2.0/list-of-rules/

Дополнительная информация

Посетите https://respect-validation.readthedocs.io/en/2.0/