简体   繁体   English

如何根据相关实体的值查询

[英]How to query related entities based on their value

I have Ads on my website. 我的网站上有广告。 For an Ad to be publicly displayed, it must be paid for. 要公开展示广告,必须付费。 An ad is public or paid for if it has no payment that is unpaid, or all its payments are paid for. 广告是公开的或已付款的,如果没有未付款项,或者已付款。

What I want is to retrieve all public ads, but that requires a large number of queries using this method. 我想要的是检索所有公共广告,但这需要使用此方法进行大量查询。 I'm looking for a better way. 我正在寻找更好的方法。

This has more fields, but let's focus on the payments field. 这里有更多字段,但让我们关注payments字段。 It's a 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;

}

For payments, I'm using PayumBundle, so the entity looks like so: 对于付款,我使用的是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;


}

Currently I'm using a service that does something like this: 目前,我正在使用执行以下操作的服务:

  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;

    }

I'm getting all the ads, and if they are public, I put them into an array which will later go to the twig view. 我正在获取所有广告,如果它们是公开的,则将它们放到一个数组中,稍后将进入树枝视图。

An Ad is public if all of its payments are paid, therefore: 如果广告的所有付款均已支付,则该广告为公开广告,因此:

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;
    }
 }

And finally, a paid Payment is paid if its details field 'paid' in the table is true. 最后,如果表中的明细字段“已付款”为真,则将支付已付款。 This is how PayumBundle works. 这就是PayumBundle的工作方式。 It creates a token, then after you use that token to pay for your object, it fills that object's payment field details with details about the payment. 它会创建一个令牌,然后在您使用该令牌为您的对象付款后,将有关付款的详细信息填充到该对象的“付款”字段中。 You can find the class here . 您可以在这里找到课程。 My Payment class from above extends it. 我的付款课程从上面进行了扩展。 So I'm checking whether those details have been filled, or if the 'paid' field is true. 因此,我正在检查这些详细信息是否已填写,或者“已付款”字段为true。

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

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

    else return false;

}

The problem is that this creates a very big and unnecessary number of queries to the database. 问题在于,这将对数据库创建非常大量且不必要的查询。 Is it possible to shorten this out? 可以缩短这个时间吗? I'm not sure I can use normal queries without Doctrine, because I need to check the details['paid'] field, whcih I can only do in a controller or service, after I've received the database results. 我不确定我是否可以在没有Doctrine的情况下使用普通查询,因为我需要在收到数据库结果后检查details ['paid']字段,而这只能在控制器或服务中进行。 If that is even possible to do inside a query, I don't know either nor seem to find a way to do it. 如果在查询中甚至可以做到这一点,我也不知道,也似乎没有找到解决方法。

You should use QueryBuilder instead of findAll method. 您应该使用QueryBuilder而不是findAll方法。 In such case you can specify conditions which need to be match (just like in plain sql ). 在这种情况下,您可以指定需要匹配的条件(就像在普通sql )。

So: 所以:

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

I didn't analyze deep your db structure by in fact innerJoin might be only condition which you need since you will get only those Ads which have relation to payments 实际上,我并没有对您的数据库结构进行深入分析,因为innerJoin可能只是您需要的条件,因为您只会获得与付款有关的Ads

To read more about QueryBuilder check doc 要了解有关QueryBuilder检查文档的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM