Модель Order ездит по всему приложению: контроллер → Action → Service → Job. И везде тащит не только данные, но и запросы, персистентность, связи, события. Бизнес-логика начинает зависеть от имён колонок (customer_id, total_cents) и может случайно дёрнуть ->delete().
Expressive ставит типизированную границу поверх Eloquent. БД остаётся за Eloquent, а логика работает с чистым типизированным объектом:
$order = OrderModel::query()
->findOrFail($id)
->expressive(attributes: ['payable']);
Что это даёт:
→ Типы видны в классе. $order->totalCents = '1000' отвергнет сам PHP. Енамы строкой не подсунешь.
→ Fail на границе. null в non-nullable свойстве — NonNullablePropertyException, а не сюрприз тремя методами позже.
→ Без ленивых сюрпризов. Связи мапятся, только если запросил их явно. Не запросил — null.
→ Генератор + sync. make:expressive поднимает класс из модели, expressive:sync ловит дрейф в CI.
Не тащите везде: CRUD живёт на голом Eloquent, для API — по-прежнему API Resources. Expressive — для важных бизнес-флоу, где модель несёт лишнюю ответственность.
🔗 Подробнее
Библиотека пхпшника