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

Чи потрібен патерн Repository поверх Eloquent?

Repository (за Фаулером) - посередник між доменом і даними, що поводиться як колекція доменних об'єктів: додати, знайти, видалити, - приховуючи, як і де вони зберігаються.

Типова реалізація в Laravel-проєктах:

interface OrderRepository
{
    public function find(int $id): ?Order;
    public function forUser(User $user): Collection;
    public function save(Order $order): void;
}

final class EloquentOrderRepository implements OrderRepository { /* ... */ }

Аргументи «за»:

  • запити в одному місці: складні запити не розкидані по контролерах і сервісах;
  • підміна в тестах: бізнес-логіку можна тестувати з репозиторієм у пам'яті, без бази;
  • незалежність від сховища: теоретично можна замінити Eloquent чи базу.

Аргументи «проти» в контексті Laravel:

  • Eloquent - уже Active Record: модель сама вміє зберігатися й будувати запити. Репозиторій, що повертає ті самі моделі Eloquent, не приховує сховища: модель усе одно має save(), delete() і ледаче завантаження зв'язків;
  • «дірява» абстракція: методи на кшталт findByStatusAndDateAndUserWithRelations() множаться, бо Eloquent-будівник запитів гнучкіший за будь-який інтерфейс;
  • заміна бази - рідкісний сценарій, а заміна ORM у Laravel-проєкті - ще рідший;
  • тестування з базою в Laravel дешеве (SQLite в пам'яті, транзакції, фабрики), тож аргумент «тести без бази» слабшає;
  • більше коду: інтерфейс + реалізація + реєстрація в контейнері на кожну модель.

Компромісні рішення, що дають більшу частину користі:

  • scopes і власні будівники запитів (#[UseEloquentBuilder]) - повторювані умови в одному місці;
  • query-класи для складних запитів і звітів (MonthlyRevenueQuery);
  • action-класи - бізнес-операції, що працюють з моделями напряму.

Коли репозиторій справді виправданий:

  • доменна модель окремо від Eloquent (DDD з чистими сутностями, які не знають про базу) - тоді репозиторій обов'язковий: він перетворює рядки бази на доменні об'єкти;
  • дані з кількох джерел за одним інтерфейсом (база + зовнішній API + кеш);
  • модульний моноліт, де модуль не повинен віддавати свої моделі назовні.

Для співбесіди: важливо показати розуміння компромісу, а не «завжди» чи «ніколи».

Докладніше в документації: Мартін Фаулер: Repository

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