Пакет Laravel Data пропонує безліч чудових можливостей для роботи з об’єктами даних у додатках Laravel. Об’єкти даних є багатими, типізованими та налаштовуваними, їх можна використовувати як API-ресурси, форму запитів, визначення TypeScript та інше.
Однією цікавою можливістю, яку я спочатку не помітив, є використання об’єктів Laravel Data для валідації запитів у контролерах. Фактично, об’єкти даних мають потужний механізм валідації, який можна використовувати різними способами. Розгляньмо простий приклад об’єкта ArticleData
:
namespace App\Data;
use Carbon\CarbonImmutable;
use Spatie\LaravelData\Data;
class ArticleData extends Data
{
public function __construct(
public string $title,
public string $content,
public ?string $description = null,
public ?CarbonImmutable $published_at = null,
public ?CarbonImmutable $created_at = null,
public ?CarbonImmutable $updated_at = null,
) {}
}
Неочевидно, але цей об’єкт автоматично визначає правила валідації:
App\Data\ArticleData::validate([])
// Illuminate\Validation\ValidationException Поле заголовка є обов'язковим. (та ще 1 помилка).
Ми не розглядатимемо всі аспекти валідації у Laravel Data, але документація з валідації детально розповість про все. Валідація чудово налаштовується і добре інтегрується з Laravel.
Розгляньмо наш приклад статті і використаємо об’єкт для валідації створення запису в базі даних через наш уявний контролер Article:
namespace App\Http\Controllers;
use App\Data\ArticleData;
use App\Models\Article;
class CreateArticleController extends Controller
{
public function __invoke(ArticleData $data)
{
$article = Article::create([
'title' => $data->title,
'content' => $data->content,
'description' => $data->description,
'published_at' => $data->published_at,
]);
return response()->json(ArticleData::from($article), 201, [
'Location' => route('article.show', $article),
]);
}
}
Якщо ми напишемо тест для цього, щоб спровокувати стандартну валідацію, він виглядатиме так:
#[Test]
public function it_validates_article_creation()
{
$response = $this->postJson('/article', []);
$response->assertStatus(422);
$response->assertJsonValidationErrors([
'title' => 'Поле заголовка є обов'язковим.',
'content' => 'Поле вмісту є обов'язковим.',
]);
}
Припустимо, ми хочемо зробити параметр published_at
необов’язковим, але при цьому перевірити, щоб формат дати відповідав очікуваному:
// app/Data/ArticleData.php
use Spatie\LaravelData\Attributes\Validation\DateFormat;
#[DateFormat(DATE_ATOM)]
public ?CarbonImmutable $published_at = null;
Якщо ми надішлемо поле published_at
з неправильним форматом, отримаємо такі помилки валідації у форматі JSON:
{
"message": "Поле заголовка є обов'язковим. (та 2 інші помилки)",
"errors": {
"title": [
"Поле заголовка є обов'язковим."
],
"content": [
"Поле вмісту є обов'язковим."
],
"published_at": [
"Поле дати публікації повинно відповідати формату Y-m-d\\TH:i:sP."
]
}
}
Припустімо, ми хочемо, щоб повідомлення валідації звучало інакше. Як і в об'єктах запитів Laravel, можна визначити метод messages():
public static function messages(): array
{
return [
'published_at.date_format' => 'Часова позначка події повинна бути у форматі ISO 8601 (наприклад, 2025-05-14T19:32:31+00:00).',
];
}
Масив повідомлень використовує ті ж шаблони, що й об'єкти запитів Laravel, підтримує вкладені об'єкти та інше. Ось як виглядатиме наше оновлене повідомлення для поля published_at
:
{
"message": "...",
"errors": {
"published_at": [
"Часова позначка події повинна бути у форматі ISO 8601 (наприклад, 2025-05-14T19:32:31+00:00)."
]
}
}
Щоб дізнатися більше про використання валідації з пакетом Laravel Data, ознайомтеся з розділом про розширене використання в Використання атрибутів валідації та сторінкою Атрибути валідації для всіх доступних атрибутів, які можна використовувати у валідації.