1. Active Record – когда модель сама все делает
Это стандартный подход в Laravel. Модель – это не просто структура данных. Это объект, который умеет сам работать с базой. То есть ты обращаешься к ней, и она уже знает, что делать.
Пример максимально базовый:
User::where('is_active', true)->get();
Ты не пишешь SQL, не дергаешь отдельные классы. Модель User сама формирует запрос.
То же самое со связями:
public function orders()
{
return $this->hasMany(Order::class);
}
И дальше ты спокойно пишешь:
$user->orders()->latest()->get();
Можно писать полноценный запросы:
class Product extends Model
{
public static function getPriceRange(array $categoryIds, array $filters = []): object
{
return static::query()
->active()
->forCategories($categoryIds)
->filter($filters)
->selectRaw('MIN(price) as min_price, MAX(price) as max_price')
->first();
}
}
Почему Active Record всем заходит в начале
Плюсы:
– быстро писать
– легко читать код
– меньше файлов и абстракций
– отлично подходит для небольших и средних проектов
Но есть момент. Пока проект маленький – все ок. Когда логики становится много, модель начинает раздуваться. И вот тут начинаются проблемы.
2. Repository / Service pattern – когда все выносят наружу
Этот подход появляется, когда Active Record уже начинает мешать. Когда в модели не только связи, но и куча бизнес-логики, фильтров, условий, разных сценариев.
Суть простая:
– модель хранит только данные и базовые связи
– вся логика запросов уходит в отдельные классы
Например:
class ProductRepository
{
public function getActiveByCategories(array $categoryIds)
{
return Product::whereIn('category_id', $categoryIds)
->where('is_active', true)
->get();
}
}
А в контроллере уже так:
$products = $productRepository->getActiveByCategories($categoryIds);
Или еще дальше – через сервис:
class ProductService
{
public function getCatalog(array $categoryIds)
{
return Product::whereIn('category_id', $categoryIds)
->where('is_active', true)
->with('images')
->get();
}
}
Тут уже видно, что логика начинает жить отдельно от модели.
Зачем вообще усложнять
Потому что появляется контроль. Ты можешь:
– переиспользовать логику
– тестировать отдельно
– не засорять модели
– легче менять реализацию
Но есть и обратная сторона. Кода становится больше. Иногда сильно больше. И для простых проектов это реально оверкилл.
Главное отличие, если коротко
Active Record:
– модель сама работает с БД
– быстро и просто
– меньше структуры
Repository / Service:
– логика вынесена в отдельные классы
– больше контроля
– больше кода и структуры
Как обычно делают на практике
И вот тут важный момент. Почти никто не выбирает что-то одно в чистом виде.
Обычно:
– простые вещи – через Active Record
– сложная бизнес-логика – через сервисы
То есть сначала пишешь быстро, потом, когда начинает разрастаться, выносишь куски в сервисы. Не наоборот.
И это, если честно, самый живой и рабочий подход. Без фанатизма.