Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що варто тримати в моделі Eloquent, а що - ні?

Eloquent реалізує патерн Active Record: модель одночасно і представляє рядок таблиці, і вміє себе зберігати. Звідси спокуса класти в модель усе - і з часом вона перетворюється на «божественний клас» на тисячі рядків.

Що природно тримати в моделі:

  • опис даних: casts() (дати, енуми, JSON, об'єкти-значення), $fillable, $hidden;
  • зв'язки (hasMany, belongsTo);
  • локальні scopes - повторювані умови запитів: scopePublished, scopeForTeam;
  • аксесори й мутатори - представлення атрибутів (Attribute::make(...));
  • прості доменні методи, що стосуються лише цієї моделі й її стану: $order->isPaid(), $post->publish(), $subscription->isActive().

Що краще винести:

  • бізнес-операції, що зачіпають кілька моделей і зовнішні системи (оформлення замовлення, оплата, повернення) - в action-класи чи сервіси;
  • складні запити й звіти - у query-класи чи окремі класи звітів;
  • виклики сторонніх API, відправка листів - у сервіси, слухачі, джоби;
  • логіка, залежна від HTTP (поточний користувач, запит) - моделі не повинні знати про request() чи auth();
  • форматування для API - в API Resources.

Пастки:

  • події й спостерігачі моделей з бізнес-логікою: «при збереженні замовлення списати товар зі складу» - спрацює і в сидері, і при імпорті, і в тестах, і не спрацює при масовому update();
  • глобальні scopes, що неявно змінюють усі запити (наприклад, мультиорендність) - потужно, але легко забути про них і отримати несподіваний результат;
  • ледаче завантаження у методах моделі ($this->items->sum(...) у циклі) - N+1;
  • моделі як DTO між шарами - зміни в таблиці миттєво стають змінами в усіх шарах.

Корисні інструменти для «схуднення» моделей: власні колекції (newCollection, атрибут #[CollectedBy]), власні будівники запитів (#[UseEloquentBuilder]) для складних scopes, касти для об'єктів-значень, трейти для поведінки, спільної кільком моделям.

Баланс: Active Record - свідомий вибір Laravel заради простоти. Боротися з ним, будуючи повний шар репозиторіїв і доменних сутностей поверх Eloquent, зазвичай дорожче, ніж тримати моделі охайними за правилами вище.

Докладніше в документації: Laravel: Eloquent

Схожі питання