2011-06-23 9 views
8

doctrine 2で単純なCRUDを実行しようとしていますが、配列コレクションとして1つのプロパティを設定してレコードを更新するとき私はremoveElement()が正常に動作するようには見えません。私もこの途方もなく醜い方法でそれをやってみました:doctrine 2で配列コレクションのプロパティでremoveElement()とclear()が機能しない

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; 
+0

正確にどのようなヨ達成しようとしていますか?あなたはすべての国を削除しようとしていますか?あるいは、ある国を削除しようとしていますか?あなたは、ドキュメントの関連付けのセクションを読んだことがありますか?http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-associations.html#removing-associations – rojoca

+0

はい@rojoca私はそれをすべて読んだ。そして、私はより多くの異なる国のためにそれらを変更することができるように、1つのユーザーエンティティに関連付けられているすべての国を削除しようとしています。 –

答えて

12

私は、参加者にあなたのユーザー/国の関係と違うことのないイベントを持つプロジェクトで同様のことをします。私はプロセスをレイアウトするだけで、あなたが何か異なることをしているかどうかを知ることができます。私はこのような初期化Event#__constructorでも

/** 
* @OneToMany(targetEntity="Participant", mappedBy="event") 
* @var \Doctrine\Common\Collections\ArrayCollection 
*/ 
protected $participants; 

ParticipantエンティティEventエンティティで

/** 
* @ManyToOne(targetEntity="Event", inversedBy="participants", fetch="LAZY") 
* @JoinColumn(name="event_id", referencedColumnName="id", nullable="TRUE") 
* @var Event 
*/ 
protected $event; 

ここ

$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エンティティの方法があります:Participantエンティティの

public function removeParticipant(Participant $participant) 
{ 
    $this->participants->removeElement($participant); 
    $participant->unsetEvent(); 
} 

public function addParticipant(Participant $participant) 
{ 
    $participant->setEvent($this); 
    $this->participants[] = $participant; 
} 

方法は以下のとおりです。

public function setEvent(Event $event) 
{ 
    $this->event = $event; 
} 

public function unsetEvent() 
{ 
    $this->event = null; 
} 

UPDATE: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; 
} 
+0

私はこれを私のプロジェクトに適用しています。しかし、簡単な質問...私は配列($ _POST実際に)私の更新機能を渡していますどのようにあなたはオブジェクトとして渡すようにイベントを設定しますか?私はそれが教義のためにもっと「健康的」だと思いますよね?配列をオブジェクトに「自動的に」送り込む方法はありますか? –

+0

私は$ _POSTから "自動"オブジェクト生成を避けるでしょう。私がこれを好きな理由は、イベントの入力が複雑で、多くの検証が必要なためです。私は配列(例えば '$ _POST')をとり、' Event'オブジェクトを作成するクラス(factory)を持っています。そのオブジェクトを検証したら、それが「新しい」場合は保存したり、上のように既存のイベントを更新するために使用することができます。入力が単純​​で、単純な検証だけが必要な場合は、この極端な状態にする必要はありません。入力を常に検証するようにしてください。 – rojoca

+0

あなたの助けを借りて、私はDoctrine 2の最大の問題を克服することができました。私は本当にこれに悩まされていました。どうもありがとう! –

1

新しい答え

、あなたが持っているべきではありません。

@ManyToOne(targetEntity="User", inversedBy="countries") 

代わりinversedBy = "ID" の?

初期答え

削除カスケードとしてエンティティに国フィールドを設定する必要があります。例えば、双方向の1に多くの関係:

class Entity 
{ 
    /** 
    * 
    * @OneToMany(targetEntity="Country", mappedBy="entity", cascade={"remove"}) 
    */ 
    private $countries; 
} 

この方法で、あなたのエンティティを保存するとき、教義にも(例えば国など)エンティティに添付のコレクションに、変更を保存します。それ以外の場合は、削除する国を明示的に削除する必要があります。

$this->em()->remove($aCountry); 

これは、永続化、マージ、および切り離し操作にも有効です。詳細情報here

+0

@faken編集内容を確認します。これはすでに提案したとおりに設定されていますが、動作しません。 –

+0

こんにちは@ la_f0ka、私の編集を参照してください。 – faken

+0

@fakenよく私はそれも試みましたが、私はまだこれらの気になる国を取り除かないようです。 –

関連する問題