Skip to content

✅ Валидация

PageBlocks включает гибкую систему валидации для проверки пользовательского ввода. Вы можете определять правила валидации с помощью строки, разделенной символами "|", или в виде массива строк с правилами.

🧩 Валидация в контроллере

Вы можете выполнять валидацию непосредственно в контроллере, используя метод $request->validate():

php
$request->validate([
    'honeypot' => 'empty',
    'username' => 'required|string',
    'password' => 'required|min:8'
]);

Альтернативно, вы можете определить правила в виде массива:

php
$request->validate([
    'honeypot' => ['empty'],
    'username' => ['required', 'string'],
    'password' => ['required', 'min:8']
]);

Оба формата полностью поддерживаются и взаимозаменяемы.

🔁 Формат ответа

Если валидация не проходит, PageBlocks определяет тип запроса:

  • Для fetch (XHR) запросов возвращается структурированный JSON-ответ с кодом состояния 422.
  • Для стандартных (не-XHR) запросов происходит перенаправление назад, а ошибки валидации сохраняются в сессии.

📦 Пример JSON-ответа

json
{
  "success": false,
  "message": "The given data was invalid.",
  "errors": {
    "username": ["The username field is required."],
    "password": ["The password must be at least 8 characters."]
  }
}

🧾 Вывод ошибок в Fenom через сессию

Когда ошибки валидации сохраняются в сессии, вы можете легко отображать их в шаблонах, используя встроенные переменные Fenom:

  • {$error_message} — содержит общее сообщение об ошибке (например, "The given data was invalid.")
php
{if $error_message}
    <p class="form-message text-center text-error text-danger">{$error_message}</p>
{/if}
  • {$errors} — содержит массив сообщений об ошибках для конкретных полей
php
<input type="text" 
       name="username" 
       class="form-control{if $errors.username} is-invalid{/if}"
>
  • {$old_input} — содержит все отправленные пользователем данные, которые можно использовать для повторного заполнения полей формы после ошибки валидации.
php
<input type="text" name="name" class="form-control" value="{$old_input.name}">

✍️ Пользовательские сообщения об ошибках

PageBlocks позволяет настраивать сообщения об ошибках валидации глобально или для отдельных полей.

🌐 Языковые файлы

Все стандартные сообщения валидации хранятся в:

php
lang/{lang}/validation.php

⚙️ Переопределение сообщений в коде

Вы можете передавать пользовательские сообщения в качестве второго параметра метода validate().

Пользовательское сообщение для всех полей с одинаковым правилом:

php
$request->validate([
    'honeypot' => 'empty',
    'username' => 'required|string',
    'password' => 'required|string|min:8'
], [
    'required' => 'The :attribute field is required.',
]);

Сообщения об ошибках для конкретных полей:

php
$request->validate([
    'honeypot' => 'empty',
    'username' => 'required|string',
    'password' => 'required|string|min:8'
], [
    'username.required' => 'We need to know your username!',
]);

🏷 Пользовательские имена полей (customAttributes)

Вы можете настроить отображаемые имена ваших полей ввода, передав третий параметр методу validate().

php
$request->validate([
    'username' => 'required|string',
    'password' => 'required|min:8',
], [], [
    'username' => 'Username',
    'password' => 'Password',
]);

🧪 Создание валидатора вручную

Хотя $request->validate() является наиболее удобным методом, вы также можете создать валидатор вручную, используя Validator::make():

php
$validator = Validator::make($request->all(), [
    'username' => 'required|string',
    'password' => 'required|string|min:8'
]);

🚫 Обработка неудачной валидации

php
if ($validator->fails()) {
    return response()->error('', $validator->errors());
}

🧼 Доступ к проверенным данным

php
$validated = $validator->validated();

⚙️ За кулисами

php
new Validation($data, $rules, $messages = [], $customAttributes = []);

🔄 Автоматическое перенаправление

Если вы хотите немедленную валидацию с автоматическим перенаправлением в случае неудачи:

php
Validator::make($request->all(), [
    'username' => 'required|string',
    'password' => 'required|string|min:8'
])->validate();

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

Иногда на одной странице размещено несколько форм — например, форма входа и форма регистрации. При валидации может возникнуть путаница: ошибки всех форм окажутся в одном массиве errors, и в шаблоне будет сложно понять, к какой форме они относятся.

Чтобы избежать этой проблемы, можно использовать метод validateWithBag($name), который сохраняет ошибки, старые значения и сообщение в именованный мешок (bag) с ключом $name.

🔧 Пример:

php
Validator::make($request->all(), [
    'username' => 'required|string',
    'password' => 'required|string|min:8',
])->validateWithBag('login');

Этот вызов:

  • запишет ошибки в errors['login'];
  • передаст старые значения в old_input['login'];
  • если задано сообщение, сохранит его в error_message['login'].

🖼️ Пример в шаблоне

html+php
{if errors.login}
    <ul class="text-danger">
        {foreach $errors.login as $field => $messages}
            {foreach $messages as $message}
                <li>{$message}</li>
            {/foreach}
        {/foreach}
    </ul>
{/if}

{if error_message.login}
    <div class="alert alert-danger">{$error_message.login}</div>
{/if}

<form method="post" action="/login">
    <input type="text" name="username" placeholder="Логин"
           value="{$old_input.login.username}">
    
    <input type="password" name="password" placeholder="Пароль">
    
    <button type="submit">Войти</button>
</form>

Аналогично можно обработать форму регистрации с другим bag:

php
Validator::make($request->all(), [...])
    ->validateWithBag('register');
php
{if errors.register}
    ...
{/if}

{if error_message.register}
    ...
{/if}

<form method="post" action="/register">
    <input type="text" name="email" value="{$old_input.register.email}">
    ...
</form>

🤔 Зачем это нужно?

  • ❌ Без validateWithBag() все ошибки попадают в errors, и их нельзя отнести к конкретной форме.

  • ✅ С именованным bag ты получаешь:

    • errors.login
    • old_input.login
    • error_message.login
    • и можешь точно знать, к какой форме всё это относится.

🧵 Работа с сообщениями об ошибках валидации

📋 Получение всех ошибок

php
$errors = $validator->errors();

🎯 Сообщения для конкретного поля

php
$messages = $errors->get('email');

❗️ Проверка наличия ошибок в поле

php
if ($errors->has('email')) {
    // В поле email есть ошибки валидации
}

📚 Доступные правила валидации

🔘 Логические значения

📘 Строки

🔢 Числа

🧺 Массивы

📅 Даты

📂 Файлы

🗄 Базы данных

🧮 Универсальные

🧰 Утилиты

Вот перевод на русский всех правил валидации с сохранением структуры и форматирования:

accepted

Поле должно содержать одно из значений: "yes", "on", 1, "1", true или "true".

php
'terms' => 'accepted'

Используется для проверки подтверждения (например, согласия с условиями через чекбокс).

accepted_if:другое_поле,значение,...

Поле должно быть принято только если другое поле имеет указанное значение.

php
'newsletter' => 'accepted_if:subscribe,true'

Если subscribe равно true, то newsletter должен быть принят (например, чекбокс отмечен).

boolean

Поле должно быть приводимо к логическому типу (true, false, 1, 0, "1", "0").

php
'agree' => 'boolean'

declined

Поле должно содержать одно из значений: "no", "off", 0, "0", false или "false".

php
'refuse_terms' => 'declined'

declined_if:другое_поле,значение,...

Поле должно быть отклонено только если другое поле имеет указанное значение.

php
'contact_by_phone' => 'declined_if:preferred_contact,email'

Если preferred_contact равно email, то contact_by_phone должен быть отклонен.

Строки

string

Значение должно быть строкой. Если допустимо null, используйте nullable|string.

php
'title' => 'string'

email

Значение должно быть корректным email-адресом.

php
'email' => 'required|email'

confirmed[:другое_поле]

Должно существовать соответствующее поле с именем {поле}_confirmation, если не указано другое.

php
// По умолчанию: сравнивает с `password_confirmation`
'password' => 'required|min:8|confirmed'
php
// Свое поле: сравнивает с `pass_confirm`
'password' => 'required|min:8|confirmed:pass_confirm'

Обычно используется для паролей, подтверждения email или любых полей, которые нужно ввести дважды.

same:поле

Поле должно иметь то же значение, что и указанное поле.

php
'password' => 'same:password_confirmation'

different:поле

Поле должно иметь значение, отличное от указанного поля.

php
'username' => 'different:email'

in:значение1,значение2,...

Значение поля должно быть одним из указанных.

php
'status' => 'in:active,inactive,pending'

not_in:значение1,значение2,...

Значение поля не должно быть одним из указанных.

php
'role' => 'not_in:admin,root'

json

Поле должно быть корректной JSON-строкой.

php
'meta' => 'json'

lowercase

Поле должно быть строкой в нижнем регистре.

php
'slug' => 'lowercase'

uppercase

Поле должно быть строкой в верхнем регистре.

php
'code' => 'uppercase'

url[:протоколы]

Поле должно быть корректным URL. Можно указать допустимые протоколы (например, http, https, steam).

php
'website' => 'url'              // Любой корректный URL
'game' => 'url:steam,minecraft' // Должен начинаться с указанных схем

uuid[:версии]

Поле должно быть корректным UUID по RFC 9562. Можно указать допустимые версии UUID (1-8).

php
'id' => 'uuid'          // Любая версия
'id' => 'uuid:4'        // Только версия 4
'id' => 'uuid:1,4,6'    // Несколько допустимых версий

Числа

numeric

Поле должно быть числом (целым или с плавающей точкой).

php
'price' => 'numeric'

integer

Поле должно быть целым числом.

php
'quantity' => 'integer'

decimal:мин,макс

Поле должно содержать указанное количество знаков после запятой.

php
'amount' => 'decimal:2,4' // Допустимо: 1.23, 5.678, 10.0000

gt:поле

Поле должно быть больше указанного поля.

php
'price' => 'gt:discounted_price'

gte:поле

Поле должно быть больше или равно указанному полю.

php
'end_date' => 'gte:start_date'

lt:поле

Поле должно быть меньше указанного поля.

php
'discounted_price' => 'lt:price'

lte:поле

Поле должно быть меньше или равно указанному полю.

php
'start_date' => 'lte:end_date'

min_digits:значение

Поле должно быть числовой строкой с минимальным количеством цифр.

php
'code' => 'min_digits:6'

max_digits:значение

Поле должно быть числовой строкой с максимальным количеством цифр.

php
'pin' => 'max_digits:4'

Массивы

array

Поле должно быть массивом.

php
'tags' => 'array'

contains:значение1,значение2,...

Массив должен содержать хотя бы одно из указанных значений.

php
'roles' => 'array|contains:admin,editor'
// Верно, если roles содержит 'admin' или 'editor'

Если поле - строка, оно будет сравниваться как единое значение.

distinct

Массив не должен содержать повторяющихся значений.

php
'tags' => 'array|distinct'
// ['php', 'html', 'php'] → ❌
// ['php', 'html', 'css'] → ✅

Работает с примитивными значениями (string, int).

in_array:другое_поле.*

Значение должно существовать в другом массиве.

php
'country' => 'in_array:countries.*'

/*
[
  'country' => 'UA',
  'countries' => ['UA', 'PL', 'DE']
]
*/

Можно также сравнивать с простым массивом:

php
'item' => 'in_array:available_items'

Даты

date

Поле должно быть корректной датой.

php
'birthdate' => 'date'

date_equals:поле_или_дата

Дата должна точно совпадать с другой датой или полем.

php
'start' => 'date_equals:end'
'fixed' => 'date_equals:2024-01-01'

date_format:формат,...

Дата должна соответствовать хотя бы одному из указанных форматов.

php
'start' => 'date_format:Y-m-d'
'custom' => 'date_format:d/m/Y,H:i'

Можно указать несколько форматов через запятую.

before:поле_или_дата

Дата должна быть раньше указанной.

php
'start' => 'before:end'

before_or_equal:поле_или_дата

Дата должна быть раньше или равна указанной.

php
'start' => 'before_or_equal:end'

after:поле_или_дата

Дата должна быть позже указанной.

php
'end' => 'after:start'
'event_date' => 'after:2025-06-01'

after_or_equal:поле_или_дата

Дата должна быть позже или равна указанной.

php
'end' => 'after_or_equal:start'

Файлы

file

Поле должно быть загруженным файлом.

php
'avatar' => 'file'

image

Поле должно быть изображением (jpeg, png, gif, webp и др.).

php
'avatar' => 'image'

mimes:тип1,тип2,...

MIME-тип файла должен соответствовать одному из указанных.

php
'document' => 'file|mimes:application/pdf'
'photo'    => 'image|mimes:image/jpeg,image/png'

Проверяется по внутреннему MIME-типу (на основе заголовков).

extensions:расш1,расш2,...

Имя файла должно иметь одно из указанных расширений.

php
'upload' => 'file|extensions:pdf,docx'

Менее строгая проверка, чем mimes - только по имени файла.

dimensions:мин_ширина=100,макс_высота=800,...

Проверяет размеры изображения.

php
'photo' => 'image|dimensions:min_width=200,max_height=500'

Доступные параметры:

  • width, height
  • min_width, max_width
  • min_height, max_height

Базы данных

unique:таблица,столбец[,исключитьID|поле,исключитьЗначение]

Значение поля должно быть уникальным в указанной таблице и столбце.

php
'email' => 'unique:modUserProfile,email'

Исключение текущей записи Можно исключить запись по ID:

php
'email' => 'unique:modUserProfile,email,123' // где id != 123

Или по другому столбцу:

php
'slug' => 'unique:modResource,alias,createdby,3' // где createdby != 3

exists:таблица,столбец[,исключитьID|поле,исключитьЗначение]

Значение поля должно существовать в указанной таблице и столбце.

php
'country' => 'exists:pbTableValue,code'

Исключение записи из проверки Можно пропустить одну запись по ID или столбцу:

php
'email' => 'exists:modUserProfile,email,123'       // где id != 123
'email' => 'exists:modUserProfile,email,blocked,1' // где blocked != 1

Универсальные

Эти правила применяются к строкам, числам, массивам и файлам. Поведение зависит от типа ввода.

min:значение

Поле должно иметь минимальное:

  • Число: не менее значения
  • Строка: не менее символов
  • Массив: не менее элементов
  • Файл: не менее килобайт
php
'age'    => 'min:18',       // число ≥ 18
'title'  => 'min:10',       // длина ≥ 10 символов
'tags'   => 'array|min:2',  // ≥ 2 элементов
'avatar' => 'file|min:100', // ≥ 100 KB

max:значение

Поле не должно превышать:

  • Число: максимальное значение
  • Строка: максимальную длину
  • Массив: максимальное количество элементов
  • Файл: максимальный размер
php
'age'    => 'max:99',
'title'  => 'max:255',
'tags'   => 'array|max:5',
'avatar' => 'file|max:500',

between:мин,макс

Поле должно находиться в диапазоне:

  • Число: значение в диапазоне
  • Строка: длина в диапазоне
  • Массив: количество элементов
  • Файл: размер в KB
php
'age'    => 'between:18,65',
'title'  => 'between:10,100',
'tags'   => 'array|between:2,4',
'avatar' => 'file|between:100,500',

size:значение

Поле должно точно соответствовать:

  • Число: равно значению
  • Строка: точное количество символов
  • Массив: точное количество элементов
  • Файл: точный размер
php
'code'   => 'size:6',       // строка из 6 символов
'count'  => 'size:10',      // число == 10
'tags'   => 'array|size:3', // ровно 3 элемента
'avatar' => 'file|size:300',// ровно 300 KB

required

Поле обязательно для заполнения.

php
'name' => 'required'

required_if:другое_поле,значение

Поле обязательно, если другое поле равно указанному значению.

php
'promo_code' => 'required_if:has_discount,true'

nullable

Позволяет полю быть null или пустым. Пропускает другие правила, если null.

php
'bio' => 'nullable|string'

empty

Поле должно быть пустым. Используется для явной проверки отсутствия значения.

php
'honeypot' => 'empty'

filled

Поле должно присутствовать и не быть пустым, если оно есть во вводе.

php
'nickname' => 'filled'

exclude

Поле будет исключено из проверенных данных.

php
'debug' => 'exclude'

exclude_if:другое_поле,значение

Поле будет исключено, если другое поле имеет указанное значение.

php
'discount_reason' => 'exclude_if:has_discount,false'

Исключенные поля удаляются из результата, даже если прошли проверку.

© PageBlocks 2019-present