エンティティコレクションを外部ソースと同期する必要があるという同様の問題がありました。しかし、私の問題には、追加だけでなく、更新と削除も必要でした。コードを使用してArrayCollectionを別の配列と比較し、その違いに基づいてCRUDメソッドaddを呼び出しました。ドキュメントからわかる限り、doctrineはこれをネイティブに処理しません。平均パフォーマンスは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);
}
);