Репозиторій у DDD - колекція агрегатів в пам'яті з погляду домену: «дай замовлення за id», «збережи замовлення». Домен не знає, як саме дані зберігаються - SQL, документна база, зовнішній API.
interface OrderRepository
{
public function find(OrderId $id): ?Order;
public function save(Order $order): void;
public function nextIdentity(): OrderId;
}
Конфлікт з Eloquent. Eloquent - патерн Active Record: модель сама знає, як себе зберегти ($order->save()), і є водночас доменним об'єктом і рядком таблиці. Класичний DDD передбачає Data Mapper: доменні об'єкти без знань про базу, а окремий шар (як Doctrine ORM) переносить їх у таблиці.
Варіанти на практиці:
1. Eloquent-моделі як доменні об'єкти, без репозиторіїв. Найпоширеніший і чесний для більшості Laravel-проєктів: поведінка в моделях, запити - в query scopes і окремих класах-запитах. Репозиторій-обгортка над Eloquent, що лише проксіює find/save, додає шар без користі.
2. Репозиторій як межа для складних запитів і тестування: інтерфейс у домені, реалізація на Eloquent. Має сенс, коли треба підміняти сховище в тестах доменної логіки чи коли запити справді складні. Але «чистоти» не дає: повертаються Eloquent-моделі з усією їх магією.
3. Чисті доменні об'єкти + Eloquent як шар зберігання. Домен - звичайні PHP-класи, репозиторій перетворює їх у Eloquent-моделі й назад. Максимальна ізоляція, але багато коду перетворень і втрата зручностей Laravel (зв'язки, касти, події моделей).
4. Doctrine ORM замість Eloquent - справжній Data Mapper, якщо DDD - ключова вимога проєкту.
Типові помилки:
- «репозиторій для кожної моделі» з методами
all(),find(),create(),update()- дублювання Eloquent без жодної переваги; - репозиторій повертає query builder - абстракція протікає, і логіка запитів розповзається;
- репозиторій для читання й для запису однаковий - звіти й списки (читання) зручніше робити окремими класами-запитами, а репозиторій лишити для агрегатів (CQRS-підхід у легкому варіанті).
Головне питання: яку проблему вирішує шар? Якщо відповідь «так прийнято», - його, ймовірно, не варто додавати.