- Введение
- Живая валидация
- Настройка правил валидации
- Обработка загрузки файлов
- Управление побочными эффектами
- Тестирование
#Введение
Laravel Precognition позволяет предвидеть результат будущего HTTP-запроса. Одним из основных сценариев использования Precognition является возможность предоставлять «живую» валидацию для вашего фронтенд-приложения на JavaScript без необходимости дублировать правила валидации из бэкенда. Precognition особенно хорошо сочетается с Inertia-ориентированными стартовыми наборами Laravel.
Когда Laravel получает «прекогнитивный запрос», он выполняет все middleware маршрута и разрешает зависимости контроллера маршрута, включая валидацию form requests — но при этом не вызывает метод контроллера маршрута.
#Живая валидация
#Использование Vue
С помощью Laravel Precognition вы можете предоставить пользователям опыт живой валидации без дублирования правил валидации в вашем фронтенд-приложении на Vue. Чтобы показать, как это работает, создадим форму для создания новых пользователей в нашем приложении.
Сначала, чтобы включить Precognition для маршрута, в определение маршрута нужно добавить middleware HandlePrecognitiveRequests. Также следует создать form request для хранения правил валидации маршрута:
use App\Http\Requests\StoreUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (StoreUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);
Далее установите frontend-хелперы Laravel Precognition для Vue через NPM:
npm install laravel-precognition-vue
После установки пакета Laravel Precognition вы можете создать объект формы с помощью функции useForm из Precognition, указав HTTP-метод (post), целевой URL (/users) и начальные данные формы.
Затем, чтобы включить живую валидацию, вызывайте метод validate формы при событии change каждого поля ввода, передавая имя поля:
<script setup>
import { useForm } from 'laravel-precognition-vue';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = () => form.submit();
</script>
<template>
<form @submit.prevent="submit">
<label for="name">Name</label>
<input
id="name"
v-model="form.name"
@change="form.validate('name')"
/>
<div v-if="form.invalid('name')">
{{ form.errors.name }}
</div>
<label for="email">Email</label>
<input
id="email"
type="email"
v-model="form.email"
@change="form.validate('email')"
/>
<div v-if="form.invalid('email')">
{{ form.errors.email }}
</div>
<button :disabled="form.processing">
Create User
</button>
</form>
</template>
Теперь, по мере заполнения формы пользователем, Precognition будет предоставлять результаты живой валидации на основе правил валидации из form request маршрута. При изменении полей формы будет отправлен дебаунсированный «прекогнитивный» запрос валидации в ваше приложение Laravel. Вы можете настроить таймаут дебаунса, вызвав функцию setValidationTimeout формы:
form.setValidationTimeout(3000);
Когда запрос валидации выполняется, свойство validating формы будет равно true:
<div v-if="form.validating">
Validating...
</div>
Любые ошибки валидации, возвращённые во время запроса валидации или отправки формы, автоматически заполнят объект errors формы:
<div v-if="form.invalid('email')">
{{ form.errors.email }}
</div>
Вы можете определить, есть ли ошибки в форме, используя свойство hasErrors формы:
<div v-if="form.hasErrors">
<!-- ... -->
</div>
Также вы можете определить, прошло ли поле валидацию или нет, передав имя поля в функции valid и invalid формы соответственно:
<span v-if="form.valid('email')">
✅
</span>
<span v-else-if="form.invalid('email')">
❌
</span>
Поле формы будет отображаться как валидное или невалидное только после того, как оно изменится и будет получен ответ на запрос валидации.
Если вы валидируете только часть полей формы с помощью Precognition, может быть полезно вручную очищать ошибки. Для этого используйте функцию forgetError формы:
<input
id="avatar"
type="file"
@change="(e) => {
form.avatar = e.target.files[0]
form.forgetError('avatar')
}"
>
Конечно, вы также можете выполнять код в ответ на отправку формы. Функция submit формы возвращает промис запроса Axios. Это удобный способ получить полезную нагрузку ответа, сбросить поля формы после успешной отправки или обработать ошибку запроса:
const submit = () => form.submit()
.then(response => {
form.reset();
alert('User created.');
})
.catch(error => {
alert('An error occurred.');
});
Вы можете определить, выполняется ли запрос отправки формы, проверяя свойство processing формы:
<button :disabled="form.processing">
Submit
</button>
#Использование Vue и Inertia
Если вы хотите быстро начать разработку Laravel-приложения с Vue и Inertia, рассмотрите возможность использования одного из наших стартовых наборов. Стартовые наборы Laravel предоставляют готовую аутентификацию на бэкенде и фронтенде для вашего нового приложения.
Перед использованием Precognition с Vue и Inertia обязательно ознакомьтесь с нашей общей документацией по использованию Precognition с Vue. При использовании Vue с Inertia необходимо установить совместимую с Inertia библиотеку Precognition через NPM:
npm install laravel-precognition-vue-inertia
После установки функция useForm Precognition вернёт Inertia form helper с расширенными возможностями валидации, описанными выше.
Метод submit form helper был упрощён: теперь не нужно указывать HTTP-метод или URL. Вместо этого можно передать опции визита Inertia в качестве единственного аргумента. Кроме того, метод submit не возвращает Promise, как в примере с Vue. Вместо этого вы можете указать любые поддерживаемые Inertia обработчики событий в опциях визита, передаваемых методу submit:
<script setup>
import { useForm } from 'laravel-precognition-vue-inertia';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = () => form.submit({
preserveScroll: true,
onSuccess: () => form.reset(),
});
</script>
#Использование React
С помощью Laravel Precognition вы можете предоставить пользователям опыт живой валидации без дублирования правил валидации в вашем фронтенд-приложении на React. Чтобы показать, как это работает, создадим форму для создания новых пользователей в нашем приложении.
Сначала, чтобы включить Precognition для маршрута, в определение маршрута нужно добавить middleware HandlePrecognitiveRequests. Также следует создать form request для хранения правил валидации маршрута:
use App\Http\Requests\StoreUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (StoreUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);
Далее установите frontend-хелперы Laravel Precognition для React через NPM:
npm install laravel-precognition-react
После установки пакета Laravel Precognition вы можете создать объект формы с помощью функции useForm из Precognition, указав HTTP-метод (post), целевой URL (/users) и начальные данные формы.
Чтобы включить живую валидацию, следует слушать события change и blur каждого поля ввода. В обработчике change нужно обновить данные формы с помощью функции setData, передав имя поля и новое значение. Затем в обработчике blur вызвать метод validate формы, передав имя поля:
import { useForm } from 'laravel-precognition-react';
export default function Form() {
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = (e) => {
e.preventDefault();
form.submit();
};
return (
<form onSubmit={submit}>
<label for="name">Name</label>
<input
id="name"
value={form.data.name}
onChange={(e) => form.setData('name', e.target.value)}
onBlur={() => form.validate('name')}
/>
{form.invalid('name') && <div>{form.errors.name}</div>}
<label for="email">Email</label>
<input
id="email"
value={form.data.email}
onChange={(e) => form.setData('email', e.target.value)}
onBlur={() => form.validate('email')}
/>
{form.invalid('email') && <div>{form.errors.email}</div>}
<button disabled={form.processing}>
Create User
</button>
</form>
);
};
Теперь, по мере заполнения формы пользователем, Precognition будет предоставлять результаты живой валидации на основе правил валидации из form request маршрута. При изменении полей формы будет отправлен дебаунсированный «прекогнитивный» запрос валидации в ваше приложение Laravel. Вы можете настроить таймаут дебаунса, вызвав функцию setValidationTimeout формы:
form.setValidationTimeout(3000);
Когда запрос валидации выполняется, свойство validating формы будет равно true:
{form.validating && <div>Validating...</div>}
Любые ошибки валидации, возвращённые во время запроса валидации или отправки формы, автоматически заполнят объект errors формы:
{form.invalid('email') && <div>{form.errors.email}</div>}
Вы можете определить, есть ли ошибки в форме, используя свойство hasErrors формы:
{form.hasErrors && <div><!-- ... --></div>}
Также вы можете определить, прошло ли поле валидацию или нет, передав имя поля в функции valid и invalid формы соответственно:
{form.valid('email') && <span>✅</span>}
{form.invalid('email') && <span>❌</span>}
Поле формы будет отображаться как валидное или невалидное только после того, как оно изменится и будет получен ответ на запрос валидации.
Если вы валидируете только часть полей формы с помощью Precognition, может быть полезно вручную очищать ошибки. Для этого используйте функцию forgetError формы:
<input
id="avatar"
type="file"
onChange={(e) =>
form.setData('avatar', e.target.value);
form.forgetError('avatar');
}
>
Конечно, вы также можете выполнять код в ответ на отправку формы. Функция submit формы возвращает промис запроса Axios. Это удобный способ получить полезную нагрузку ответа, сбросить поля формы после успешной отправки или обработать ошибку запроса:
const submit = (e) => {
e.preventDefault();
form.submit()
.then(response => {
form.reset();
alert('User created.');
})
.catch(error => {
alert('An error occurred.');
});
};
Вы можете определить, выполняется ли запрос отправки формы, проверяя свойство processing формы:
<button disabled={form.processing}>
Submit
</button>
#Использование React и Inertia
Если вы хотите быстро начать разработку Laravel-приложения с React и Inertia, рассмотрите возможность использования одного из наших стартовых наборов. Стартовые наборы Laravel предоставляют готовую аутентификацию на бэкенде и фронтенде для вашего нового приложения.
Перед использованием Precognition с React и Inertia обязательно ознакомьтесь с нашей общей документацией по использованию Precognition с React. При использовании React с Inertia необходимо установить совместимую с Inertia библиотеку Precognition через NPM:
npm install laravel-precognition-react-inertia
После установки функция useForm Precognition вернёт Inertia form helper с расширенными возможностями валидации, описанными выше.
Метод submit form helper был упрощён: теперь не нужно указывать HTTP-метод или URL. Вместо этого можно передать опции визита Inertia в качестве единственного аргумента. Кроме того, метод submit не возвращает Promise, как в примере с React. Вместо этого вы можете указать любые поддерживаемые Inertia обработчики событий в опциях визита, передаваемых методу submit:
import { useForm } from 'laravel-precognition-react-inertia';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = (e) => {
e.preventDefault();
form.submit({
preserveScroll: true,
onSuccess: () => form.reset(),
});
};
#Использование Alpine и Blade
С помощью Laravel Precognition вы можете предоставить пользователям опыт живой валидации без дублирования правил валидации в вашем фронтенд-приложении на Alpine. Чтобы показать, как это работает, создадим форму для создания новых пользователей в нашем приложении.
Сначала, чтобы включить Precognition для маршрута, в определение маршрута нужно добавить middleware HandlePrecognitiveRequests. Также следует создать form request для хранения правил валидации маршрута:
use App\Http\Requests\CreateUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (CreateUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);
Далее установите frontend-хелперы Laravel Precognition для Alpine через NPM:
npm install laravel-precognition-alpine
Затем зарегистрируйте плагин Precognition в Alpine в вашем файле resources/js/app.js:
import Alpine from 'alpinejs';
import Precognition from 'laravel-precognition-alpine';
window.Alpine = Alpine;
Alpine.plugin(Precognition);
Alpine.start();
После установки и регистрации пакета Laravel Precognition вы можете создать объект формы с помощью «магии» $form Precognition, указав HTTP-метод (post), целевой URL (/users) и начальные данные формы.
Чтобы включить живую валидацию, нужно связать данные формы с соответствующим полем ввода, а затем слушать событие change каждого поля. В обработчике change вызывайте метод validate формы, передавая имя поля:
<form x-data="{
form: $form('post', '/register', {
name: '',
email: '',
}),
}">
@csrf
<label for="name">Name</label>
<input
id="name"
name="name"
x-model="form.name"
@change="form.validate('name')"
/>
<template x-if="form.invalid('name')">
<div x-text="form.errors.name"></div>
</template>
<label for="email">Email</label>
<input
id="email"
name="email"
x-model="form.email"
@change="form.validate('email')"
/>
<template x-if="form.invalid('email')">
<div x-text="form.errors.email"></div>
</template>
<button :disabled="form.processing">
Create User
</button>
</form>
Теперь, по мере заполнения формы пользователем, Precognition будет предоставлять результаты живой валидации на основе правил валидации из form request маршрута. При изменении полей формы будет отправлен дебаунсированный «прекогнитивный» запрос валидации в ваше приложение Laravel. Вы можете настроить таймаут дебаунса, вызвав функцию setValidationTimeout формы:
form.setValidationTimeout(3000);
Когда запрос валидации выполняется, свойство validating формы будет равно true:
<template x-if="form.validating">
<div>Validating...</div>
</template>
Любые ошибки валидации, возвращённые во время запроса валидации или отправки формы, автоматически заполнят объект errors формы:
<template x-if="form.invalid('email')">
<div x-text="form.errors.email"></div>
</template>
Вы можете определить, есть ли ошибки в форме, используя свойство hasErrors формы:
<template x-if="form.hasErrors">
<div><!-- ... --></div>
</template>
Также вы можете определить, прошло ли поле валидацию или нет, передав имя поля в функции valid и invalid формы соответственно:
<template x-if="form.valid('email')">
<span>✅</span>
</template>
<template x-if="form.invalid('email')">
<span>❌</span>
</template>
Поле формы будет отображаться как валидное или невалидное только после того, как оно изменится и будет получен ответ на запрос валидации.
Вы можете определить, выполняется ли запрос отправки формы, проверяя свойство processing формы:
<button :disabled="form.processing">
Submit
</button>
#Восстановление старых данных формы
В примере создания пользователя, описанном выше, мы используем Precognition для живой валидации; однако отправка формы происходит традиционным серверным способом. Поэтому форма должна быть заполнена любыми «старыми» данными и ошибками валидации, возвращёнными после серверной отправки:
<form x-data="{
form: $form('post', '/register', {
name: '{{ old('name') }}',
email: '{{ old('email') }}',
}).setErrors({{ Js::from($errors->messages()) }}),
}">
В качестве альтернативы, если вы хотите отправлять форму через XHR, вы можете использовать функцию submit формы, которая возвращает промис запроса Axios:
<form
x-data="{
form: $form('post', '/register', {
name: '',
email: '',
}),
submit() {
this.form.submit()
.then(response => {
form.reset();
alert('User created.')
})
.catch(error => {
alert('An error occurred.');
});
},
}"
@submit.prevent="submit"
>
#Настройка Axios
Библиотеки валидации Precognition используют HTTP-клиент Axios для отправки запросов на бэкенд вашего приложения. Для удобства экземпляр Axios можно настроить, если это требуется вашему приложению. Например, при использовании библиотеки laravel-precognition-vue вы можете добавить дополнительные заголовки к каждому исходящему запросу в файле resources/js/app.js вашего приложения:
import { client } from 'laravel-precognition-vue';
client.axios().defaults.headers.common['Authorization'] = authToken;
Или, если у вас уже есть настроенный экземпляр Axios для вашего приложения, вы можете указать Precognition использовать именно его:
import Axios from 'axios';
import { client } from 'laravel-precognition-vue';
window.axios = Axios.create()
window.axios.defaults.headers.common['Authorization'] = authToken;
client.use(window.axios)
Варианты библиотек Precognition для Inertia будут использовать настроенный экземпляр Axios только для запросов валидации. Отправка форм всегда будет выполняться через Inertia.
#Настройка правил валидации
Возможно настроить правила валидации, выполняемые во время прекогнитивного запроса, используя метод isPrecognitive запроса.
Например, в форме создания пользователя мы можем захотеть проверять, что пароль не был скомпрометирован, только при окончательной отправке формы. Для прекогнитивных запросов валидации мы просто проверим, что пароль обязателен и имеет минимум 8 символов. Используя метод isPrecognitive, мы можем настроить правила, определённые в нашем form request:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
class StoreUserRequest extends FormRequest
{
/**
* Получить правила валидации, применяемые к запросу.
*
* @return array
*/
protected function rules()
{
return [
'password' => [
'required',
$this->isPrecognitive()
? Password::min(8)
: Password::min(8)->uncompromised(),
],
// ...
];
}
}
#Обработка загрузки файлов
По умолчанию Laravel Precognition не загружает и не валидирует файлы во время прекогнитивного запроса валидации. Это предотвращает ненужную многократную загрузку больших файлов.
Из-за такого поведения следует убедиться, что ваше приложение настраивает соответствующие правила валидации form request, чтобы поле было обязательным только при полной отправке формы:
/**
* Получить правила валидации, применяемые к запросу.
*
* @return array
*/
protected function rules()
{
return [
'avatar' => [
...$this->isPrecognitive() ? [] : ['required'],
'image',
'mimes:jpg,png'
'dimensions:ratio=3/2',
],
// ...
];
}
Если вы хотите включать файлы в каждый запрос валидации, вы можете вызвать функцию validateFiles на клиентском экземпляре формы:
form.validateFiles();
#Управление побочными эффектами
При добавлении middleware HandlePrecognitiveRequests к маршруту следует учитывать, есть ли побочные эффекты в других middleware, которые следует пропускать во время прекогнитивного запроса.
Например, у вас может быть middleware, которое увеличивает общее число «взаимодействий» каждого пользователя с вашим приложением, но вы не хотите, чтобы прекогнитивные запросы учитывались как взаимодействия. Для этого можно проверить метод isPrecognitive запроса перед увеличением счётчика взаимодействий:
<?php
namespace App\Http\Middleware;
use App\Facades\Interaction;
use Closure;
use Illuminate\Http\Request;
class InteractionMiddleware
{
/**
* Обработать входящий запрос.
*/
public function handle(Request $request, Closure $next): mixed
{
if (! $request->isPrecognitive()) {
Interaction::incrementFor($request->user());
}
return $next($request);
}
}
#Тестирование
Если вы хотите выполнять прекогнитивные запросы в тестах, класс TestCase Laravel включает хелпер withPrecognition, который добавляет заголовок запроса Precognition.
Кроме того, если вы хотите проверить, что прекогнитивный запрос прошёл успешно, например, не вернул ошибок валидации, вы можете использовать метод assertSuccessfulPrecognition на ответе:
public function test_it_validates_registration_form_with_precognition()
{
$response = $this->withPrecognition()
->post('/register', [
'name' => 'Taylor Otwell',
]);
$response->assertSuccessfulPrecognition();
$this->assertSame(0, User::count());
}