Symfony - обновить несколько записей - PullRequest
9 голосов
/ 07 января 2012

Каков наилучший способ обновления нескольких записей в базе данных с использованием доктрины symfony2?

Я получаю массив идентификаторов записей, которые мне нужно обновить.
Я хочу присвоить каждой записи свой индекс из полученного массива в столбец show_order. Поэтому, если я получу массив $ array = array (22, 1, 5, 10), тогда я захочу сделать

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

но это ужасный способ, потому что для каждой записи я делаю один SELECT, поэтому количество запросов равно O (n).

Как это сделать лучше?

Ответы [ 3 ]

9 голосов
/ 07 января 2012

Что-то вроде ...

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

$em->flush();
7 голосов
/ 07 января 2012

В качестве первого варианта вы должны рассмотреть Пакетная обработка .Если это по какой-то причине вам не подходит, второй вариант - использовать простой SQL, возможно, через DBAL .

1 голос
/ 03 апреля 2012

Так что это все равно 0 (n), но это 1n, а не 2n. Чтобы избежать ненужных выборок, я решил эту проблему, используя пользовательский класс репозитория и конструктор запросов doctrine, например:

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

затем скажите, что у вас есть массив идентификаторов контента в следующем порядке:

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

Затем вы можете обновить заказ с вашего контроллера довольно просто:

$count = $this->getRepository('BRSPageBundle:Content')->reorder($content);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...