2016-01-19 42 views
1

我的網站上有廣告。對於要公開展示的廣告,必須付費。如果廣告沒有未付款項,或者所有付款都已付款,則該廣告是公開的或付費的。如何根據其值查詢相關實體

我想要的是檢索所有公開廣告,但這需要使用此方法的大量查詢。我正在尋找更好的方法。

這有更多的領域,但讓我們專注於payments字段。這是一個OneToMany。

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的工作原理。它會創建一個令牌,然後在您使用該令牌爲您的對象付款之後,它將填充該對象的付款字段詳細信息以及有關付款的詳細信息。你可以找到類here。我上面的支付類擴展了它。所以我正在檢查這些細節是否已經填滿,或者「付費」字段是否爲真。

public function paidPayment(Payment $payment) 
{ 
    $details = $payment->getDetails(); 

    if (array_key_exists("paid", $details) && $details["paid"]) return true; 

    else return false; 

} 

問題是,這會對數據庫創建一個非常大且不必要數量的查詢。是否有可能縮短這一點?我不確定在沒有Doctrine的情況下我可以使用普通查詢,因爲我需要在收到數據庫結果之後檢查詳細信息['paid']字段,我只能在控制器或服務中執行此操作。如果這甚至可以在查詢中完成,我既不知道也沒有辦法做到這一點。

+0

我可以給你一個原始的MySQL解決方案 - 如果你可以適應symf/doctrine - 但我需要一個樣本數據集。 – Strawberry

回答

2

您應該使用QueryBuilder而不是findAll方法。在這種情況下,您可以指定需要匹配的條件(就像普通的sql一樣)。

所以:

$paidAds = $this->em->getRepository('MyBundle:Ad') 
       ->createQueryBuilder('a') 
       ->innerJoin('a.Payments', 'p') 
       ->getQuery() 
       ->getResult(); 

我沒有分析深你的數據庫的結構,在事實上innerJoin可能只是你需要,因爲你會得到只有那些Ads具有相對於支付

要條件閱讀更多關於QueryBuilder支票doc

+0

問題是如何檢查querybuilder中的$ details [「paid」]。它是數據庫中的DC2Type:json_array字段。這是我的問題。您的查詢確實提供了付款,但它不會僅提供付費廣告(公開),而是提供所有廣告。 –

+0

你可以使用REGEXP原則擴展 $ qb-> andWhere('REGEXP(x。('':']:}} //在這裏插入你自己的正則表達式 - > getQuery() - > getResult() – rommct

+0

有沒有辦法只查詢具有一定數量付款的行?我將不得不查詢所有付款並查看是否全部付款。這在查詢中是否可能? –

相關問題