[英]How to query related entities based on their value
我的網站上有廣告。 要公開展示廣告,必須付費。 廣告是公開的或已付款的,如果沒有未付款項,或者已付款。
我想要的是檢索所有公共廣告,但這需要使用此方法進行大量查詢。 我正在尋找更好的方法。
這里有更多字段,但讓我們關注payments
字段。 這是一對多的。
class Ad
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255,nullable=true)
*/
private $adTitle;
/**
* @var string
*
* @ORM\Column(name="description", type="string", length=255,nullable=true)
*/
private $description;
/**
* @ORM\ManyToOne(targetEntity="Application\FOS\UserBundle\Entity\User")
* @ORM\JoinColumn(name="advertiser")
*/
private $advertiser;
/**
* @ORM\OnetoMany(targetEntity="MyBundle\Entity\Payment",mappedBy="ad",cascade={"persist"})
* @ORM\JoinColumn(name="payments", referencedColumnName="id",nullable=true)
*/
private $payments;
}
對於付款,我使用的是PayumBundle,因此實體看起來像這樣:
use Payum\Core\Model\Payment as BasePayment;
class Payment extends BasePayment
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* @var integer $id
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="MyBundle\Entity\Ad",inversedBy="payments",cascade={"persist"})
* @ORM\JoinColumn(name="ad", referencedColumnName="id",nullable=true)
*/
protected $ad;
}
目前,我正在使用執行以下操作的服務:
public function getAllPublicAds()
{
$allAds = $this->em->getRepository('MyBundle:Ad')->findAll();
$publicAds=array();
foreach($allAds as $ad){
if($this->isPublicAd($ad)) array_push($publicAds,$ad);
}
return $publicAds;
}
我正在獲取所有廣告,如果它們是公開的,則將它們放到一個數組中,稍后將進入樹枝視圖。
如果廣告的所有付款均已支付,則該廣告為公開廣告,因此:
public function isPublicAd(Ad $ad)
{
$payments = $ad->getPayments();
if (!count($payments)) {
return false;
} else {
foreach ($payments as $payment) {
if (!$this->paidPayment($payment)) return false;
}
return true;
}
}
最后,如果表中的明細字段“已付款”為真,則將支付已付款。 這就是PayumBundle的工作方式。 它會創建一個令牌,然后在您使用該令牌為您的對象付款后,將有關付款的詳細信息填充到該對象的“付款”字段中。 您可以在這里找到課程。 我的付款課程從上面進行了擴展。 因此,我正在檢查這些詳細信息是否已填寫,或者“已付款”字段為true。
public function paidPayment(Payment $payment)
{
$details = $payment->getDetails();
if (array_key_exists("paid", $details) && $details["paid"]) return true;
else return false;
}
問題在於,這將對數據庫創建非常大量且不必要的查詢。 可以縮短這個時間嗎? 我不確定我是否可以在沒有Doctrine的情況下使用普通查詢,因為我需要在收到數據庫結果后檢查details ['paid']字段,而這只能在控制器或服務中進行。 如果在查詢中甚至可以做到這一點,我也不知道,也似乎沒有找到解決方法。
您應該使用QueryBuilder
而不是findAll
方法。 在這種情況下,您可以指定需要匹配的條件(就像在普通sql
)。
所以:
$paidAds = $this->em->getRepository('MyBundle:Ad')
->createQueryBuilder('a')
->innerJoin('a.Payments', 'p')
->getQuery()
->getResult();
實際上,我並沒有對您的數據庫結構進行深入分析,因為innerJoin
可能只是您需要的條件,因為您只會獲得與付款有關的Ads
要了解有關QueryBuilder
檢查文檔的更多信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.