2012-04-27 11 views
1

つまり、「php、mysql、doctrine2」というオブジェクトを表す文字列があります 私のデータベースにはすでに " php "と" doctrine2 "になります。 今、欠けているelemets(この場合はmysql)を追加する最良の方法が必要です。Doctrine2:コレクションの同期/既に存在している可能性のある複数の要素の追加

すべての要素に対してオブジェクトを作成し、persist/syncなどを使用するか、より良い方法がありますか?

とにかく、すべてのオブジェクトを新しいオブジェクト(単純な多対多の関係)に追加する必要があります。

私は何か提案がありましたら幸いです。

+0

1)タグで1つのクエリですべての既存のタグを探す2)ループを見つけます3)欠けているオブジェクトを作成して永続させる4)すべてのオブジェクトを含む別の配列を作成し、タグとして設定する。何が問題ですか? – meze

+0

@meze:問題は、共通の/簡単な作業のためにするのが大変なようだということです。私はコレクションやエンティティの状態などを持ってこれを行うために、よりスマートな "マージ"オプションがあるかもしれないと思った。 –

+0

各オブジェクトを手動で永続化することをスキップするリレーションシップに設定できるカスケード永続性があります。しかし、既存のタグと新しく作成されたタグの組み合わせが必要です。 – meze

答えて

2

1)配列

2)用のインサートを作成したデータセット

3)に存在しないタグを検出するための閉鎖とともにarray_filter使用に単一のクエリですべてのタグ名を引き出し新しいタグ

$currentTags = getCurrentTagsArray(); 
$newTags = explode(',', 'php,mysql,doctrine2'); 

$newTagsToSave = array_filter($currentTags, function($item) use ($newTags){ 
    if (in_array($item, $newTags)) 
    { 
     return false; 
    } 
    return true; 
}); 

それとも...

あなたはそれがhaの教義2のArrayCollectionのラッパー(\教義\共通\コレクション\ ArrayCollectionのを())を使用することができますフィルタメソッドとほぼ同じ実装です(まだクロージャを渡す必要があります)。

$myCollection->filter($closure); 
+0

ありがとう!それは私が前にしたことよりもずっと良くて簡単です。 –

0

エンティティコレクションを外部ソースと同期させなければならなかったのと同じ問題がありました。しかし、私の問題は追加だけでなく、更新と削除も必要でした。私は別の配列でArrayCollectionを比較するコードを使用し、CRUDメソッドを呼び出すと、その違いに基づいて追加されます。私がドキュメントから知る限り、教義はこれをネイティブに扱っていません。平均パフォーマンスはO(n)にする必要がありますが、いくらかのメモリが必要です。

/** 
* @param array $source - the array we are starting with 
* @param array $new - the array we want to end with 
* @param $fnHash - function used to determine object equality, not based on object id 
* @param $fnUpdate - function to perform update of existing object, takes current object and new object as params 
* @param $fnAdd - function to perform insert 
* @param $fnDelete - function to perform delete 
*/ 
public static function syncArrays(array $source, array $new, 
     $fnHash, $fnUpdate, $fnAdd, $fnDelete) 
{ 
    // make modifiable array copies mapped by hashes of the elements 

    $sourceKeys = array_map($fnHash, $source); 
    $hasKeys =count($sourceKeys) > 0; 
    $newarray = ($hasKeys) ? array_combine(array_map($fnHash, $new), $new) : $new; 
    if ($hasKeys) { // true => may have updates or deletes 
     $sourcearray = array_combine($sourceKeys, $source); 

     // updates 
     foreach ($sourceKeys as $hashkey) { 
      if (isset($sourcearray[$hashkey]) && isset($newarray[$hashkey])) { 
       $fnUpdate($sourcearray[$hashkey], $newarray[$hashkey]); 
       unset($sourcearray[$hashkey]); 
       unset($newarray[$hashkey]); 
      } 
     } 


     // deletes 
     foreach ($sourcearray as $entity) { 
      $fnDelete($entity); 
     } 
    } 
    //adds 
    foreach ($newarray as $entity) { 
     $fnAdd($entity); 
    } 
} 

私は(私の教義協会$ parentEntity-> getPaymentsを更新するために、それを呼び出す方法が)です:

ArrayHelper::syncArrays($parentEntity->getPayments()->toArray(), $newPayments, 
    function($entity) {return $a->getName();}, // hash function 
    function($current, $new) { 
     $current->setTotal($new->getTotal()); // update function 
    }, 
    function($a) use ($parent, $manager) { 
     $parent->addVendorPaymentObject($a); // add function 
     $manager->persist($a); 
    }, 
    function($a) use ($manager) { // delete function 
     $manager->remove($a); 
    } 
); 
関連する問題