2012-01-06 12 views
7

Jaki jest najlepszy sposób aktualizacji wielu rekordów w bazie danych za pomocą doktryny, symfony2?Symfony - aktualizacja wielu rekordów

Otrzymuję tablicę identyfikatorów rekordów, które muszę zaktualizować.
Chcę przypisać do każdego rekordu jego indeks z odebranej tablicy do kolumny show_order. więc jeśli otrzyma tablicy $ array = array (22, 1, 5, 10), a następnie chcę zrobić

$i = 0; 
foreach($array as $a) { 
    $record = $this->getDoctrine->getRepository('AcmeBundle:SomeEntity')->findOneById($a); 
    if ($record != null) $record->setOrder($i++); 
} 
$this->getDoctrine()->getEntityManager()->flush(); 

ale to straszny sposób, bo dla każdego rekordu zrobić dobrać, więc liczba zapytań jest Na).

Jak to zrobić lepiej?

+0

Mam na razie jeden pomysł: uzyskać wszystkie rekordy, sprawdzić, która kolejność się zmieniła i zaktualizować tylko je. Ale nie czuję się usatysfakcjonowany z powodu tego rozwiązania. Więc zrobi jedno SELECT, aby uzyskać wszystkie rekordy, kilka wybranych (aby uzyskać obiekty encji) i kilka aktualizacji (lub może jeden, ponieważ myślę, że aktualizacja jest wywoływana po flush()). –

+0

Jeśli nie ma dobrego rozwiązania przy użyciu doktryny 2 może powinienem to zrobić w prostym PHP i użyć CASE WHEN ... THEN ... w kwerendzie sql? –

Odpowiedz

6

Coś ...

foreach ($repo->findById($ids) as $obj) { 
    $obj->setOrder(array_search($obj->getId(), $ids)); 
} 

$em->flush(); 
+0

wydaje mi się miła - jedna wybierz, jedna aktualizacja. Całkowicie zapomniałem, że mogę przekazać tablicę jako argument w findById. :) –

+3

Właśnie zaimplementowałem to w moim projekcie symfony i od oglądania app/dev.log to robi jedną wybierz i jedną aktualizację na rekord - nie jedna aktualizacja – semateos

6

Jako pierwszą opcję należy rozważyć Batch Processing. Jeśli z jakiegoś powodu nie jest to możliwe, drugą opcją jest zwykły SQL, prawdopodobnie poprzez DBAL.

+0

bardzo przydatne rzeczy, dzięki. –

0

Więc to jest nadal 0 (N), ale to 1n zamiast 2n. Aby uniknąć niepotrzebnych wybiera, ja rozwiązać ten problem za pomocą custom repository class i doktryny Query Builder tak:

namespace BRS\PageBundle\Repository; 

use Doctrine\ORM\EntityRepository; 

class ContentRepository extends EntityRepository 
{ 
    public function reorder($content) 
    {  
     $em = $this->getEntityManager(); 

     $count = 0; 

     foreach($content as $i => $content_id){ 

      $q = $em->createQuery('update BRSPageBundle:Content c set c.display_order = ?1 where c.id = ?2') 
        ->setParameter(1, $i) 
        ->setParameter(2, $content_id); 

      $count += $q->execute(); 
     } 

     return $count; 
    } 
} 

następnie powiedzenia masz tablicę identyfikatorów treści w kolejności tak:

$content = array(23,12,8,4); 

Następnie możesz zaktualizować zamówienie ze swojego kontrolera po prostu:

$count = $this->getRepository('BRSPageBundle:Content')->reorder($content); 
Powiązane problemy