В Symfony - обновление нескольких записей

каков наилучший способ обновления нескольких записей в базе данных с помощью doctrine, 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();

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

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

3 ответов


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

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

$em->flush();

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


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

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