将属性添加到与Doctrine的QueryBuilder

时间:2015-05-14 08:13:21

标签: php symfony doctrine-orm associations query-builder

我正在使用Symfony 2.3和doctrine 1.2

我有以下实体结构,包括Product,Tag和TagCategory。 Product与Tag具有ManyToMany关系,Tag与TagCategory具有ManyToOne关系

产品类别:

class Product
{
    /**
     * @var ArrayCollection List of tags
     *
     * @ORM\ManyToMany(targetEntity="Tag", inversedBy="products")
     * @ORM\JoinTable(name="tags_productos",
     *      joinColumns={@ORM\JoinColumn(name="cod_pro", referencedColumnName="cod_pro")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="cod_tag", referencedColumnName="id")}
     *      )
     */
    protected $tags;
}

TagCategory类:

class TagCategory extends BaseTagCategory
{
    /**
     * @ORM\OneToMany(targetEntity="Tag", mappedBy="category", orphanRemoval=true)
     */
    protected $tags;
}

标记类:

class Tag extends BaseTag
{
    /**
     * @Assert\NotBlank()
     * @ORM\ManyToOne(targetEntity="TagCategory", inversedBy="tags")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false)
     */
    protected $category;

    /**
     * @var ArrayCollection List of products that have this tag assigned
     *
     * @ORM\ManyToMany(targetEntity="Product", mappedBy="tags")
     */
    protected $products;
}

我需要做的是,对于给定的产品列表,获取这些产品所具有的标签,并且对于每个标签,获取具有该标签的产品数量。

我还想检索按TagCategory分组的标签,因为它们需要进行分组。

以下是我尝试的其中一个查询,它位于 TagCategory 存储库:

$qb->select('c as tagCategory, t as tag, COUNT(t) as total')
        ->from($this->_entityName, 'c')
        ->leftJoin('c.tags', 't')
        ->leftJoin('t.products', 'p')
        ->where(
            $qb->expr()->in('p.id', $productsIds)
            )
        ->groupBy('t.id')
    ;

这给了我一个具有以下结构的数组:

array(3) {
    [0]=> array(2) {
        ["tagCategory"]=> array(4) {
            ["id"]=>
            ["name"]=>
            ["slug"]=>
            ["tags"]=> array(2) {
                [0]=> array(4) {
                    ["id"]=>
                    ["order"]=>
                    ["name"]=>
                    ["slug"]=>
                }
                [1]=> array(4) {
                    ["id"]=>
                    ["order"]=>
                    ["name"]=>
                    ["slug"]=>
                }
            }
        }
        ["total"]=>
}

此查询对类别中的所有标记进行分组,这是我想要的,但它将总数放在顶级,并将其作为类别中最后一个标记的总和。我需要总数作为标记实体的另一个属性。

我也尝试在标记存储库中执行此查询:

$qb->select('c as tagCategory, t as tag, COUNT(t) as total')
        ->from($this->_entityName, 't')
        ->leftJoin('t.category', 'c')
        ->leftJoin('t.products', 'p')
        ->where(
            $qb->expr()->in('p.id', $productsIds)
            )
        ->groupBy('t.id')
    ;

这个查询给了我一个标签数组,类别和总数作为属性,这是正确的,但我需要将标签分组到一个类别中:

array(4) {
    [0]=> array(2) {
        ["tag"]=> array(5) {
            ["id"]=>
            ["order"]=>
            ["name"]=>
            ["slug"]=>
            ["category"]=> array(3) {
                ["id"]=>
                ["name"]=>
                ["slug"]=>
            }
        }
        ["total"]=>
}

我需要这样的东西,可以吗?

array(3) {
    [0]=> array(2) {
        ["tagCategory"]=> array(4) {
            ["id"]=>
            ["name"]=>
            ["slug"]=>
            ["tags"]=> array(2) {
                [0]=> array(4) {
                    ["id"]=>
                    ["order"]=>
                    ["name"]=>
                    ["slug"]=>
                    **["total"]=>**
                }
                [1]=> array(4) {
                    ["id"]=>
                    ["order"]=>
                    ["name"]=>
                    ["slug"]=>
                    **["total"]=>**
                }
            }
        }
}

谢谢。

2 个答案:

答案 0 :(得分:2)

您要执行的操作无法在SQL级别上使用单个查询完成。

您可以使用子查询进行2次查询或1次查询。 仍然可以在背景中做到这一点,但我不认为教条可以做到这一点。我怀疑教义1. *能够。

无论如何,如果您不需要tagCategory中的所有数据,最好的解决方案是修改您的第二个查询,并选择您需要的其他字段。

$qb->select('c as tagCategory, t as tag, COUNT(t) as total, c.name as tagCategory_name')
    ->from($this->_entityName, 't')
    ->leftJoin('t.category', 'c')
    ->leftJoin('t.products', 'p')
    ->where(
        $qb->expr()->in('p.id', $productsIds)
        )

    ->groupBy('t.id')
;

如果您需要,所有数据和您描述的确切结构,请选择所有带有一个查询的tagCategories,然后通过id在foreach循环中对其进行配对。

答案 1 :(得分:0)

在下面的代码中有一些误区

joinColumns = {@ ORM \ JoinColumn(name =“cod_pro”,referencedColumnName =“cod_pro”)},

应该是

joinColumns = {@ ORM \ JoinColumn(name =“cod_pro”,referencedColumnName =“id”)},