【问题标题】:How to get partial result from doctrine query builder如何从学说查询生成器中获取部分结果
【发布时间】:2013-06-04 09:05:45
【问题描述】:

我有一个产品实体,其中有一个数组作为属性:

     /**
     * @ORM\OneToMany(targetEntity="Shopious\MainBundle\Entity\ProductPicture", mappedBy="product", cascade={"persist","remove"})
     */
    protected $pictures;

    /** 
    * @Accessor(getter="getCover") 
    */
    private $cover;
    public function getCover()
    {
        if($this->pictures->count() > 0) {
            return $this->pictures[0];
        }
        return new ProductPicture();
    }

现在在我的查询生成器中,我有以下代码:

 $query = $em->createQueryBuilder()->select('p')
            ->from("SiteMainBundle:Product", 'p')
            ->innerJoin('p.category', 'c')
            ->innerJoin('p.shop', 'shop')
            ;

这里的问题是我不想选择 p 的所有属性。所以我只想得到图片数组中的第一个 ProductPicture (在我上面的例子中,它类似于 getCover() 方法)。我该怎么做?

到目前为止,我可以通过以下方式过滤掉我想要的部分属性:

 $query = $em->createQueryBuilder()->select('p.name, p.id')
                ->from("SiteMainBundle:Product", 'p')
                ->innerJoin('p.category', 'c')
                ->innerJoin('p.shop', 'shop')
                ->innerJoin('p.pictures', 'pictures')
                ;

所以在上面的例子中我已经对图片进行了内连接,但是我如何从这里获取第一个元素呢?

总之,我的问题是如何使用查询构建器选择/查询图片数组中的第一个 ProductPicture?因为当我这样做时:

$query = $em->createQueryBuilder()->select('p')

它返回整个产品属性,但我不想要整个产品属性。我只想要其中的一些,例如 id、名称等。但是其中一个产品属性实际上是一个实体(其中是 ProductPicture),那么如何在 select 语句中返回这个?

编辑:

这是一个关于如何将图片进行内部连接的 SQL 等价物:

SELECT * 
FROM  `product` 
JOIN  `product_picture` ON  `product`.id =  `product_picture`.product_id
WHERE  `product`.id =100
LIMIT 1

【问题讨论】:

  • 你的意思是把where放在哪里或者如何执行查询?
  • 我在问有没有办法将 SQL 转换为查询生成器?我对将限制翻译成查询有点困惑。我知道学说中有一个 setMaxResults,但这给出了不同的结果。
  • 什么不同的结果?喜欢不同的图片?还是整行都不一样?
  • 我赞成您的问题,因为它是一个有趣的问题,但根据您尝试的查询构建器和之后提供的 SQL,它也是模棱两可的。如果您可以向我们提供您希望返回哪些数据的示例,就像查询已成功执行一样,那么我可以帮助您弄清楚如何构建查询。
  • @Adam-E 我再次编辑/更新了问题

标签: php sql symfony doctrine query-builder


【解决方案1】:

试试这样,如果是一对多,正常的 mySQL 行为是返回多条带有冗余产品数据的记录,如果这里发生同样的情况,那么只返回第一条记录就可以了。
PS假设 ProductPicture 实体有一个您想要获取的 url 属性

$query = $em->createQueryBuilder()->select('p.id, p.name, pictures.url')
            ->from("SiteMainBundle:Product", 'p')
            ->innerJoin('p.category', 'c')
            ->innerJoin('p.shop', 'shop')
            ->innerJoin('p.pictures', 'pictures')
            ;

【讨论】:

  • 好的,所以这个查询的问题是它多次返回相同的产品 ID。我将在原始问题中添加更多详细信息。
  • 你需要先了解mysql,如果我们有产品p,有图片img1,img2,img3,你查询,它会返回3条记录,所有3条记录都有相同的产品p,但是每条记录都有不同的图像,(p,img1),(p,img2),(p,img3),您应该指定您想要的图像,例如main = 1的图像或类似的东西
  • 我明白了,我认为解决方案是分组
【解决方案2】:

为您的实体添加带有 DQL 的自定义存储库方法,然后从控制器调用它

您可以随意命名存储库方法,在此示例中我使用的是findProductWithPicture

class ProductRepository extends EntityRepository
{
    /**
     * @param integer $id
     */
    public function findProductWithPicture($id)
    {
        $dql = <<<SQL
SELECT
    p.id    id,
    p.name  name,
    q       picture
FROM
    Shopious\MainBundle\Entity\ProductPicture q,
    Shopious\MainBundle\Entity\Product p
WHERE
    p.id        = :picture_id  AND
    q.product   = p.id
SQL;

        $query = $this->_em->createQuery($dql)->setParameter('picture_id', $id);

        return $query->setMaxResults(1)->getResult();
    }
}

从控制器中使用它

$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('ShopiousMainBundle:Product')->findProductWithPicture($id);

return $this->render('ShopiousMainBundle:Product:show.html.twig', array(
    'product' => $product[0]
));

在渲染的 Twig 模板中,你可以像这样访问它们

<p>{{ product.id }}
<p>{{ product.name }}
<p>{{ product.picture.whatever_property }}

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 2020-01-18
    • 1970-01-01
    • 2017-05-22
    • 2021-07-08
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    相关资源
    最近更新 更多