如何使用Doctrine2 getScheduledEntityUpdates()

时间:2015-11-08 02:09:27

标签: symfony doctrine-orm sql-update

BudgetItemManyToOneBudgetProduct相关联。以下是3个实体:

BudgetItem

<?php

namespace CDGBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use CDGBundle\Entity\Product;

/**
 * BudgetItem
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="CDGBundle\Entity\Repository\BudgetItemRepository")
 * @ORM\HasLifecycleCallbacks
 */
class BudgetItem
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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

    /**
     * @var string
     *
     * @ORM\Column(name="price", type="decimal", scale=2)
     */
    private $price;

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

    /**
     * To String
     * 
     * @return string
     */
    public function __toString()
    {
        return $this->getProduct()->getName();
    }

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

    /**
     * Set budget
     *
     * @param integer $budget
     *
     * @return BudgetItem
     */
    public function setBudget(Budget $budget)
    {
        $this->budget = $budget;

        return $this;
    }

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

    /**
     * Set product
     *
     * @param integer $product
     *
     * @return BudgetItem
     */
    public function setProduct(Product $product = null)
    {
        $this->product = $product;

        return $this;
    }

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

    /**
     * Set meters
     *
     * @param integer $meters
     *
     * @return BudgetItem
     */
    public function setMeters($meters)
    {
        $this->meters = $meters;

        return $this;
    }

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

    /**
     * Set price
     *
     * @param string $price
     *
     * @return BudgetItem
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

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

    /**
     * @return integer;
     */
    public function decreaseProductMeters()
    {
        return $this->getProduct()->getMeters() - $this->getMeters();
    }

    /**
     * @ORM\PrePersist
     */
    public function onPreEvents()
    {
        $this->getProduct()->setMeters($this->decreaseProductMeters());
    }

    public function onFlush(\Doctrine\ORM\Event\OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        foreach ($uow->getScheduledEntityUpdates() as $entity) {
            $entity->getProduct();
            $em->persist($entity);
            $uow->recomputeSingleEntityChangeSet($em->getClassMetadata(get_class($entity)), $entity);
        }
    }
}

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

Product

<?php

namespace CDGBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use CDGBundle\Entity\ProductType;

/**
 * Product
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="CDGBundle\Entity\Repository\ProductRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Product
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var string
     * 
     * @ORM\ManyToOne(targetEntity="ProductType")
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     */
    private $type;

    /**
     * @var string
     *
     * @ORM\Column(name="price", type="decimal", scale=2)
     */
    private $price;

    /**
     * @var integer
     * 
     * @ORM\Column(name="meters", type="integer", nullable=true)
     */
    private $meters;

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

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

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

    /**
     * To String
     * 
     * @return string
     */
    public function __toString()
    {
        return $this->name;
    }

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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Product
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set type
     *
     * @param \CDGBundle\Entity\ProductType $type
     *
     * @return Product
     */
    public function setType(ProductType $type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * Get type
     *
     * @return \CDGBundle\Entity\ProductType
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Set price
     *
     * @param string $price
     *
     * @return Product
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

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

    /**
     * Set meters
     *
     * @param integer $meters
     *
     * @return Product
     */
    public function setMeters($meters)
    {
        $this->meters = $meters;

        return $this;
    }

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

    /**
     * Set description
     *
     * @param string $description
     *
     * @return Product
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

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

        return $this;
    }

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

ProductBudget内的集合表单。它列出了在注册新预算时要选择的所有注册产品。我有所有必要的JavaScript和宏来显示表单。

在编辑现有meters时,我需要更新Product实体的Budget总金额。我在onFlush内有一个BudgetItem方法:

public function onFlush(\Doctrine\ORM\Event\OnFlushEventArgs $args)
{
    $em = $args->getEntityManager();
    $uow = $em->getUnitOfWork();

    foreach ($uow->getScheduledEntityUpdates() as $entity) {
        $entity->getItems();
        $em->persist($entity);
        $uow->recomputeSingleEntityChangeSet($em->getClassMetadata(get_class($entity)), $entity);
    }
}

现在这是我的问题。我不知道在foreach方法中要做什么。我需要像在PrePersist方法中那样做,但是我得到了不同的错误。

在循环内部,如果我$entity->getItems(),我收到错误:

  

尝试调用名为&#34; getItems&#34;的未定义方法。类&#34; CDGBundle \ Entity \ BudgetItem&#34;。

如果我$entity->getProduct(),则错误:

  

尝试调用名为&#34; getProduct&#34;的未定义方法。类&#34; CDGBundle \ Entity \ Budget&#34;。

为什么它会神奇地改变实体?为了上帝的缘故,有人帮助我。 Doctrine2有一个太复杂的更新事件。

1 个答案:

答案 0 :(得分:0)

在Doctrine监听器中,您始终需要检查实体的类,因为每个更新的项都存储在getScheduledEntityUpdates()方法中。

解决方案是测试更新的实体是否为预算实例:

foreach ($uow->getScheduledEntityUpdates() as $entity) {
    if ($entity instanceof Budget) {
        // $entity is a Budget entity
        // ... your code here
    }
}