Doctrine PrePersist不为自己的实体工作

时间:2015-10-27 00:31:38

标签: symfony orm doctrine-orm

我有CustomerProductBudgetBudgetItem个实体。 Budget @ORM \ ManyToOne Customer @ORM \ OneToMany BudgetItem相关联。 BudgetItem @ORM \ ManyToOne 相关联为ProductBudget

BudgetItem内部,有一种方法可以计算之前选择的Products的总价,然后保存到budget_itens表中。更新项目时,代码将被执行并再次成功保存到数据库中。方法如下:

public function calculateTotalPrice()
{
    return $this->getProduct()->getPrice() * $this->getMeters();
}

/**
 * @ORM\PrePersist
 */
public function onPreEvents()
{
    $this->setPrice($this->calculateTotalPrice());
}

现在,我有Budget

/**
 * @return \DateTime
 */
public function generateNextPaymentDate()
{
    if ($this->getStartsAt() !== null) {
        $date = new \DateTime($this->getStartsAt()->format('Y-m-d'));
        return $date->add(new \DateInterval('P' . $this->getCheckFor() . 'D'));
    }
}

/**
 * @return decimal
 */
public function calculateTotalBudgetPrice()
{
    $totalBudgetPrice = 0;

    foreach ($this->getItems() as $item) {
        $totalBudgetPrice += $item->getPrice();
    }

    return $totalBudgetPrice;
}

/**
 * @return decimal
 */
public function calculateInstallmentRatePrice()
{
    return $this->calculateTotalBudgetPrice() / $this->getInstallmentRate();
}

/**
 * @ORM\PrePersist
 */
public function onPreEvents()
{
    $this->setNextPaymentDate($this->generateNextPaymentDate());
    $this->setInstallmentRatePrice($this->calculateInstallmentRatePrice());
    $this->setTotalBudgetPrice($this->calculateTotalBudgetPrice());
}

编辑 Budget后,这些方法都没有将结果保留在数据库中。如果我理解得很好,似乎Doctrine2不会更新其他相关实体,但这些字段属于此实体。还有什么我需要做的?

修改

BudgetController,我坚持并冲洗。

<?php

namespace CDGBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use CDGBundle\Entity\Budget;
use CDGBundle\Form\BudgetType;

class BudgetController extends Controller
{
    /**
     * Lista todos os orçamentos
     */
    public function indexAction()
    {
        return $this->render('budget/index.html.twig', array(
            'budgets' => $this->getDoctrine()->getRepository('CDGBundle:Budget')->findAll(),
            'title' => 'Lista de Orçamentos'
        ));
    }

    /**
     * Adicionar um novo orçamento
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function addAction(Request $request)
    {
        $budget = new Budget();
        $form = $this->createForm(new BudgetType(), $budget);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($budget);
            $em->flush();

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

        return $this->render('budget/add.html.twig', array(
            'form' => $form->createView(),
            'title' => 'Novo Orçamento'
        ));
    }

    /**
     * Exibe os detalhes do orçamento selecionado
     * 
     * @param integer $id
     * @return Budget
     */
    public function showAction($id)
    {
        $budget = $this->getDoctrine()->getRepository('CDGBundle:Budget')->find($id);

        return $this->render('budget/show.html.twig', array(
            'budget' => $budget,
            'title' => 'Dados do orçamento #' . $budget->getId()
        ));
    }

    /**
     * Edita as informações do orçamento selecionado
     * 
     * @param integer $id
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editAction($id, Request $request)
    {
        $budget = $this->getDoctrine()->getRepository('CDGBundle:Budget')->find($id);
        $form = $this->createForm(new BudgetType(), $budget);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($budget);
            $em->flush();

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

        return $this->render('budget/edit.html.twig', array(
            'form' => $form->createView(),
            'title' => 'Editar orçamento #' . $budget->getId()
        ));
    }

    /**
     * Deleção de um orçamento
     * 
     * @param integer $id
     * @return Budget
     */
    public function deleteAction($id)
    {
        $budget = $this->getDoctrine()->getRepository('CDGBundle:Budget')->find($id);
        $em = $this->getDoctrine()->getManager();
        $em->remove($budget);
        $em->flush();

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

我的Budget课程:

<?php

namespace CDGBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use CDGBundle\Entity\Customer;
use CDGBundle\Entity\BudgetItem;

/**
 * Budget
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="CDGBundle\Entity\Repository\BudgetRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Budget
{

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     * 
     * @ORM\ManyToOne(targetEntity="Customer", inversedBy="budgets")
     */
    private $customer;

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

    /**
     * @var string
     *
     * @ORM\Column(name="address", type="string", length=255)
     */
    private $address;

    /**
     * @var integer
     *
     * @ORM\Column(name="installment_rate", type="integer")
     */
    private $installmentRate;

    /**
     * @var integer
     *
     * @ORM\Column(name="check_for", type="integer")
     */
    private $checkFor;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="starts_at", type="datetime", nullable=true)
     */
    private $startsAt;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="deadline", type="datetime", nullable=true)
     */
    private $deadline;

    /**
     * @var string
     * 
     * @ORM\Column(name="is_approved", type="string", length=1, nullable=true)
     */
    private $isApproved;

    /**
     * @var string
     * 
     * @ORM\Column(name="has_started", type="string", length=1, nullable=true)
     */
    private $hasStarted;

    /**
     * @var decimal
     * 
     * @ORM\Column(name="installment_rate_price", type="decimal", scale=2, nullable=true)
     */
    private $installmentRatePrice;

    /**
     * @var decimal
     * 
     * @ORM\Column(name="total_budget_price", type="decimal", scale=2, nullable=true)
     */
    private $totalBudgetPrice;

    /**
     * @var \DateTime
     * 
     * @ORM\Column(name="next_payment_date", type="datetime", nullable=true)
     */
    private $nextPaymentDate;

    /**
     * @var string
     * 
     * @ORM\Column(name="is_paid", type="string", length=1)
     */
    private $isPaid;

    /**
     * @var string
     *
     * @ORM\Column(name="obs", type="text", nullable=true)
     */
    private $obs;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created_at", type="datetime")
     */
    private $createdAt;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->items = new ArrayCollection();
        $this->createdAt = new \DateTime();
        $this->isPaid = 'n';
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set address
     *
     * @param string $address
     *
     * @return Budget
     */
    public function setAddress($address)
    {
        $this->address = $address;

        return $this;
    }

    /**
     * Get address
     *
     * @return string
     */
    public function getAddress()
    {
        return $this->address;
    }

    /**
     * Set installmentRate
     *
     * @param integer $installmentRate
     *
     * @return Budget
     */
    public function setInstallmentRate($installmentRate)
    {
        $this->installmentRate = $installmentRate;

        return $this;
    }

    /**
     * Get installmentRate
     *
     * @return integer
     */
    public function getInstallmentRate()
    {
        return $this->installmentRate;
    }

    /**
     * Set checkFor
     *
     * @param integer $checkFor
     *
     * @return Budget
     */
    public function setCheckFor($checkFor)
    {
        $this->checkFor = $checkFor;

        return $this;
    }

    /**
     * Get checkFor
     *
     * @return integer
     */
    public function getCheckFor()
    {
        return $this->checkFor;
    }

    /**
     * Set startsAt
     *
     * @param \DateTime $startsAt
     *
     * @return Budget
     */
    public function setStartsAt($startsAt)
    {
        $this->startsAt = $startsAt;

        return $this;
    }

    /**
     * Get startsAt
     *
     * @return \DateTime
     */
    public function getStartsAt()
    {
        return $this->startsAt;
    }

    /**
     * Set deadline
     *
     * @param \DateTime $deadline
     *
     * @return Budget
     */
    public function setDeadline($deadline)
    {
        $this->deadline = $deadline;

        return $this;
    }

    /**
     * Get deadline
     *
     * @return \DateTime
     */
    public function getDeadline()
    {
        return $this->deadline;
    }

    /**
     * Set isApproved
     *
     * @param string $isApproved
     *
     * @return Budget
     */
    public function setIsApproved($isApproved)
    {
        $this->isApproved = $isApproved;

        return $this;
    }

    /**
     * Get isApproved
     *
     * @return string
     */
    public function getIsApproved()
    {
        return $this->isApproved;
    }

    /**
     * Set hasStarted
     *
     * @param string $hasStarted
     *
     * @return Budget
     */
    public function setHasStarted($hasStarted)
    {
        $this->hasStarted = $hasStarted;

        return $this;
    }

    /**
     * Get hasStarted
     *
     * @return string
     */
    public function getHasStarted()
    {
        return $this->hasStarted;
    }

    /**
     * Set installmentRatePrice
     *
     * @param string $installmentRatePrice
     *
     * @return Budget
     */
    public function setInstallmentRatePrice($installmentRatePrice)
    {
        $this->installmentRatePrice = $installmentRatePrice;

        return $this;
    }

    /**
     * Get installmentRatePrice
     *
     * @return string
     */
    public function getInstallmentRatePrice()
    {
        return $this->installmentRatePrice;
    }

    /**
     * Set totalBudgetPrice
     *
     * @param string $totalBudgetPrice
     *
     * @return Budget
     */
    public function setTotalBudgetPrice($totalBudgetPrice)
    {
        $this->totalBudgetPrice = $totalBudgetPrice;

        return $this;
    }

    /**
     * Get totalBudgetPrice
     *
     * @return string
     */
    public function getTotalBudgetPrice()
    {
        return $this->totalBudgetPrice;
    }

    /**
     * Set nextPaymentDate
     *
     * @param \DateTime $nextPaymentDate
     *
     * @return Budget
     */
    public function setNextPaymentDate($nextPaymentDate)
    {
        $this->nextPaymentDate = $nextPaymentDate;

        return $this;
    }

    /**
     * Get nextPaymentDate
     *
     * @return \DateTime
     */
    public function getNextPaymentDate()
    {
        return $this->nextPaymentDate;
    }

    /**
     * Set isPaid
     *
     * @param string $isPaid
     *
     * @return Budget
     */
    public function setIsPaid($isPaid)
    {
        $this->isPaid = $isPaid;

        return $this;
    }

    /**
     * Get isPaid
     *
     * @return string
     */
    public function getIsPaid()
    {
        return $this->isPaid;
    }

    /**
     * Set obs
     *
     * @param string $obs
     *
     * @return Budget
     */
    public function setObs($obs)
    {
        $this->obs = $obs;

        return $this;
    }

    /**
     * Get obs
     *
     * @return string
     */
    public function getObs()
    {
        return $this->obs;
    }

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     *
     * @return Budget
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set customer
     *
     * @param Customer $customer
     *
     * @return Budget
     */
    public function setCustomer(Customer $customer = null)
    {
        $this->customer = $customer;

        return $this;
    }

    /**
     * Get customer
     *
     * @return Customer
     */
    public function getCustomer()
    {
        return $this->customer;
    }

    /**
     * Add item
     *
     * @param BudgetItem $item
     *
     * @return Budget
     */
    public function addItem(BudgetItem $item)
    {
        $item->setBudget($this);
        $this->items[] = $item;

        return $this;
    }

    /**
     * Remove item
     *
     * @param BudgetItem $item
     */
    public function removeItem(BudgetItem $item)
    {
        $this->items->removeElement($item);
    }

    /**
     * Get items
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getItems()
    {
        return $this->items;
    }

    /**
     * @return \DateTime
     */
    public function generateNextPaymentDate()
    {
        if ($this->getStartsAt() !== null) {
            $date = new \DateTime($this->getStartsAt()->format('Y-m-d'));
            return $date->add(new \DateInterval('P' . $this->getCheckFor() . 'D'));
        }
    }

    /**
     * @return decimal
     */
    public function calculateTotalBudgetPrice()
    {
        $totalBudgetPrice = 0;

        foreach ($this->getItems() as $item) {
            $totalBudgetPrice += $item->getPrice();
        }

        return $totalBudgetPrice;
    }

    /**
     * @return decimal
     */
    public function calculateInstallmentRatePrice()
    {
        return $this->calculateTotalBudgetPrice() / $this->getInstallmentRate();
    }

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function onPreEvents()
    {
        $this->setNextPaymentDate($this->generateNextPaymentDate());
        $this->setInstallmentRatePrice($this->calculateInstallmentRatePrice());
        $this->setTotalBudgetPrice($this->calculateTotalBudgetPrice());
    }
}

EDIT2

我刚刚意识到@ORM \ PreUpdate正在运行但仅适用于我的nextPaymentDate。我在collection中有一个Budget,在ProductController内有一种收集产品信息的方法:

<?php

namespace CDGBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use CDGBundle\Entity\Product;
use CDGBundle\Form\ProductType;
use Symfony\Component\HttpFoundation\JsonResponse;

class ProductController extends Controller
{
    /**
     * Lista todos os materials
     */
    public function indexAction()
    {
        return $this->render('product/index.html.twig', array(
            'products' => $this->getDoctrine()->getRepository('CDGBundle:Product')->findAll(),
            'title' => 'Lista de Materiais'
        ));
    }

    /**
     * Adicionar um novo material
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function addAction(Request $request)
    {
        $product = new Product();
        $form = $this->createForm(new ProductType(), $product);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($product);
            $em->flush();

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

        return $this->render('product/add.html.twig', array(
            'form' => $form->createView(),
            'title' => 'Novo Material'
        ));
    }

    /**
     * Exibe os detalhes do material selecionado
     * 
     * @param integer $id
     * @return Product
     */
    public function showAction($id)
    {
        $product = $this->getDoctrine()->getRepository('CDGBundle:Product')->find($id);

        return $this->render('product/show.html.twig', array(
            'product' => $product,
            'title' => 'Dados do material #' . $product->getId()
        ));
    }

    /**
     * Edita as informações do material selecionado
     * 
     * @param integer $id
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editAction($id, Request $request)
    {
        $product = $this->getDoctrine()->getRepository('CDGBundle:Product')->find($id);
        $form = $this->createForm(new ProductType(), $product);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->merge($product);
            $em->flush();

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

        return $this->render('product/edit.html.twig', array(
            'form' => $form->createView(),
            'title' => 'Editar material #' . $product->getId() . ' - ' . $product->getName()
        ));
    }

    /**
     * Deleção de um material
     * 
     * @param integer $id
     * @return Product
     */
    public function deleteAction($id)
    {
        $product = $this->getDoctrine()->getRepository('CDGBundle:Product')->find($id);
        $em = $this->getDoctrine()->getManager();
        $em->remove($product);
        $em->flush();

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

    /**
     * Traz as informações do material selecionado na criação do orçamento.
     * 
     * @param Request $request
     * @return JsonResponse
     */
    public function getProductInfoAction(Request $request)
    {
        $id = $request->query->get('id');
        $product = $this->getDoctrine()->getRepository('CDGBundle:Product')->find($id);

        if ($request->query->get('format') == 'json') {
            $data = array(
                'id' => $product->getId(),
                'name' => $product->getName(),
                'price' => $product->getPrice(),
                'meters' => $product->getMeters(),
                'description' => $product->getDescription(),
                'created_at' => $product->getCreatedAt()->format('d-m-Y H:i'),
            );

            return new JsonResponse($data, 200, array(
                'Content-type' => 'application/json'
            ));
        }
    }
}

编辑时似乎存在问题,因为我遇到了一些错误,比如我在点击编辑后更改了一些产品信息,就好像根本没有选定的产品。

1 个答案:

答案 0 :(得分:0)

请参阅documentation,特别是prePersist

  

应该注意,此事件仅在初始时触发   坚持实体(即未在未来更新时触发)。

所以你还需要添加一个preUpdate监听器。