Как получить исходные данные перед изменением? - PullRequest
0 голосов
/ 17 мая 2018

У меня есть простое действие edit для Product Entity.Он отлично работает в оригинальной, стандартной форме, но мне нужно провести специальную проверку, прежде чем я сохраню Product после редактирования.Продукт имеет несколько цен в отдельных полях.В проекте у меня есть общая настройка «минимальная цена» на продукты.Прежде чем сохранить продукт после редактирования, я хочу сравнить цены с «минимальной ценой».Я делаю это так:

public function editAction(Request $request, Product $pr1, UserInterface $op)
{
    // 1
    $pr_original = $this->getDoctrine()->getRepository(Product::class)->getProductById($pr1->getId());

    $form = $this->createForm('AppBundle\Form\ProductType', $product);
    $form->handleRequest($request); 

    if($form->isSubmitted() && $form->isValid())
    {
        // 2
        $em = $this->getDoctrine()->getManager();
        $em->persist($product);
        $em->flush();
    }

    return $this->redirect(path('product_list'));
}

Во 2 есть место, где я сравниваю значения.Но проблема в том ... Я не могу получить исходные значения для сравнения.В 1 я хочу получить оригинальный продукт, но он будет $pr_original с уже измененными значениями!Это странно, потому что я вижу непосредственно в базе данных, что объект все еще имеет исходные значения.Поэтому я думаю, что Symfony не делает новый запрос к базе данных.Так что же теперь делать?Как заставить Symfony достать мне оригинальный предмет?

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Вы должны понять, что Доктрина делает для вас.ORM не являются создателями простых запросов.Они отображают состояние вашей базы данных на объекты в памяти, которые ваш код понимает и может работать с ними.

Итак, когда вы передаете форму, как вы делали, доктрина запрашивает объект и обновляет значения всостояние объектов.Таким образом, после обработки формы ваш объект уже имеет другое состояние, чем состояние в базе данных.Единственное, что осталось сделать для доктрины - это сохранить и сбросить, или, другими словами, зарегистрировать, что изменение состояния будет отражено в базе данных (сохраниться), и фактически изменить значения в БД (очистить).

Есливы запрашиваете объект, который является «управляемым» (имеется в виду, что он уже был запрошен и находится в памяти доктрины), тогда доктрина выдаст вам объект в памяти, ради эффективности.Он не будет запрашивать БД для этого снова.Вы можете вызвать метод обновления в диспетчере для обновления состояния объекта из базы данных, но это будет означать потерю состояния, которое еще не было сохранено, например, данные, поступающие из вашей формы.

В этом случае я бы порекомендовал либо создать событие формы, которое будет сравнивать значение, которое пользователь написал, со значением вашей системы.Событие формы должно быть preSetData, поскольку вы хотите провести сравнение до того, как ваша сущность будет обновлена ​​новыми данными.Вы можете проверить больше здесь здесь

Другой альтернативой является создание пользовательского ограничения проверки.Если ваше системное значение является фиксированным, вы можете проверить его с помощью специального валидатора.Или даже с обычными сравнительными ограничениями .

Надеюсь, эта информация поможет!

0 голосов
/ 17 мая 2018

Спасибо за @Cerad - ваш комментарий - решение:

В Doctrine есть то, что известно как кэш единицы работы.Каждый раз, когда вы делаете запрос с одним и тем же идентификатором, вы всегда возвращаете один и тот же объект.Подумайте о клонировании вашей сущности:

$prOriginal = clone $pr1;

Это хорошо работает для меня.

...