2012-01-06 3 views
7

Qual è il modo migliore per aggiornare più record nel database usando doctrine, symfony2?Symfony - aggiorna più record

Ricevo array di ID di record che devo aggiornare.
Desidero assegnare a ciascun record il suo indice dalla matrice ricevuta alla colonna show_order. Quindi, se io ricevo gamma $ array = array (22, 1, 5, 10), poi voglio fare

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

ma è modo orribile, perché per ogni record che faccio una SELECT, quindi numero di query è Sopra).

Come fare meglio?

+0

Per ora ho un'idea: ottenere tutti i record, controllare quale ordine è cambiato e aggiornarli solo. Ma non mi sento soddisfatto a causa di quella soluzione. Quindi eseguirà un SELECT per ottenere tutti i record, pochi seleziona (per ottenere oggetti entità) e pochi aggiornamenti (o forse uno, perché penso che l'aggiornamento sia invocato dopo flush()). –

+0

Se non c'è una buona soluzione con doctrine2 forse dovrei farlo in chiaro PHP e usare CASE QUANDO ... THEN ... in sql query? –

risposta

6

Qualcosa di simile ...

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

$em->flush(); 
+0

mi sembra bello - un solo aggiornamento, uno. Ho completamente dimenticato che posso passare array come argomento in findById. :) –

+3

L'ho appena implementato nel mio progetto symfony e dal guardare l'app/dev.log ne viene eseguito uno solo e uno per record - non un aggiornamento – semateos

6

Come prima opzione, è necessario considerare Batch Processing. Se per qualche motivo non è fattibile per te, la seconda opzione è quella di utilizzare semplicemente SQL, probabilmente tramite DBAL.

+0

cose abbastanza utili, grazie. –

0

Quindi questo è ancora 0 (n), ma è 1n piuttosto che 2n. Per evitare gli seleziona inutili, ho risolto questo problema utilizzando un custom repository class ed il generatore di query dottrina in questo modo:

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; 
    } 
} 

poi dire di avere una matrice di ID di contenuto in modo simile a questo:

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

Poi è possibile aggiornare l'ordine dal controller semplicemente:

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