Разбираем паттерны: Active Record
Последнее время я изучаю паттерны проектирования и архитектурные подходы, и постепенно начинаю замечать, что многие вещи, которыми я давно пользуюсь в Laravel, имеют вполне конкретные названия.
Один из таких паттернов — Active Record.
Если коротко, идея Active Record заключается в том, что объект одновременно представляет данные из базы и умеет работать с этой базой.
Именно такой подход используется в Eloquent ORM в Laravel.
Как это выглядит в Laravel
Например, у нас есть модель пользователя:
class User extends Model { }
Получить пользователя и изменить его можно непосредственно через модель:
$user = User::find(10); $user->name = 'John'; $user->save();
Здесь User отвечает сразу за несколько вещей: представляет пользователя, содержит его данные и предоставляет методы для работы с базой данных — find(), save(), delete() и т.д.
Получается примерно такая схема:
User
├── данные пользователя
├── бизнес-логика
└── работа с БД
В этом и заключается основная идея Active Record.
Active Record vs Data Mapper
Другой распространённый подход — Data Mapper. Здесь объект предметной области не должен знать, как он сохраняется в базе.
Условно код будет выглядеть так:
$user = $userRepository->findById(10);
$user->changeName('John');
$entityManager->flush();
Здесь User отвечает за данные и поведение, а отдельный механизм — Repository/EntityManager/Data Mapper — занимается сохранением в БД.
То есть:
Active Record:
User
├── данные
└── работа с БД
Data Mapper:
User
└── данные и поведение
Data Mapper / EntityManager
└── работа с БД
В PHP хорошим примером Data Mapper является Doctrine ORM, который часто используется в Symfony.
Где здесь плюсы и минусы?
Главное преимущество Active Record — простота. Для обычных CRUD-приложений очень удобно написать:
$product = Product::find($id); $product->price = 100; $product->save();
Не нужно создавать дополнительные классы и абстракции.
Но у этого подхода есть и обратная сторона. При сложной бизнес-логике модели могут постепенно превращаться в очень большие классы, которые отвечают одновременно за данные, persistence и часть бизнес-логики.
Поэтому в Laravel часто используют Eloquent вместе с Service Layer, Repository и другими паттернами, распределяя ответственность между несколькими слоями.
В итоге я бы сформулировал разницу так:
Active Record — объект знает, как сохранить себя.
Data Mapper — объект не знает, как он сохраняется.
И, как мне кажется, это один из тех случаев, когда понимание самого паттерна помогает лучше понимать архитектуру фреймворка, а не просто запоминать методы Eloquent.
