removeElement() и clear() не работают в доктрине 2 со свойством коллекции массивов
Я пытаюсь сделать простой CRUD с доктриной 2, но когда пришло время обновить запись с одним свойством, установленным в качестве коллекции массивов, мне кажется, что removeElement() не работает так, как должно. Я даже попытался сделать это таким смехотворно безобразным способом:
foreach($entity->getCountries() as $c) {
$entity->getCountries()->removeElement($c);
$this->em->persist($entity);
$this->em->flush();
}
и это не сработало... Кто-нибудь знает, как справиться с этим? Я просил решение этой проблемы во многих различных формах и пока не получил хорошего ответа... кажется, что не хватает хороших примеров обработки Doctrine 2 CRUD. Я выложу больше кода по запросу.
редактировать
//in user entity
/**
*
* @param \Doctring\Common\Collections\Collection $property
* @OneToMany(targetEntity="Countries",mappedBy="user", cascade={"persist", "remove"})
*/
private $countries;
//in countries entity
/**
*
* @var User
* @ManyToOne(targetEntity="User", inversedBy="id")
* @JoinColumns({
* @JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $user;
2 ответа
Я делаю нечто подобное в проекте с событиями, в которых есть участники, не похожие на ваши отношения между пользователем и страной. Я просто изложу процесс, и вы увидите, что вы делаете по-другому.
На Participant
юридическое лицо
/**
* @ManyToOne(targetEntity="Event", inversedBy="participants", fetch="LAZY")
* @JoinColumn(name="event_id", referencedColumnName="id", nullable="TRUE")
* @var Event
*/
protected $event;
На Event
юридическое лицо:
/**
* @OneToMany(targetEntity="Participant", mappedBy="event")
* @var \Doctrine\Common\Collections\ArrayCollection
*/
protected $participants;
Также в Event#__constructor
Я инициализирую так:
$this->participants = new \Doctrine\Common\Collections\ArrayCollection();
Вот как я обновляю событие:
public function update(Event $event, Event $changes)
{
// Remove participants
$removed = array();
foreach($event->participants as $participant)
{
if(!$changes->isAttending($participant->person))
{
$removed[] = $participant;
}
}
foreach($removed as $participant)
{
$event->removeParticipant($participant);
$this->em->remove($participant);
}
// Add new participants
foreach($changes->participants as $participant)
{
if(!$event->isAttending($participant->person))
{
$event->addParticipant($participant);
$this->em->perist($participant);
}
}
$event->copyFrom($changes);
$event->setUpdated();
$this->em->flush();
}
Методы на Event
сущностью являются:
public function removeParticipant(Participant $participant)
{
$this->participants->removeElement($participant);
$participant->unsetEvent();
}
public function addParticipant(Participant $participant)
{
$participant->setEvent($this);
$this->participants[] = $participant;
}
Методы на Participant
сущностью являются:
public function setEvent(Event $event)
{
$this->event = $event;
}
public function unsetEvent()
{
$this->event = null;
}
ОБНОВЛЕНИЕ: метод isAttending
/**
* Checks if the given person is a
* participant of the event
*
* @param Person $person
* @return boolean
*/
public function isAttending(Person $person)
{
foreach($this->participants as $participant)
{
if($participant->person->id == $person->id)
return true;
}
return false;
}
Новый ответ
В вашей стране, если вы не имеете:
@ManyToOne(targetEntity="User", inversedBy="countries")
вместо inversedBy="id"?
Начальный ответ
Вам необходимо установить поле стран в вашей сущности как удалить каскад. Например, для двунаправленного отношения один ко многим:
class Entity
{
/**
*
* @OneToMany(targetEntity="Country", mappedBy="entity", cascade={"remove"})
*/
private $countries;
}
Таким образом, при сохранении вашей сущности, доктрина также будет сохранять изменения в коллекциях, привязанных к вашей сущности (например, странам). В противном случае вы должны явно удалить страны, которые вы хотите удалить, прежде чем очищать, например,
$this->em()->remove($aCountry);
Это также верно для операций сохранения, объединения и отключения. Больше информации здесь.