2014-09-27 5 views
9

Я новичок в Symfony и Doctrine.Symfony2/Doctrine2 - ManyToOne - Сохранить обратную сторону

У меня есть сущность «Пользователь» и сущность «Тип». Один пользователь может иметь один из любимых типов, и один тип может иметь много пользователей, которые имеют этот особый тип в качестве избранного. Поэтому мне нужно много (User) to One (Type).

Я реализовал его, и он отлично работает (в основном). Но есть одна вещь, которую я не понимаю.

Если я что-то подобное, что это работает:

$user = new User(); 
$type = new Type(); 

$user->setFavoriteType($type); 
$em->persist($user); 
$em->persist($type); 
$em->flush(); 

объекты генерируются и хранятся в БД. И favorite_type_id правильно установлен. So изменение владельца действует как ожидается.

Но если я добавлю пользователя на обратную сторону (только) и сброшу диспетчер сущности, функция favorite_type_id не будет задано.

$user = new User(); 
$type = new Type(); 

$type->getUsers()->add($user); //same with $type->addUser($user); 
$em->persist($user); 
$em->persist($type); 
$em->flush(); 

Почему? Есть ли причина, почему это не работает с обратной стороны? Мне действительно нужно установить это вручную? Если я манипулирую методом addUser в объекте типа «$ user-> setFavoriteType ($ this)», он работает. Но разве это не должно быть задачей доктрины?

документация говорит

Когда двунаправленная связь обновляется, только Doctrine проверки на одной из обеих сторон для этих изменений. Это называется принадлежностью ассоциации.

Так что, похоже, это желание, верно? Но почему? Из-за производительности? Семантические причины?

Я был бы рад, если бы кто-нибудь мог объяснить это мне или сказать, что я делаю неправильно.

+0

Интересный вопрос, мне также интересно узнать о выборе этой логики. – DonCallisto

+0

http://doctrine-orm.readthedocs.org/en/latest/reference/unitofwork-associations.html – DonCallisto

+0

Можете ли вы показать нам связанные сущности? – ReynierPM

ответ

3

Проверьте Doctrine documentation on cascading.. Это должно помочь вам начать с того, что вы хотите сделать быстро и легко, добавив cascade={"persist"} и очистив кеш (чтобы восстановить кеш метаданных Doctrine).

0

Это происходит потому, что в основном при рассмотрении персистенции Doctrine отображает объекты PHP непосредственно в таблицы базы данных. В вашем случае пользователи и типы концептуально имеют отношение «Много-к-одному», но на уровне базы данных связь полностью представлена ​​в таблице «Пользователь» - пользователь имеет тип избранного, поэтому таблица «Пользователь» имеет столбец favorite_type_id. Хотя мы можем думать о Type Entities, имеющем список пользователей, для которых они являются фаворитами, это также, по существу, также получается путем просмотра таблицы User, в таблице Type нет ничего.

Настройка отображения сущностей в Doctrine сообщает Doctrine, какова взаимосвязь между объектами, и позволяет Doctrine предоставлять вам определенные методы доступа, такие как $type->getUsers(), но не изменяет, как хранятся базовые данные. Если я использую $user->setFavoriteType, я манипулирую данными, для которых существует прямая корреспонденция базы данных, но по умолчанию, если я звоню $type->addUser, я не являюсь основной целью сделать этот вид вызова из коробки, чтобы сохранить гидратированные объекты, с которыми вы в настоящее время работаете в актуальном состоянии, в отсутствие простое отбрасывание объектов и извлечение их из БД.

Конечно, вы видели, что вы можете настроить addUser, а также позвонить setFavoriteType или настроить каскадное сохранение, как предлагает Shon M, чтобы сделать поведение немного более похожим на то, как вы можете ожидать/хотите его. Это может показаться пустой тратой времени, чтобы оставить это с самого начала, но я подозреваю, что разработчики Doctrine сознательно решили реализовать необходимую функциональность самым простым способом, в то время как documenting it clearly и предлагают несколько простых альтернатив, если это то, что вы после , тем самым обслуживая всех так или иначе. Нравится вам это или нет, какие данные находятся в БД и какие данные работают в постгидратации PHP, являются технически разными вещами, особенно в такой модели, как Doctrine, где активность DB откладывается до тех пор, пока разработчик не попросит об этом, и это имеет большой смысл чтобы сделать все это максимально явным!