1

I have Budget, BudgetItem and Product entities. A Budget has a BudgetItem list, which has one or more Products. I am trying to remove a list of these previously added products following the this tutorial. When I try to remove an existing Product from the BudgetItem list, I can see that the total price of my Budget has decreased the total amount for that specific Product I have deleted, but it is not removed from the list, in the Budget entity.

First, let me show you their relationship:

Budget:

/**
 * @var integer
 * 
 * @ORM\OneToMany(targetEntity="BudgetItem", mappedBy="budget", cascade={"persist"}, orphanRemoval=true)
 */
private $items;

BudgetItem:

/**
 * @ORM\ManyToOne(targetEntity="Product")
 * @ORM\JoinColumn(nullable=false)
 */
private $product;

/**
 * @ORM\ManyToOne(targetEntity="Budget", inversedBy="items")
 * @ORM\JoinColumn(nullable=false)
 */
private $budget;

Now, the editAction from my BudgetController, doing the operation, according to the documentation:

public function editAction($id, Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $budget = $em->getRepository('CDGBundle:Budget')->find($id);

    $products = new ArrayCollection();

    foreach ($budget->getItems() as $item) {
        $products->add($item);
    }

    $form = $this->createForm(BudgetType::class, $budget);
    $form->handleRequest($request);

    if ($form->isValid()) {
        if ($this->get('cdg.budget_updater')->updateProductQtd($budget)) {
            // Here \/
            foreach ($products as $product) {
                if (!$budget->getItems()->contains($product)) {
                    $product->getBudget()->removeItem($product);
                    $em->persist($product);
                }
            }
            // Here /\

            $this->get('cdg.budget_updater')->updatePaymentDates($budget);
            $this->addFlash('notice', 'Orçamento de \'' . $budget->getCustomer() . '\' alterado com sucesso');
        } else {
            $this->addFlash('notice', 'Material(is) esgotado(s). Reveja o seu estoque.');
        }

        return $this->redirectToRoute('budgets');
    }

    return $this->render('budget/edit.html.twig', array(
        'form' => $form->createView(),
        'title' => 'Editar orçamento de ' . $budget->getCustomer()
    ));
}
GabrielMF
  • 31
  • 1
  • 6
  • You should call `$em->flush()` to actually perform the changes. Persisting only adds the entity to a queue. – Artamiel Jan 14 '16 at 08:31
  • @Artamiel Success! Not only this, but I had to remove the `foreach` from inside of the `updateProductQtd`. I thought I did not had to because inside of these methods from these services I already have a `flush`. – GabrielMF Jan 14 '16 at 14:20

1 Answers1

1

I had to remove the foreach loop from inside of updateProductQtd() method and add $em->flush(), as @Artamiel said, after the loop:

if ($form->isValid()) {
    foreach ($products as $product) {
        if (!$budget->getItems()->contains($product)) {
            $product->getBudget()->removeItem($product);
            $em->persist($product);
        }
    }
    $em->flush();

    if ($this->get('cdg.budget_updater')->updateProductQtd($budget)) {
        $this->get('cdg.budget_updater')->updatePaymentDates($budget);
        $this->addFlash('notice', 'Orçamento de \'' . $budget->getCustomer() . '\' alterado com sucesso');
    } else {
        $this->addFlash('notice', 'Material(is) esgotado(s). Reveja o seu estoque.');
    }

    return $this->redirectToRoute('budgets');
}
GabrielMF
  • 31
  • 1
  • 6