2016-10-21 3 views
0

私はPurchaseOrderエンティティを持っていて、Paymentsエンティティを持っています。 PurchaseOrderエンティティの内部で、Payments.amountPaidの合計を取得しようとしていますが、期待通りに機能しません。理想的には、$ allPaidは各PurchaseOrderに対して支払われるすべての支払い額の合計を持つべきです。ここでメインエンティティの子オブジェクトの合計値をデフォルトで取得する方法

enter link description hereは私の発注書エンティティである:私はこのチュートリアルを以下ました

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であることを示しています:

enter image description here

+0

'private $ allPaid = 0;' private $ allPaid;に変更 –

+0

さて、今はnullです。 – user1029829

答えて

1

Doctrine2 postLoad eventを使用してください。 postLoadイベントは、エンティティがデータベースから現在のEntityManagerにロードされた後、またはリフレッシュ操作が適用された後でエンティティに対して発生します。

... 
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; 
    } 
} 
+0

美しい。どうもありがとう! – user1029829

+0

@ORM \ HasLifecycleCallbacksと@ORM \ PostLoadの両方を使用したときのように見えます。私はamountPaidを2倍にしました。これらのうちの1つだけが必要なようです... – user1029829

+0

これは、オブジェクトが完全にロードされた後にgetAllPaid()を呼び出したためです。 $ this-> allPaidがnullと異なる場合、コード例をチェックで更新しました。 –

1

Matkoの回答はうまくいきますが、あなたの質問はあなたが何か基本的なものを見逃していることを意味します。

元のコードでは、内部(プライベート)allPaidプロパティはゼロに初期化されています。 getAllPaid()メソッドは、実際の値を計算して返します。書かれているように、getAllPaid()は呼び出されるたびに支払いコレクションを繰り返し処理します。

$allPaidをダンプすると、をダンプするので、getAllPaid()が呼び出されたため、プロパティはゼロになります。 getAllPaid()を呼び出してダンプすると、計算された値が含まれていることがわかります。これは、getAllPaid()が途中でその値を設定するためです。または、ダンプする(そして初期化されていない内部値を見る)代わりに、実際にgetAllPaid()を呼び出してテストし、正しい値が返されることを確認してください。

マッコの解決策の弱点は、毎回熱心にコレクションを読み込むことです。すべての支払いをロードせずにPurchaseOrderをロードする必要があるシナリオがいくつかあります。

$allPaidはプライベートなので、常にgetAllPaid()を使用して値にアクセスします。あなたのコードを改善するために

、私はあなたがmemoize$allPaid

  1. 初期private $allPaid = null;だろう。初期化時に値がゼロでないため、nullのセマンティクスがより適切です。それは不明です。

  2. getAllPaid()には、$this->allPaid !== nullのチェックを追加します。その場合は早めに返されます。そうすれば、getAllPaid()への呼び出しを繰り返すたびに値が再計算されることはありません。

  3. 支払いのコレクションが変更された場合は、必ずメモを消去してください。PurchaseOrder::addPayment()PurchaseOrder::removePayment()の両方を$this->allPaidに設定すると、次回の時に値を再計算する必要があります。getAllPaid()が呼び出されます。

  4. 最後に、熱心なフェッチモードをPurchaseOrder::paymentsから削除します。必要があることがわかっている場合に積極的にロードしたい場合は、クエリでフェッチ結合できます。

関連する問題