У Laravel-застосунку налаштування часто зручно описувати окремими Settings-класами. Вони дають типізований доступ, значення за замовчуванням, перетворення типів і зрозумілий інтерфейс для коду застосунку.
Але іноді з’являється зовсім інша задача: адмін-сторінка має просто показати, що реально збережено в таблиці settings.
Якщо в одній таблиці лежить кілька груп, а сторінка працює лише на читання, завантажувати всі Settings-класи може бути зайвою роботою.
У такому випадку пряме читання таблиці може бути не обхідним шляхом, а найточнішою моделлю для конкретного екрана.
Проблема з’являється, коли екрану не потрібна поведінка Settings-класів
Припустімо, в системі є кілька груп налаштувань: профіль, сповіщення, пошта, інтеграції та інші.
Кожна група має свій Settings-клас, але всі значення фізично лежать в одній таблиці.
Якщо адмін-сторінка повинна показати лише список груп, назв і збережених значень, їй не обов’язково створювати об’єкт кожного класу лише для того, щоб знову перетворити його на таблицю.
$rows = DB::table('settings') ->select([ 'group', 'name', 'payload', 'locked', ]) ->orderBy('group') ->orderBy('name') ->get();Такий запит відповідає рівно на те запитання, яке ставить сторінка: які записи зараз є в таблиці.
Він не намагається відтворити поведінку налаштувань, не підставляє значення за замовчуванням і не робить вигляд, що екран редагує ці дані.
Важливо розрізняти збережений стан і розраховане значення
Settings-клас може повертати значення, яке вже пройшло через перетворення типів, значення за замовчуванням або іншу логіку пакета.
А прямий запит до таблиці показує саме те, що збережено.
Це різні задачі. Для звичайного коду застосунку частіше потрібне готове значення. Для службової сторінки діагностики або огляду іноді важливіше бачити фактичний запис.
Application code: "What value should the application use?" Read-only admin page: "What is actually stored right now?"Одна таблиця з кількома групами сама підказує простішу модель читання
Коли всі групи зберігаються в одній таблиці, сама схема вже дає зручний зріз для сторінки огляду.
Можна згрупувати записи за group, відсортувати за name і показати їх без знання про конкретний PHP-клас кожної групи.
Це особливо корисно, якщо нові групи можуть з’являтися пізніше: сторінка бачить фактичні записи таблиці й не потребує окремого списку всіх Settings-класів.
$settings = DB::table('settings') ->select([ 'group', 'name', 'payload', 'locked', ]) ->orderBy('group') ->orderBy('name') ->get() ->groupBy('group');Ключова умова - сторінка справді працює лише на читання
Прямий запит до таблиці стає небезпечним, якщо той самий код починає ще й змінювати налаштування.
Тоді легко обійти перетворення типів, перевірки, кешування, події або інші гарантії, які надає пакет.
Тому межа проста: читати для діагностики або огляду можна напряму, якщо це свідоме рішення; записувати краще через офіційний механізм налаштувань.
// Read-only inspection: acceptable.$rows = DB::table('settings') ->orderBy('group') ->orderBy('name') ->get(); // Write path: use the Settings class.$settings = app(NotificationSettings::class);$settings->email_enabled = false;$settings->save();Не варто створювати об’єкти лише тому, що вони існують
Абстракція корисна тоді, коли сторінці потрібна поведінка, яку вона дає.
Якщо ж екрану потрібні лише чотири колонки з однієї таблиці, створення десятків об’єктів може не додавати жодної цінності.
Це не означає, що Settings-класи погані. Це означає, що конкретний екран має інше завдання.
Причина не лише в продуктивності
Так, прямий запит може бути дешевшим за завантаження багатьох класів. Але продуктивність тут не головний аргумент.
Сильніша причина - відповідність запиту задачі.
Сторінка огляду збережених налаштувань повинна читати збережені налаштування. Якщо для цього достатньо однієї таблиці, додаткова побудова об’єктів може лише приховувати просту природу запиту.
Коли пряме читання таблиці вже не підходить
Є кілька випадків, коли краще залишитися на рівні Settings-класів:
- сторінка повинна показувати вже перетворені значення;
- потрібні значення за замовчуванням, яких немає в таблиці;
- потрібна логіка конкретної групи;
- сторінка редагує налаштування;
- на рівні пакета є важливе кешування або додаткові гарантії;
- формат зберігання є внутрішньою деталлю, яку сторінка не повинна знати.
Прямий запит не означає, що сирі дані треба бездумно показувати
Навіть у режимі лише читання сторінці може знадобитися окреме представлення: підпис групи, форматування значення, приховування чутливих даних або зрозуміле відображення стану locked.
Тобто прямий доступ до таблиці спрощує отримання даних, але не скасовує відповідальність шару представлення.
Окремо потрібно подумати про чутливі значення
Таблиця налаштувань може містити значення, які не можна показувати навіть адміністратору у відкритому вигляді.
Тому read-only не означає "показати все". Перед відображенням потрібно визначити, які записи можна показувати повністю, які маскувати, а які взагалі не повертати у відповідь.
Це правило важливіше за зручність прямого запиту.
Що варто перевірити тестами
1. Сторінка показує всі потрібні групи з таблиці.2. Новий запис у settings з'являється без додавання нового класу до сторінки.3. Сторінка не змінює дані.4. Чутливі значення маскуються або приховуються.5. Сортування за group і name стабільне.6. Відсутній запис не підміняється неочікуваним значенням за замовчуванням.7. locked відображається як стан, а не змінюється сторінкою.8. Шлях запису й далі використовує Settings-класи.Для сторінки лише читання найпростіший шлях інколи є найточнішим
Settings-класи залишаються хорошою межею для коду, який використовує або змінює налаштування.
Але службова сторінка, яка повинна лише показати фактичний стан однієї таблиці, має іншу потребу.
У такому випадку прямий запит може бути простішим, прозорішим і менш зв’язаним із переліком конкретних класів.
Головне - не переносити цей виняток із читання на запис. Читати фактичний стан напряму можна. Змінювати налаштування варто через механізм, який відповідає за їхні правила.
Не кожне читання повинно проходити через всю поведінку моделі, якщо екрану потрібен лише фактичний стан зберігання.



