我有一个PurchaseOrder实体,我有一个Payments实体。在PurchaseOrder实体内部,我正在尝试获取Payments.amountPaid的总和但是它不能按预期工作。理想情况下,$ allPaid应该具有每个PurchaseOrder的所有支付金额的总和。我正在学习本教程:enter link description here
这是我的PurchaseOrder实体:
class PurchaseOrder
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\OneToOne(targetEntity="RequestForEstimate", fetch="EAGER")
* @ORM\JoinColumn(name="request_id", referencedColumnName="request_id")
*/
private $request;
/**
* @ORM\OneToMany(targetEntity="Payment", mappedBy="purchaseOrder", orphanRemoval=true, cascade={"persist"}, fetch="EAGER")
*/
private $payments;
/**
* @var \DateTime
*
* @ORM\Column(name="create_time", type="datetime")
*/
private $createTime;
/**
* @var \DateTime
*
* @ORM\Column(name="update_time", type="datetime")
*/
private $updateTime;
/**
* @ORM\ManyToOne(targetEntity="PurchaseOrderStatus", cascade={"persist"})
*/
private $status;
/**
* @var \DateTime
*
* @ORM\Column(name="ship_date",type="datetime")
*/
private $shipDate;
private $allPaid = 0;
public function getAllPaid()
{
foreach ($this->payments as $payment) {
$this->allPaid += $payment->amountPaid();
}
return $this->allPaid;
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set createTime
*
* @param \DateTime $createTime
*
* @return PurchaseOrder
*/
public function setCreateTime($createTime)
{
$this->createTime = $createTime;
return $this;
}
/**
* Get createTime
*
* @return \DateTime
*/
public function getCreateTime()
{
return $this->createTime;
}
/**
* Set updateTime
*
* @param \DateTime $updateTime
*
* @return PurchaseOrder
*/
public function setUpdateTime($updateTime)
{
$this->updateTime = $updateTime;
return $this;
}
/**
* Get updateTime
*
* @return \DateTime
*/
public function getUpdateTime()
{
return $this->updateTime;
}
/**
* Set status
*
* @param integer $status
*
* @return PurchaseOrder
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* @return int
*/
public function getStatus()
{
return $this->status;
}
/**
* Set shipDate
*
* @param \DateTime $shipDate
*
* @return PurchaseOrder
*/
public function setShipDate($shipDate)
{
$this->shipDate = $shipDate;
return $this;
}
/**
* Get shipDate
*
* @return \DateTime
*/
public function getShipDate()
{
return $this->shipDate;
}
/**
* Set requestForEstimate
*
* @param \InboundBundle\Entity\RequestForEstimate $requestForEstimate
*
* @return PurchaseOrder
*/
public function setRequestForEstimate(\InboundBundle\Entity\RequestForEstimate $requestForEstimate = null)
{
$this->requestForEstimate = $requestForEstimate;
return $this;
}
/**
* Get requestForEstimate
*
* @return \InboundBundle\Entity\RequestForEstimate
*/
public function getRequestForEstimate()
{
return $this->requestForEstimate;
}
/**
* Set requestId
*
* @param \InboundBundle\Entity\RequestForEstimate $requestId
*
* @return PurchaseOrder
*/
// public function setRequest(\InboundBundle\Entity\RequestForEstimate $request = null)
// {
// $this->request = $request;
// $request->setRequestId($this);
// return $this;
// }
public function setPayments(Payment $payments = null)
{
$this->payments = $payments;
return $this;
}
/**
* Get requestId
*
* @return \InboundBundle\Entity\RequestForEstimate
*/
public function getRequest()
{
return $this->request;
}
/**
* Set request
*
* @param \InboundBundle\Entity\RequestForEstimate $request
*
* @return PurchaseOrder
*/
/**
* Constructor
*/
public function __construct()
{
$this->payments = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add payment
*
* @param \InboundBundle\Entity\Payment $payment
*
* @return PurchaseOrder
*/
public function addPayment(\InboundBundle\Entity\Payment $payment)
{
$this->payments[] = $payment;
return $this;
}
/**
* Remove payment
*
* @param \InboundBundle\Entity\Payment $payment
*/
public function removePayment(\InboundBundle\Entity\Payment $payment)
{
$this->payments->removeElement($payment);
}
/**
* Get payments
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getPayments()
{
return $this->payments;
}
/**
* Set request
*
* @param \InboundBundle\Entity\RequestForEstimate $request
*
* @return PurchaseOrder
*/
public function setRequest(\InboundBundle\Entity\RequestForEstimate $request = null)
{
$this->request = $request;
return $this;
}
}
付款实体:
class Payment
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="PurchaseOrder", inversedBy="payments", cascade={"persist", "detach"})
* @ORM\JoinColumn(name="purchase_order", referencedColumnName="id")
*/
private $purchaseOrder;
/**
* @var \DateTime
*
* @ORM\Column(name="create_time", type="datetime")
*/
private $createTime;
/**
* @var \DateTime
*
* @ORM\Column(name="update_time", type="datetime")
*/
private $updateTime;
/**
* @var int
*
* @ORM\Column(name="creator", type="integer")
*/
private $creator;
/**
* @var string
*
* @ORM\Column(name="amount_paid", type="decimal", precision=10, scale=2)
*/
private $amountPaid;
/**
* @ORM\ManyToOne(targetEntity="PaymentType", cascade={"persist"})
* @ORM\JoinColumn(name="payment_type", referencedColumnName="id")
*/
private $paymentType;
/**
* @var string
*
* @ORM\Column(name="external_transaction_id", type="string", length=255)
*/
private $externalTransactionId;
/**
* @var string
*
* @ORM\Column(name="including_fees", type="decimal", precision=10, scale=2)
*/
private $includingFees;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set createTime
*
* @param \DateTime $createTime
*
* @return Payment
*/
public function setCreateTime($createTime)
{
$this->createTime = $createTime;
return $this;
}
/**
* Get createTime
*
* @return \DateTime
*/
public function getCreateTime()
{
return $this->createTime;
}
/**
* Set updateTime
*
* @param \DateTime $updateTime
*
* @return Payment
*/
public function setUpdateTime($updateTime)
{
$this->updateTime = $updateTime;
return $this;
}
/**
* Get updateTime
*
* @return \DateTime
*/
public function getUpdateTime()
{
return $this->updateTime;
}
/**
* Set creator
*
* @param integer $creator
*
* @return Payment
*/
public function setCreator($creator)
{
$this->creator = $creator;
return $this;
}
/**
* Get creator
*
* @return integer
*/
public function getCreator()
{
return $this->creator;
}
/**
* Set amountPaid
*
* @param string $amountPaid
*
* @return Payment
*/
public function setAmountPaid($amountPaid)
{
$this->amountPaid = $amountPaid;
return $this;
}
/**
* Get amountPaid
*
* @return string
*/
public function getAmountPaid()
{
return $this->amountPaid;
}
/**
* Set paymentType
*
* @param string $paymentType
*
* @return Payment
*/
public function setPaymentType($paymentType)
{
$this->paymentType = $paymentType;
return $this;
}
/**
* Get paymentType
*
* @return string
*/
public function getPaymentType()
{
return $this->paymentType;
}
/**
* Set externalTransactionId
*
* @param string $externalTransactionId
*
* @return Payment
*/
public function setExternalTransactionId($externalTransactionId)
{
$this->externalTransactionId = $externalTransactionId;
return $this;
}
/**
* Get externalTransactionId
*
* @return string
*/
public function getExternalTransactionId()
{
return $this->externalTransactionId;
}
/**
* Set includingFees
*
* @param string $includingFees
*
* @return Payment
*/
public function setIncludingFees($includingFees)
{
$this->includingFees = $includingFees;
return $this;
}
/**
* Get includingFees
*
* @return string
*/
public function getIncludingFees()
{
return $this->includingFees;
}
/**
* Set purchaseOrder
*
* @param \InboundBundle\Entity\PurchaseOrder $purchaseOrder
*
* @return Payment
*/
public function setPurchaseOrder(\InboundBundle\Entity\PurchaseOrder $purchaseOrder = null)
{
$this->purchaseOrder = $purchaseOrder;
return $this;
}
/**
* Get purchaseOrder
*
* @return \InboundBundle\Entity\PurchaseOrder
*/
public function getPurchaseOrder()
{
return $this->purchaseOrder;
}
}
当我转储对象时,它显示默认情况下allPaid为0:
答案 0 :(得分:2)
Matko的答案有效,但你的问题暗示你(或者至少你是)遗漏了一些基本的东西。
在原始代码中,内部(私有)allPaid
属性初始化为零。您的getAllPaid()
方法计算实际值并返回它。如上所述,getAllPaid()
将在每次调用时迭代付款集合。
转储实体时,$allPaid
属性为零,因为您在调用 getAllPaid()
之前转储了。如果您调用getAllPaid()
然后转储,您将看到它包含计算值。这是因为getAllPaid()
在此过程中设置了该值。或者,不是转储(并查看未初始化的内部值),而是通过实际调用getAllPaid()
进行测试,并查看是否返回了正确的值。
Matko解决方案的弱点在于它每次都急切地加载集合。在某些情况下,您可能需要在不加载所有付款的情况下加载PurchaseOrder。
由于$allPaid
是私有的,因此您始终会使用getAllPaid()
来访问该值。
要改进您的代码,我会记住 $allPaid
初始化private $allPaid = null;
。 null
的语义更合适,因为在初始化时,该值不为零。这是未知的。
在getAllPaid()中,添加$this->allPaid !== null
的检查,如果是,请提前返回。这样,重复调用getAllPaid()
不会每次都重新计算该值。
请务必在付款收集更改时清除备忘录。 PurchaseOrder::addPayment()
和PurchaseOrder::removePayment()
都应将$this->allPaid
设置为null,强制在下次调用getAllPaid()
时重新计算该值。
最后,删除PurchaseOrder::payments
上的急切fetchmode。如果您想在知道自己需要它们的情况下急切加载它们,可以在查询中获取它们。
答案 1 :(得分:1)
您应该使用Doctrine2 postLoad event。实体从数据库加载到当前EntityManager或刷新操作应用到实体后,实体会发生 postLoad 事件。
...
use Doctrine\ORM\Mapping as ORM;
...
/**
* ...
* @ORM\HasLifecycleCallbacks
* ...
*/
class PurchaseOrder
{
...
private $allPaid = null;
/**
* @ORM\PostLoad
*/
public function getAllPaid()
{
if (null === $this->allPaid) {
foreach ($this->payments as $payment) {
$this->allPaid += $payment->amountPaid();
}
}
return $this->allPaid;
}
}