尝试使用 Symfony 创建一个允许我访问外键对象的查询

Trying to create a query with Symfony that allows me to access object of foreign key

所以我有 3 个实体:

超市:

|编号 | supermarket_name |

类别:

|编号 | category_name |

产品:

|编号 | product_name | supermarket_id | category_id |

supermarket_id 和 category_id 分别与超市和类别的 id 多对一。

我希望这样当我 select 一家超市时,我可以获得该超市下方列出的所有类别。我一直在尝试通过已传递到我的 ProductRepository.php 文件中的查询方法的超市 id 从产品实体进行查询来获取此数据,如果我有以下内容,该文件将成功运行:

public function findAllCategoriesBySupermarket($supermarketId)
    {
        return $this->getEntityManager()
            ->createQuery(
                "SELECT p
                FROM AppBundle:Product p
                WHERE p.supermarketId = $supermarketId"
            )
            ->getResult();
    }

然后我可以在我的视图中循环成功地显示产品:

{{ product.categoryId.categoryName }}

问题是因为我是从产品中查询的,所以我最终会得到不止一个相同的类别,因为可以将多个产品分配到同一类别,所以我试图通过向类别:

public function findAllCategoriesBySupermarket($supermarketId)
    {
        return $this->getEntityManager()
            ->createQuery(
                "SELECT DISTINCT p.categoryId
                FROM AppBundle:Product p
                WHERE p.supermarketId = $supermarketId"
            )
            ->getResult();
    }

当我在 phpmyadmin 中测试它时它工作正常但不幸的是 symfony 给出了以下错误:

[Semantical Error] line 0, col 18 near 'categoryId
': Error: Invalid PathExpression. Must be a StateFieldPathExpression.

不确定我该如何解决这个问题,因为我已经尝试了很多不同的方法,但都没有成功。任何关于我如何解决这个问题的建议都将不胜感激!

问题是您不能通过 属性 在学说中 select 一个不同的实体关联。但是,您可以 select 不同的身份。假设您想要实体而不仅仅是 ID...

为此,您需要将两个实体之间的关联定义为双向关联。

由于您在 Product.category 上有关联但与 Category.products 没有关联,因此您需要创建它。

/**
 * @ORM\Entity
 */
class Category 
{
   //...

   /**
    * @ORM\OneToMany(targetEntity="AppBundle\Entity\Product", mappedBy="category")
    */
   private $products;


    public function __construct()
    {
         $this->products = new \Doctrine\Common\Collections\ArrayCollection;
    }

    //...

   /**
    * get Products
    * @return Product[]|ArrayCollection
    */
    public function getProducts()
    {
        return $this->products;
    }

     /**
      * add Product
      * @param Product $product
      * @return $this
      */
     public function addProduct(Product $product)
     {
        $this->products->add($product);

         return $this;
     }

    /**
     * remove Product
     * @param Product $product
     * @return $this
     */
    public function removeProduct(Product $product)
    {
        $this->products->removeElement($product);

        return $this;
    }
}

然后在您的 Product.category 属性

中加入协会 inversedBy
/**
 * @ORM\Entity
 */
class Product
{

    //...

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="products")
     * @ORM\JoinColumn(name="category", referencedColumnName="id")
     */
    private $category;

    //...
}

您也不能 select 没有根关联的关联实体。 例如

SELECT DISTINCT c
FROM AppBundle:Product p
JOIN p.category c

'SELECT DISTINCT': Error: Cannot select entity through identification variables without choosing at least one root entity alias.

因此,要检索与指定超市的产品关联的不同类别,您可以像这样编写 DQL。

public function findAllCategoriesBySupermarket($supermarketId)
{
    return $this->_em->createQuery(
            'SELECT c
            FROM AppBundle:Category c
            JOIN c.products p WITH p.supermarketId = :supermarket'
        )
        ->setParameter('supermarket', $supermarketId)
        ->getResult();
}

虽然我想指出,DISTINCT 标志在这种情况下是多余的,因为它仅隐含在 select 类别 (c) 中。

您也可以使用 SELECT c, p 来获取一系列类别及其相关产品。

{% for category in categories %}
    {{ category.name }}:
    {% for product in category.products %}
        {{ product.name }}
    {% endfor %}
{% endfor %}

或者,要保留单向关系,您需要使用子查询。但是您将失去检索 Category.products 关联的能力,如上所示。

SELECT c
FROM AppBundle:Category c
WHERE c.id IN (
    SELECT DISTINCT IDENTITY(p.categoryId)
    FROM AppBundle:Product p
    WHERE p.supermarketId = :supermarket
)