(ссылка на предыдущий вопрос на всякий случай: Борьба с отношением «один ко многим» в форме администратора )
У меня есть отношение «многие ко многим» в моем проекте Symfony-1.3 / Propel-1.4 между пользователем и партнером . Когда Пользователь сохраняется, если он имеет определенный логический флаг, который является истинным, я хочу очистить все ссылки к партнерам. Вот что я делаю в данный момент, и это не работает:
// inside the User model class public function save(PropelPDO $con = null) { if ($this->getIsBlaBla()) { $this->setStringProperty(NULL); $this->clearUserPartners(); } parent::save($con); }
Установка свойства string в NULL; взгляд на БД ясно показывает это. Тем не менее, таблица USER_PARTNER по-прежнему поддерживает отношения между пользователями и партнерами. Поэтому я решил, что мне нужно очистить ссылки один за другим, вот так:
foreach($this->getUserPartners() as $user_partner) { $user_partner->delete(); //UserPartnerPeer::doDelete($user_partner); // tried that too }
Оба не делают трюк.
Как я уже упоминал в своем предыдущем вопросе, я просто изучаю обезьяну Symfony с помощью проб и ошибок, поэтому я, очевидно, пропущу что-то очень очевидное. Пожалуйста, указывайте мне в правильном направлении!
EDIT: Вот как я сделал это работу:
Переместил код в класс Form, например:
public function doSave(PropelPDO $con = null) { parent::doSave($con); if ($this->getObject()->getIsSiteOwner()) { $this->getObject()->setType(NULL); $this->getObject()->save(); foreach($this->getObject()->getUserPartners() as $user_partner) { $user_partner->delete(); } } return $this->getObject(); } public function updateObject($values = null) { $obj = parent::updateObject($values); if ($obj->getIsSiteOwner()) { $obj->clearUserPartners(); } return $this->object; }
Что это делает:
Это то, что мне нужно. Спасибо всем, кто принимал участие.
Okey, так что теперь у вас есть отношение «многие ко многим», где в терминах базы данных реализовано три таблицы (User, Parter и UserPartner). То же самое происходит с Symfony и Propel, поэтому вам нужно сделать что-то подобное в методе doSave, который должен объявляться в UserForm:
public function doSave($con = null) { parent::doSave($con); //First all that's good and nice from propel if ($this->getValue('please_errase_my_partners_field')) { foreach($this->getObject()->getUserPartners() as $user_partner_relation) { $user_partner_relation->delete(); } } return $this->getObject(); }
Проверьте имя метода «getUserPartners», которое должно быть объявлено на BaseUser.class.php (lib / model / om / BaseUser.class.php)
Если вы изучаете Symfony, я предлагаю использовать Doctrine вместо Propel, потому что, я думаю, что Doctrine проще и «красивее», чем Propel.
Для вашей проблемы, я думаю, вы на хорошем пути. Если бы я был вами, я сохраню свою функцию save()
Я напишу еще одну функцию в моей модели User
public function clearUserPartners(){ // You have to convert this query to Propel query (I'm sorry, but I don't know the right syntax) "DELETE FROM `USER_PARTNER` WHERE user_id = '$this->id'" }
С помощью этой функции вы не должны использовать PHP foreach.
Но я не понимаю, что такое атрибут StringProperty
…
UserPartnerQuery::create()->filterByUser( $userObject )->delete();
или
UserPartnerQuery::create()->filterByUser( $partnerObject )->delete();
Имела та же проблема. Это рабочее решение.
Дело в том, что ваше второе решение, т.е. цикл над связанными объектами и вызов delete () на них должны работать. Это документированный способ делать вещи (см .: http://www.symfony-project.org/book/1_0/08-Inside-the-Model-Layer#chapter_08_sub_saving_and_deleting_data ).
Но вместо того, чтобы бомбить DB с помощью запросов на удаление, вы могли бы просто удалить их за один раз, добавив метод в ваш класс Peer, который выполняет удаление, используя простой запрос БД.