Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Но PHP — это не Java
Поскольку HTTP протокол является протоколом «без сохранения состояния»
UnitOfWork слишком переусложнён
ленивая» загрузка является плохой практикой… Так почему же тогда это один из центральных концептов
Зачем нам нужна настолько сложная система, для обеспечивания целостности данных?
Если у нашего приложения хорошая архитектура, то данные не меняются в случайных местах.… нам просто нужно изменить данные по POST запросу
Однако, я свято верю в то, что в хорошо спроектированном приложении, EntityManager должен использоваться только в трёх случаях:
быть неаккуратными с инъекцией зависимостей
$em->persist($entity);
$em->flush();
Доктрину пытаются использовать как любую другую ORM
Своих проблем добавляет и сама доктрина, вводя такие понятия как сущность, репозиторий
слой инфраструктуры сильно смешивается со слоем предметной области
Но это беда не инструментов, а умов.
один пользователь сделал один запрос, он отработал один раз и умер
Identity Map действительно антипаттерн
IM при нормальной архитектуре заменяется DI.
Data mapping тоже отдельная история
Сложный биндинг на разные таблицы
вовсе не классичессичейский фаулеровский AR
Раз уж про обёртки над стороджем
class ApiController extends Controller
{
function getListOfItems()
{
return $this->view($this->get('items_repository')->getListOfItems());
}
function createNewItem(CreateItemRequest $request)
{
$item = Item::fromDTO($request->getDTO());
// мы просто добавляем объект в репозиторий
// разве это не прекрасно?
$this->get('items_repository')->add($item);
return $this->view($item);
}
function updateNewItem(UpdateItemRequest $request)
{
$item = $this->get('items_repository')->findItem($request->getItemID());
if (!$item) {
throw new ItemNotFoundException($request->getItemID());
}
$item->updateFromDTO($request->getDTO());
// все что вернул репозиторий уже крутится в UoW так что нам не надо делать persist
// это сохраняет смысл репозиториев, там не должно быть метода update
return $this->view($item);
}
function removeItem(Request $request)
{
$itemRepository = $this->get('items_repository');
$item = $itemRepository->findItem($request->get('id'));
// DELETE запросы должны быть идемпотентными
// если такого айтема нет, то все хорошо, а если есть - удаляем из репозитория
if ($item) {
$itemRepository->remove($item);
}
return new Response(null, 204);
}
// вообще этот метод в листенере во фронт контроллере, но мне лень
// вызывается аккурат перед отправкой ответа
// так что если транзакция зафэйлится, мы сможем сгенерить ошибку
function onResponse() {
// flush вызывается на любой запрос, даже на get
$this->get('doctrine.orm.entity_manager')->flush();
}
}
А в Laravel это решается через DI
вокруг сраной модельки из-за того, что ей поручают заниматься не её делами
да ещё она и делает это криво.
плясали от горячей печки в итоге и сами обожглись и еду недоготовили, выпустив сырой продукт.
Именно DI, потому что мы даже напрямую не пляшем не с EM как в случае doctrine, не с контейнером App в случае Laravel
function foo(string $bar) : string {
return 'foo' + $bar;
}
что приходится по три дня рыться, чтобы выяснить в чём баг.
Laravel умеет инджектить в метод
IM в простом виде это и есть конструкция
жуткие контроллеры пляшущие вокруг EM.
вытаскивает другой инфраструктурный код
А в чём тогда их смысл, если в паралельном запросе мы снесли вообще данную запись, которую потом считаем существуюей ибо на у нас извлекается из DI
в существующий проект не с самой продуманной структурой БД
его хилость при наличии большого оверхеда на скорость разработки и производительность.
Во первых там есть работа с колекциями
НЕ прямой мэпинг и мделать это в разы проще чем в Doctrine.
Поддержка связей для вытаскивания связанных сущностей.
Скоупы, которые являются аналогом DDD-шных критерий.
Разные мутаторы и ассесоры
Обсервинг и т.д.
Посмотрите на свой пример и на мой, у вас пляска вокруг EM
даже в случае с AR код получается чище.
при этом анемичная кодель представляет собой спагетти из анотаций
репозитории с своим подъязыком DQL
ограниченные IM и UoW
rкоторые всё равно не гарантируют атомарность и целостность данных.
а вторая их только добавляет.
UoW прекрасно работает, когда у нас долгоживущее приложение
у вас пляска вокруг EM, хотя это должен быть инфраструктурный слой и он не должен засирать бизнес логику, даже в случае с AR код получается чище.
что ни одной засранной AR не снилось.
Плюс всё разнесено по 100500 слоям из-за чего малейшее изменение влечёт кучу правок.
На моей личной практике такой подход оказывается более эффективным.
SELECT * FROM users u WHERE u.foo = bar;
SELECT * FROM posts p JOIN users u ON u.id = p.user_id WHERE u.foo = bar; // или IN(id1, id2, ...)
А также сетить идентификатор в relation вместо целого объекта?
А Doctrine научилась фильтровать по идентификатору внешнего ключа, не выгружая целиком весь связанный объект из БД?
user.group = 5 работало всегда
$user->setGroupId(5);
Почему Doctrine ORM плохо подходит для PHP