Модель природно притягує все, що стосується сутності: запити, обчислення, правила, побічні дії. Розподіл за видами відповідальності:
Лишається в моделі - те, що описує саму сутність: зв'язки, касти, $fillable, короткі методи стану (isPaid()).
Виноситься:
- запити - у скопи (
#[Scope]методи) або власний Query Builder моделі, коли скопів багато; - перетворення значень - у касти й об'єкти-значення (
Money,Address) замість пари аксесорів на кожне поле; - логіка над набором моделей - у власну колекцію (
#[CollectedBy]); - бізнес-операції («оформити замовлення», «повернути кошти») - у дії чи сервіси, а не методи
Order::refund()на 80 рядків з HTTP-викликами; - побічні дії - у події й слухачі, явні в коді, а не приховані в
booted(); - правила доступу - у політики;
- повторювана поведінка кількох моделей (slug, мультитенантність, архівування) - у трейти з
boot{Trait}().
Ознаки, що час ділити: модель імпортує сервіси й HTTP-клієнти, методи потребують моків у тестах, частина методів використовується лише в одному місці.
Мета не «тонка модель будь-якою ціною», а щоб кожна зміна мала одне очевидне місце.