所以我有3个实体:
超市:
| id | supermarket_name |
分类
| id | category_name |
产品:
| id | product_name | supermarket_id | category_id |
supermarket_id和category_id分别与超市和类别的ID分别为多对一。
我希望这样当我选择一家超市时,我会获得该超市下面列出的所有类别。我一直试图通过我的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 }}
问题是因为我从产品中查询我将最终得到多个相同类别的产品,因为可以将多个产品分配到同一类别,因此我尝试通过向该类别添加distinct来解决此问题:
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.
我不知道如何解决这个问题,因为我已经尝试了很多不同的事情而没有运气。关于如何解决这个问题的任何建议都将不胜感激!
答案 0 :(得分:0)
问题是您无法在学说中按属性选择不同的实体关联。但是,您可以选择不同的身份。假设您想要实体而不仅仅是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;
}
}
然后在inversedBy
属性
Product.category
/**
* @ORM\Entity
*/
class Product
{
//...
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="products")
* @ORM\JoinColumn(name="category", referencedColumnName="id")
*/
private $category;
//...
}
如果没有根关联,您也无法选择关联的实体。 例如
SELECT DISTINCT c
FROM AppBundle:Product p
JOIN p.category c
'SELECT DISTINCT':错误:如果不选择至少一个根实体别名,则无法通过标识变量选择实体。
因此,要检索产品与指定超市相关联的不同类别,您可以像这样编写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
标志在此上下文中是多余的,因为仅选择类别(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
)