📊
Repository Pattern vs Query BuilderRepository — это не про «обернуть Eloquent в класс». Это про то, что доменный код не должен знать, откуда берутся данные.
Плохой Repository, который можно часто встретить:
class UserRepository {
public function findActive(): Collection {
return User::where('status', 'active')->get();
}
public function findByEmailAndStatus(string $email, string $status): ?User {
return User::where('email', $email)
->where('status', $status)
->first();
}
// ...ещё 40 методов под каждый запрос
} Это не Repository — это коллекция запросов в обёртке. Домен по-прежнему диктует методы через свои нужды, а репозиторий распухает.
Хороший Repository работает с агрегатами и скрывает детали хранения:
interface UserRepository {
public function findById(UserId $id): ?User;
public function findByEmail(Email $email): ?User;
public function save(User $user): void;
public function remove(User $user): void;
} Всё остальное — спецификации, критерии, query objects. Или честный Query Builder там, где это не домен.
Где Query Builder напрямую оправдан:— Read-модели (CQRS: команды через домен, запросы — прямо в БД)
— Отчёты, дашборды, агрегации — там нет смысла гидрировать объекты
— Простые CRUD-экраны без доменной логики
// Это нормально для read-модели
$stats = DB::table('orders')
->selectRaw('status, COUNT(*) as count, SUM(amount) as total')
->groupBy('status')
->get();
Пытаться пропустить это через Repository с Order-сущностями — оверинжиниринг.
Правило: Repository живёт на границе домена. Если у тебя нет домена, нет смысла в Repository. Если домен есть, Repository скрывает инфраструктуру, а не просто переносит запросы в другой файл.
🐸
Библиотека пхпшника#элементарный_выбор