教义 PrePersist 不为自己的实体工作



我有CustomerProductBudgetBudgetItem实体。 BudgetCustomer@ORM\ManyToOne@ORM\OneToManyBudgetItem相关。 BudgetItemProductBudget相关的@ORM\ManyToOne

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

public function calculateTotalPrice()
{
    return $this->getProduct()->getPrice() * $this->getMeters();
}
/**
 * @ORMPrePersist
 */
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();
}
/**
 * @ORMPrePersist
 */
public function onPreEvents()
{
    $this->setNextPaymentDate($this->generateNextPaymentDate());
    $this->setInstallmentRatePrice($this->calculateInstallmentRatePrice());
    $this->setTotalBudgetPrice($this->calculateTotalBudgetPrice());
}

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

编辑

BudgetController,我坚持和冲洗的地方。

<?php
namespace CDGBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use CDGBundleEntityBudget;
use CDGBundleFormBudgetType;
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 SymfonyComponentHttpFoundationRedirectResponse|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 SymfonyComponentHttpFoundationRedirectResponse|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 CDGBundleEntity;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineORMMapping as ORM;
use CDGBundleEntityCustomer;
use CDGBundleEntityBudgetItem;
/**
 * Budget
 *
 * @ORMTable()
 * @ORMEntity(repositoryClass="CDGBundleEntityRepositoryBudgetRepository")
 * @ORMHasLifecycleCallbacks
 */
class Budget
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var integer
     * 
     * @ORMManyToOne(targetEntity="Customer", inversedBy="budgets")
     */
    private $customer;
    /**
     * @var integer
     * 
     * @ORMOneToMany(targetEntity="BudgetItem", mappedBy="budget", cascade={"persist"})
     */
    private $items;
    /**
     * @var string
     *
     * @ORMColumn(name="address", type="string", length=255)
     */
    private $address;
    /**
     * @var integer
     *
     * @ORMColumn(name="installment_rate", type="integer")
     */
    private $installmentRate;
    /**
     * @var integer
     *
     * @ORMColumn(name="check_for", type="integer")
     */
    private $checkFor;
    /**
     * @var DateTime
     *
     * @ORMColumn(name="starts_at", type="datetime", nullable=true)
     */
    private $startsAt;
    /**
     * @var DateTime
     *
     * @ORMColumn(name="deadline", type="datetime", nullable=true)
     */
    private $deadline;
    /**
     * @var string
     * 
     * @ORMColumn(name="is_approved", type="string", length=1, nullable=true)
     */
    private $isApproved;
    /**
     * @var string
     * 
     * @ORMColumn(name="has_started", type="string", length=1, nullable=true)
     */
    private $hasStarted;
    /**
     * @var decimal
     * 
     * @ORMColumn(name="installment_rate_price", type="decimal", scale=2, nullable=true)
     */
    private $installmentRatePrice;
    /**
     * @var decimal
     * 
     * @ORMColumn(name="total_budget_price", type="decimal", scale=2, nullable=true)
     */
    private $totalBudgetPrice;
    /**
     * @var DateTime
     * 
     * @ORMColumn(name="next_payment_date", type="datetime", nullable=true)
     */
    private $nextPaymentDate;
    /**
     * @var string
     * 
     * @ORMColumn(name="is_paid", type="string", length=1)
     */
    private $isPaid;
    /**
     * @var string
     *
     * @ORMColumn(name="obs", type="text", nullable=true)
     */
    private $obs;
    /**
     * @var DateTime
     *
     * @ORMColumn(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 DoctrineCommonCollectionsCollection
     */
    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();
    }
    /**
     * @ORMPrePersist
     * @ORMPreUpdate
     */
    public function onPreEvents()
    {
        $this->setNextPaymentDate($this->generateNextPaymentDate());
        $this->setInstallmentRatePrice($this->calculateInstallmentRatePrice());
        $this->setTotalBudgetPrice($this->calculateTotalBudgetPrice());
    }
}

编辑2

我刚刚意识到@ORM\PreUpdate正在工作,但仅适用于我的nextPaymentDate。我在Budget有一个collectionProductController里面有一种收集产品信息的方法:

<?php
namespace CDGBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use CDGBundleEntityProduct;
use CDGBundleFormProductType;
use SymfonyComponentHttpFoundationJsonResponse;
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 SymfonyComponentHttpFoundationRedirectResponse|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 SymfonyComponentHttpFoundationRedirectResponse|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'
            ));
        }
    }
}
编辑

它时似乎有问题,因为我遇到了一些错误,比如如果我在单击编辑后更改了一些产品信息,就像根本没有选择产品一样。

请参阅文档,特别是prePersist

应该注意的是,此事件仅在初始时触发 实体的持久性(即它不会在将来的更新中触发(。

因此,您还需要添加一个预更新侦听器。

最新更新