GabrielMF
GabrielMF

Reputation: 31

Symfony - Items from an ArrayColletion is removed, but is still shown in the list

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

Upvotes: 1

Views: 39

Answers (1)

GabrielMF
GabrielMF

Reputation: 31

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

Upvotes: 1

Related Questions