Завантаження публікації
ОГОЛОШЕННЯ

DTO та Value Objects у Laravel: легкий рівень і нормалізація даних перед записом

Як перестати тягати “сирий масив” по проєкту: збираємо дані в DTO, приводимо формат (trim, дати, boolean, гроші), відділяємо бізнес-значення у Value Object і зменшуємо кількість багів у create/update.


Максим Третяк
Максим Третяк
Газета Дейком | 01.01.2026, 14:00 GMT+3; 07:00 GMT-4

DTO (Data Transfer Object) — це простий об’єкт, який переносить дані між шарами системи в передбачуваному вигляді. Value Object — це “значення з правилами”: об’єкт, який гарантує, що всередині завжди валідний формат (наприклад, гроші, дата-період, slug, email). На легкому рівні тобі не треба будувати складну доменну модель. Тобі треба навчитися одному: перед тим як писати в базу, дані мають бути нормалізовані і зібрані в чітку структуру, а не “як прийшло з форми”.

Чому “сирий масив” — проблема. У Laravel легко зробити $data = $request->validated() і віддати його в сервіс. Але навіть валідовані дані можуть бути в “поганому” форматі: зайві пробіли, різний регістр, різні формати дат, числа як рядки, чекбокси як 'on', порожні строки там, де ти хочеш null. Якщо ти це не нормалізуєш, база заповнюється сміттям: потім фільтри по даті працюють дивно, slug має пробіли, boolean порівнюється як строка, а пошук стає непередбачуваним.

Легкий DTO-рівень — це коли ти робиш клас типу TagData, SectionData, ResourceData, NewsData і маєш один метод “зроби з масиву” (або з FormRequest). У цьому класі ти приводиш дані до нормальної форми і повертаєш об’єкт з типізованими властивостями. Сервіс отримує DTO, а не масив. У результаті сервісу не потрібно щоразу пам’ятати “trim тут, lowercase там”, бо DTO гарантує формат.

Нормалізація — це конкретні технічні кроки, які треба робити завжди. Рядки треба обрізати (trim) і часто чистити від “невидимих” символів. Порожні рядки часто варто перетворити на null, щоб в базі не було “порожнього тексту” замість відсутності значення. Slug зазвичай треба привести до нижнього регістру і замінити пробіли/підкреслення на дефіси. Email — у lower-case. Дати — привести в один формат і одну часову зону. Boolean — привести до true/false, а не залишати '0'/'1'/'on'. Числа і гроші — привести до чіткого типу, часто до integer у “копійках”, щоб уникнути проблем з float.

DTO добре працює разом з FormRequest. FormRequest гарантує, що поля існують і відповідають базовим правилам. DTO робить наступний рівень: приводить до єдиного формату, прибирає “сміття” і робить типи передбачуваними. Після цього сервіс працює як механізм сценарію, а не як набір “перевірок на кожному кроці”.

Value Objects — це наступний крок після DTO, коли ти хочеш зафіксувати правила для одного значення. Наприклад, Slug, Money, DateRange, Email, Percent. На легкому рівні Value Object може бути дуже простим: він приймає рядок/число і або створюється, або кидає виняток, якщо формат неправильний. Перевага в тому, що ти більше не передаєш по коду “просто рядок”, ти передаєш “Slug”, який завжди нормальний. І тоді не треба кожного разу згадувати правила.

Найкорисніші Value Object для адмінок і CMS — це Slug і DateRange. Slug — бо він часто використовується в URL, має бути чистим і унікальним. DateRange — бо фільтри “від/до” постійно ламаються через межі дня і часові зони. Money — якщо у вас рахунки та суми, бо float майже гарантовано дасть помилки на масштабі. Навіть якщо зараз “якось працює”, в майбутньому ці дрібні неточності перетворюються на фінансові баги.

Як це виглядає в реальному потоці create/update без зайвого ускладнення. Контролер приймає FormRequest і отримує валідовані дані. Далі замість того, щоб передати масив у сервіс, ти створюєш DTO: TagData::fromArray($request->validated()). DTO нормалізує. Сервіс отримує DTO і записує в базу тільки те, що треба. Якщо є 2+ таблиці або pivot — робиться транзакція. У такій схемі вся система стає менш крихкою: змінив правило нормалізації — змінив в одному місці.

Типові помилки при DTO/VO. Перша — робити DTO, але знову пхати туди “все підряд”, включно зі службовими полями, які не мають приходити з UI. DTO має бути whitelist-представленням даних, а не копією request. Друга — робити Value Objects занадто складними на старті і “задушити” навчання. Легкий рівень — це 1–2 VO максимум (Slug, Money), і тільки якщо реально є сенс. Третя — робити нормалізацію в 5 місцях: частково в контролері, частково в сервісі, частково в моделі. Потрібна одна точка правди: або DTO, або mutator, але узгоджено.

Висновок: DTO — це спосіб тримати дані в системі в однаковому, передбачуваному вигляді, а Value Object — спосіб зафіксувати правила для конкретних значень. На легкому рівні це означає одне: перед записом у БД ти не зберігаєш “як прийшло”, ти зберігаєш нормалізовані, типізовані дані. Це зменшує кількість багів, робить фільтри та пошук стабільнішими, і дає основу для масштабування, коли проєкт стане більшим і “дрібні” неточності почнуть боліти.


Максим Третяк — Кореспондент, який спеціалізується на суспільно важливих темах, пише про політику, фінансові ринки та економіку. Він проживає та працює в Україні.

Цей матеріал є частиною розгорнутої теми: Web-програмування, яка охоплює численні цікаві аспекти цієї події. Газета «Дейком» ретельно відстежує події, проводячи перевірку джерел та інформації, щоб забезпечити нашим читачам найбільш точне та актуальне інформування.

Цей матеріал опубліковано 01.01.2026 року о 14:00 GMT+3 Київ; 07:00 GMT-4 Вашингтон, розділ: Освіта, із заголовком: "DTO та Value Objects у Laravel: легкий рівень і нормалізація даних перед записом". Якщо в публікації з'являться зміни, про це буде зазначено та описано у кінці публікації.

Читайте щоденну газету та загальну стрічку новин газети Дейком, яка поєднує багато цікавого в понад 40 розділах з усіх куточків світу.


Save
ОГОЛОШЕННЯ

Новини, які можуть Вас зацікавити:

Штатні та позаштатні журналісти газети «Дейком» щодня готують сотні публікацій, щоб читачі отримували найоперативнішу, перевірену й глибоку інформацію. Ми працюємо для тих, хто хоче розуміти суть подій, бачити широку картину та бути на крок попереду.

Останні новини

Вибір редакції