feedbee
@feedbee

Взаимосвязи объектов-сущностей (entities) в ORM Doctrine2

Долгое время писал слой доступа к БД на уровне SQL-запросов. Теперь решил попробовать перейти на ORM. В частности — Doctrine2. Есть одна концептуальное недопонимание части процесса работы с entities.

Пример:

try {
$user = $entityManager->find('User', 1);
$user->setName('New name');
$entityManager->flush();
} catch (...)
{
// изменение провалилось по какой-то причине, т.е. объект не был сохранен
}

// ...

$user = $entityManager->find('User', 1);
$user->setOther('Other');
$entityManager->flush(); // <- здесь сохранится и [other], и [name], потому что [name] осталось измененным кодом выше


Проблема следующая. В одном месте кода я запросил $user, изменил его и попытался сохранить. Если бы сохранение прошло удачно, то проблемы бы и не было. Но у меня оно провалилось. Объект $user остался измененным в коде, но не в БД.

Ниже по коду происходит независимый от первой части запрос $user. EntityManager вернет тот же самый объект, который он вернул при первом вызове, т.е. объект с измененным свойством [name]. Но нижний блок кода об этом не знает. Изменив другое поле, код делает повторный запрос на сохранение. Но этот запрос с точки зрения вызывающего будет некорректным, т.к. в результате отправится UPDATE сразу на два свойства [name] и [other], вместо одного только [other].

Я догадываюсь, что просто неправильно работаю с ORM. Помогите мне, пожалуйста, понять правильную идеологию и разрулить приведенную ситуацию. Вопрос не в том, какие костыли вставить в коде, чтобы это работало как надо — я и сам вижу массу вариантов. Вопрос в том, как это нужно делать правильно.
  • Вопрос задан
  • 3653 просмотра
Пригласить эксперта
Ответы на вопрос 3
denver
@denver
Думаю в catch нужно делать $entityManager->detach($user)
Ответ написан
@Vampiro
В отличии от привычного вам "слоя SQL запросов", Доктрина не стремится сохранять в БД каждое изменение при первом же чихе пользователя. Изменяйте сущности в пределах разумного, затем один раз обновите все это в хранилище одним flush(). Это правильно и нормально, когда ваш скрипт в начале работы делает select'ы, а в конце — update/delete. И неправильно, когда по ходу работы скрипта в базу летит пачка запросов на модификацию разных полей в одной и той же табличке. Вначале немного ломает, но подиссонируете и попустит =)
Ответ написан
SowingSadness
@SowingSadness
web-разработчик
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
07 апр. 2020, в 13:42
1000 руб./за проект
07 апр. 2020, в 13:40
700 руб./в час
07 апр. 2020, в 13:37
10000 руб./за проект