查询生成器 - 获取另一个查询的行数

时间:2017-02-27 22:17:04

标签: php mysql doctrine symfony query-builder

我正在参加摄影比赛并且有这样的关系

  • 所有图片都有和id,标题,作者和文件名
  • 所有投票都有一个ID,投票所针对的图片的ID和数据

以下是项目中的实体:

图像     

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Image {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\Column(type="string", length=255, name="file_name")
     * @var string $fileName
     */
    protected $fileName;

    /**
     * @ORM\Column(type="string", length=255, name="title", nullable=true)
     * @var string $title
     */
    protected $title = null;

    /**
     * @ORM\Column(type="string", length=255, name="author", nullable=true)
     * @var string $author
     */
    protected $author = null;

    /**
     * @ORM\Column(type="datetime", name="upload_at")
     */
    protected $uploadDate;

    /**
     * @ORM\Column(type="boolean", name="in_pool")
     */
    protected $inPool;


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set fileName
     *
     * @param string $fileName
     *
     * @return Image
     */
    public function setFileName($fileName)
    {
        $this->fileName = $fileName;

        return $this;
    }

    /**
     * Get fileName
     *
     * @return string
     */
    public function getFileName()
    {
        return $this->fileName;
    }

    /**
     * Set title
     *
     * @param string $title
     *
     * @return Image
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set author
     *
     * @param string $author
     *
     * @return Image
     */
    public function setAuthor($author)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return string
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Set uploadDate
     *
     * @param \DateTime $uploadDate
     *
     * @return Image
     */
    public function setUploadDate($uploadDate)
    {
        $this->uploadDate = $uploadDate;

        return $this;
    }

    /**
     * Get uploadDate
     *
     * @return \DateTime
     */
    public function getUploadDate()
    {
        return $this->uploadDate;
    }

    /**
     * Set inPool
     *
     * @param boolean $inPool
     *
     * @return Image
     */
    public function setInPool($inPool)
    {
        $this->inPool = $inPool;

        return $this;
    }

    /**
     * Get inPool
     *
     * @return boolean
     */
    public function getInPool()
    {
        return $this->inPool;
    }

    public function __construct()
    {
        $this->uploadDate = new \DateTime('now');
        $this->inPool = false;
    }
}

投票

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Image;

/**
 * @ORM\Entity
 */
class Vote
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Image")
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    protected $image;

    /**
     * @ORM\Column(type="datetime", name="date")
     */
    protected $date;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }


    /**
     * Set date
     *
     * @param \DateTime $date
     *
     * @return Vote
     */
    public function setDate($date)
    {
        $this->date = $date;

        return $this;
    }

    /**
     * Get date
     *
     * @return \DateTime
     */
    public function getDate()
    {
        return $this->date;
    }

    public function __construct()
    {
        $this->date = new \DateTime('now');
    }

    /**
     * Set image
     *
     * @param \AppBundle\Entity\Image $image
     *
     * @return Vote
     */
    public function setImage(Image $image = null)
    {
        $this->image = $image;

        return $this;
    }

    /**
     * Get image
     *
     * @return \AppBundle\Entity\Image
     */
    public function getImage()
    {
        return $this->image;
    }
}

现在在我的主页面上,我有一个简单的查询构建器,在表格中显示所有具有属性的图像。

现在我想在表格的每一行添加一个字段,显示每张图片的投票数

这意味着我需要获取每行的count,其id为当前图像的id。

使用QueryBuilder实现此目的的最佳方法是什么?

请注意,我想获取所有图片的值

2 个答案:

答案 0 :(得分:0)

在投票中添加inversedBy

/**
         * @ORM\ManyToOne(targetEntity="Image", inversedBy="votes")
         * @ORM\JoinColumn(onDelete="CASCADE")
         */
        private $image;
图片实体中的

添加属性$ votes

  /**
         * One image has many votes
         * @ORM\OneToMany(targetEntity="Vote", mappedBy="image")
         */
        private $votes;

  function __construct() {
       $this-> votes = new ArrayCollection()
  }

然后使用getter你可以获得选票:

function getVotes()
{
   return $this->votes;
}

和ArrayCollection具有count()方法,因此您可以使用它来获得投票数

答案 1 :(得分:0)

Vote实体的存储库类中(它应该是VoteRepository,如果它已经存在,则创建此类)添加方法countVotesForImage

/**
 * Method returns count of votes assigned to an Image entity
 *
 * @param Image $image Instance of Image entity
 *
 * @return int Result of count query
 */
public function countVotesForImage(Image $image)
{
    $imageID = $image->getId();

    if (!is_numeric($imageID)) {
        // for new images which are not stored in DB
        // we dont have to query database
        return 0;
    }

    return (int) $this->createQueryBuilder('v')
        ->select('COUNT(v.id)')
        ->where('v.image = :id')
        ->setParameter('id', $image->getId())
        ->getQuery()
        ->getSingleScalarResult();
}

在任何控制器中,您都可以使用它:

$image; // this variable should contain valid class of Image entity
$counter = $this->getDoctrine()->getRepository('AppBundle:Vote')
    ->countVotesForImage($image);

最后一步是将其传递给视图:

return $this->render(
    'your/template.html.twig',
    array('counter' => $counter)
);

如果您想对所有图片进行所有投票,请将此方法添加到ImageRepository

/**
 * Method returns count of votes assigned to an Image entity
 *
 * @return ArrayCollection
 */
public function countVotesForAllImages()
{
    return $this->createQueryBuilder('i')
        ->select(array(
            'i',
            'COUNT(i.id) as counter'
        ))
        ->join('i.votes', 'v')
        ->groupBy('i.id')
        ->getQuery()
        ->getResult();
}

如果添加此方法,您还需要添加投票实体:

/**
 * This is internal variable, it does not have to be mapped into database field
 * @var int Counter of votes for an Image
 */
private $counter;

/**
 * Method sets internal counter of votes for an Image
 *
 * @param int $counter
 */
public function setCounter($counter)
{
    $this->counter = $counter;
}

/**
 * Method gets internal counter of votes for an Image
 *
 * @return int
 */
public function getCounter()
{
    return $this->counter;
}

@Markownikow提出的方法也可以使用,但它将所有投票从DB存入内存,水合它们,并在计数后作为内存中的数组项。由于这可能是一种矫枉过正,我建议选择我的方法。