2012-01-06 33 views
7

¿Cuál es la mejor manera de actualizar múltiples registros en la base de datos usando doctrine, symfony2?Symfony - actualizar múltiples registros

Recibo un conjunto de identificadores de registros que debo actualizar.
Quiero asignar a cada registro su índice de la matriz recibida a la columna show_order. Así que si recibo arreglo $ array = array (22, 1, 5, 10), entonces quiero hacer

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

pero es horrible manera, porque para cada registro que hago un SELECT, por lo que el número de consultas es En).

¿Cómo hacerlo mejor?

+0

Tengo por ahora una idea: obtener todos los registros, verificar qué orden ha cambiado y actualizarlos solo. Pero no me siento satisfecho por esa solución. Así que hará un SELECCIONAR para obtener todos los registros, pocas selecciones (para obtener objetos de entidad) y algunas actualizaciones (o tal vez una, porque creo que la actualización se invoca después de flush()). –

+0

Si no hay una buena solución usando doctrine2 quizás debería hacerlo en PHP claro y usar CASE WHEN ... THEN ... in sql query? –

Respuesta

6

Algo así como ...

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

$em->flush(); 
+0

me parece bien: una selección, una actualización. Me olvidé por completo de que puedo pasar array como argumento en findById. :) –

+3

Acabo de implementar esto en mi proyecto symfony y al mirar la aplicación/dev.log hace una selección y una actualización por registro, no una actualización – semateos

6

Como primera opción, debe considerar Batch Processing. Si eso no es viable para usted por alguna razón, la segunda opción es ir con SQL simple, probablemente a través de DBAL.

+0

cosas bastante útiles, gracias. –

0

Así que esto sigue siendo 0 (n), pero es 1n en lugar de 2n. Para evitar los selecciona innecesarios, he resuelto este problema utilizando un custom repository class y la doctrina generador de consultas de este 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; 
    } 
} 

continuación, supongamos que tiene una tabla de id de contenido con el fin de esta manera:

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

Entonces usted puede actualizar el orden de su controlador bastante simple:

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