> For the complete documentation index, see [llms.txt](https://docs.johncms.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.johncms.com/10.0/obshie-svedeniya/validaciya/rules.md).

# Правила валидации

Все правила живут в пространстве имён `Johncms\Validator\Rules`. Параметры передаются именованными аргументами конструктора, поэтому указывать нужно только то, что отличается от значений по умолчанию.

Общие для большинства правил параметры:

* **allowEmpty** — разрешить пустое значение. По умолчанию `false`: поле, у которого есть правила, обязательно. Подробнее — в [обзоре](/10.0/obshie-svedeniya/validaciya.md#obyazatelnye-i-neobyazatelnye-polya).
* **message** — свой текст ошибки вместо стандартного.

## NotEmpty — значение заполнено

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

```php
'admin_login' => [new NotEmpty()],
```

Пустыми считаются `null`, пустая строка, строка из одних пробелов, пустой массив и `false`. Ноль (`0`, `0.0`, `'0'`) пустым не считается.

## StringLength — длина строки

```php
// От 2 до 50 символов
'name' => [new StringLength(min: 2, max: 50)],

// Не короче 6 символов
'password' => [new StringLength(min: 6)],

// Не длиннее 250 символов, поле можно не заполнять
'meta_keywords' => [new StringLength(max: 250, allowEmpty: true)],
```

| Параметр | Значение по умолчанию | Описание           |
| -------- | --------------------- | ------------------ |
| `min`    | `null`                | минимальная длина  |
| `max`    | `null`                | максимальная длина |

Длина считается в символах, а не в байтах. Значение, которое не является строкой (например число), правило отклоняет: если поле объявлено текстовым, оно должно приходить текстом.

## EmailAddress — адрес электронной почты

```php
// Проверка формата адреса
'email' => [new EmailAddress()],

// Дополнительно проверить, что домен существует и принимает почту
'email' => [new EmailAddress(checkMxRecord: true)],
```

| Параметр        | Значение по умолчанию | Описание                                         |
| --------------- | --------------------- | ------------------------------------------------ |
| `checkMxRecord` | `false`               | проверять MX- или A-записи домена (запрос к DNS) |

Проверка DNS требует обращения к сети и заметно медленнее проверки формата, поэтому включайте её там, где адрес действительно должен принимать письма: регистрация, смена почты в профиле.

## Between — значение в диапазоне

Границы включаются в диапазон.

```php
'day'   => [new Between(min: 1, max: 31)],
'year'  => [new Between(min: 1900, max: 3000)],
```

Значение, которое не является числом, проверку не проходит. Числовая строка (`'5'`) считается числом.

## InArray — значение из списка

```php
'sex' => [new InArray(haystack: ['m', 'zh'])],
```

| Параметр   | Значение по умолчанию | Описание                          |
| ---------- | --------------------- | --------------------------------- |
| `haystack` | `[]`                  | список допустимых значений        |
| `strict`   | `false`               | строгое сравнение (с учётом типа) |

По умолчанию сравнение нестрогое, потому что форма присылает строки: значение `"1"` совпадёт со списком `[1, 2]`. Если типы важны — например список собирается из перечисления, — включите `strict: true`.

## Identical — значение совпадает с образцом

Сравнение строгое: `1` и `'1'` — разные значения.

```php
// Флажок согласия должен быть отмечен
'consent_1' => [new Identical(token: '1', message: __('Необходимо принять соглашение'))],

// Поле-ловушка для ботов должно остаться пустым
'website' => [new Identical(token: '', allowEmpty: true)],
```

| Параметр | Описание                       |
| -------- | ------------------------------ |
| `token`  | значение, с которым сравнивают |

## Captcha — защитный код

Проверяет ответ на капчу, которая выбрана в настройках сайта. Как именно — решает сама капча: встроенная сравнивает значение с кодом из сессии, не учитывая регистр, внешний сервис спрашивают о присланном токене.

```php
'code' => [new Captcha(scope: 'feedback')],
```

| Параметр | Значение по умолчанию | Описание                          |
| -------- | --------------------- | --------------------------------- |
| `scope`  | `'default'`           | имя формы, которую защищает капча |

Область должна совпадать с той, с которой форма запрашивала задание, иначе ответ будут искать не там. Подробности — в разделе [Капча](/10.0/obshie-svedeniya/captcha.md).

## Flood — защита от частой отправки

Проверяет, не отправлял ли посетитель сообщение слишком недавно. Значение поля не проверяется, поэтому правило относится к форме целиком.

```php
use Johncms\Validator\ValidationResult;

$rules[ValidationResult::FORM_KEY] = [new Flood()];
```

Сколько секунд осталось ждать, подставляется в текст сообщения.

## Ban — проверка банов посетителя

Тоже правило уровня формы: проверяется посетитель, а не поле.

```php
$rules[ValidationResult::FORM_KEY] = [new Flood(), new Ban(bans: [1, 13])];
```

| Параметр | Значение по умолчанию | Описание                                       |
| -------- | --------------------- | ---------------------------------------------- |
| `bans`   | `[1]`                 | типы банов, наличие которых запрещает отправку |

## ModelExists — запись в базе есть

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

```php
'user_id' => [
    new ModelExists(model: User::class, field: 'id'),
],
```

| Параметр  | Значение по умолчанию | Описание                             |
| --------- | --------------------- | ------------------------------------ |
| `model`   | —                     | класс модели Eloquent                |
| `field`   | —                     | поле таблицы, по которому идёт поиск |
| `exclude` | `null`                | замыкание, сужающее выборку          |

## ModelNotExists — записи в базе нет

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

```php
// Имя пользователя не занято
'name' => [
    new StringLength(min: 2, max: 20),
    new ModelNotExists(model: User::class, field: 'name'),
],

// Такое же сообщение от этого же посетителя за последние 10 минут — повтор
'message' => [
    new StringLength(min: 4),
    new ModelNotExists(
        model: GuestbookEntry::class,
        field: 'text',
        exclude: function ($query): void {
            $query->where('user_id', $this->user->id)
                ->where('time', '>', time() - 600);
        },
    ),
],
```

Параметр `exclude` принимает замыкание, которое получает построитель запроса и добавляет к нему условия. Так правило узнаёт об остальных данных формы — сами правила видят только значение своего поля.

## MxRecord — домен принимает почту

Проверяет наличие MX- или A-записи у домена из адреса. Обычно отдельно не нужен: его включает `EmailAddress` параметром `checkMxRecord`. Используйте его напрямую, если адрес проверяется по частям.

```php
'email' => [new EmailAddress(), new MxRecord()],
```

Значение без символа `@` правило пропускает молча — о том, что это не адрес, скажет `EmailAddress`, и два сообщения об одной ошибке под полем не появятся.
