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

标签 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 实现此目的的最佳方法是什么?

请记住,我想获取所有图像的值

最佳答案

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

在任何 Controller 中您都可以使用它:

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

最后一步是将其传递给 View :

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

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

/**
 * 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 提出的方法也可以工作,但是它将所有投票从数据库中放入内存中,对它们进行水合,然后在内存中作为数组项进行计数。因为这太过分了,所以我建议选择我的方法。

关于php - 查询生成器 - 获取另一个查询的行数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42496797/

相关文章:

javascript - 将单选按钮的值发布到电子邮件

javascript - 无法让 PHP 在 HTML 中的 &lt;textarea&gt; 标记内执行

mysql - 基于可用 RAM 调优 MySQL

mysql - 巨大的性能差异 : "WHERE x IN (...values...)" vs. "WHERE x IN (<subquery>)"

mysql - 如何查询相关实体但返回根实体?

php - Doctrine Migrations 命名空间错误

php - 动态生成使用 PHP 变量的静态 CSS 文件

php - mongodb 聚合中空字段的投影

php - 在 PHP 中处理大数组

php - 在选择子查询中选择 Doctrine 错误