我正在尝试使用实体产品和实体商店之间的联接来创建QueryBuilder。我想展示所有与OneStore相关的产品。他们有多对多的关系。我不知道如何获取ID。请哭。预先感谢!
这是我的product_store表的屏幕截图:
因此,如果我很清楚我的英语能力,那么您了解我只想显示与一个商店ID相关的产品。
让我们举个例子。如果我在/ store / detail / {1}页面上,我想显示产品ID 1,3,6,8,10,13,因为它们与store.id = 1相关。
因此,按照我的建议,我进行了更新,但是它不起作用,并且我没有发现错误所在。我在哪里弄错了? (控制器已更新)
这是我得到的错误: https://imgur.com/a/q3Uun3E
----------------------我的存储库功能---------------------- -------
public function getProductsForStore($sid)
{
return $this->createQueryBuilder('s')
->join('s.product', 'p')
->addSelect('p')
->andWhere('s.id = :sid')
->orderBy('p.name', 'ASC')
->setParameter('sid', $sid)
->getQuery()
->getResult();
}
商店实体中的$ produt:
/**
*
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="App\Entity\Product", mappedBy="store")
* * @ORM\JoinTable(name="product_store",
* joinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="store_id", referencedColumnName="id")}
* )
*/
private $product;
$ store在产品实体中:
/**
* * @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="App\Entity\Store", inversedBy="product")
* * @ORM\JoinTable(name="product_store",
* joinColumns={@ORM\JoinColumn(name="store_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="id")}
* )
*/
private $store;
我的控制器功能:
/**
* @Route("stores/detail/{id}", name="detail_store"))
*/
public function getOneStore(StoreRepository $repository, Store $store): Response
{
$store = $repository->findOneBy(array(
'id' => $store->getId(),
));
$products_store = $repository->getProductsForStore(':id');
return $this->render('store.html.twig', array(
'store' => $store,
'product' => $products_store,
));
}
答案 0 :(得分:0)
我确实想知道为什么要从一个商店获取所有产品,为什么要进行自定义查询。
建立多对多关系(希望与制造商捆绑销售)时,还应该在Store
实体中添加一个吸气剂($store->getProducts()
),以获取该商店的所有产品。
无论如何,这是您的查询...
public function getAllProductsFromOneStore(Store $store) {
$qb=$this->createQueryBuilder('store');
$qb->addSelect('product')
->join('store.product', 'product')
->andWhere('store.id = :storeId')
->setParameters(array(
'storeId'=>$store->getId();
));
return $qb->getQuery->getResult();
}
以上查询应返回一家商店的所有产品。
另外,永远不要使用where()
,永远不要使用andWhere()
。 Read more about it here.
[编辑]
响应您的编辑。正如Frank B所说,您可以做得更好。
首先,正如我所说,您不需要自定义查询。
相反,请在Store
和Product
实体中进行吸气。
src / Entity / Store.php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
class Store {
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Product", inversedBy="stores")
*/
private $products;
public function __construct() {
$this->products=new ArrayCollection();
}
/**
* GETTER
*
* @return Collection|Product[]
*/
public function getProducts(): Collection {
return $this->products;
}
/**
* ADD A PRODUCT TO A STORE
*/
public function addProduct(Product $product): self {
if(!$this->products->contains($product)) {
$this->products[]=$product;
}
return $this;
}
/**
* REMOVE A PRODUCT FROM A STORE
*/
public function removeProduct(Product $product): self {
if($this->products->contains($product)) {
$this->products->removeElement($product);
}
return $this;
}
}
src / Entity / Product.php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
class Product {
private $stores;
public function __construct() {
$this->stores=new ArrayCollection();
}
/**
* GETTER
*
* @return Collection|Store[]
*/
public function getStores(): Collection {
return $this->stores;
}
/**
* ADD A STORE TO A PRODUCT
*/
public function addStore(Store $store): self {
if(!$this->stores->contains($store)) {
$this->stores[]=$store;
$store->addProduct($this);
}
return $this;
}
/**
* REMOVE A STORE FROM A PRODUCT
*/
public function removeStore(Store $store): self {
if($this->stores->contains($store)) {
$this->stores->removeElement($store);
$store->removeProduct($this);
}
return $this;
}
}
现在在您的控制器中,您要做的就是调用您的吸气剂。
教义将为您处理查询:
/**
* @Route("stores/store-{id}", name="index_store"))
*/
public function index(Store $store): Response {
$products=$store->getProducts();
return $this->render('store.html.twig', array(
'store'=>$store,
'products'=>$products,
));
}
然后在您的树枝视图中:
{% for product in store.products %}
// Your code here
{% endfor %}
就是这样。在实体中使用吸气剂后,就不需要自定义查询。
请注意,您可以对Product
($product->getStores()
)进行相同操作,以了解可以在哪家商店中找到您的产品。
答案 1 :(得分:0)
您最好将属性称为$ stores和$ products,而不是单数版本,以明确说明我们所讨论的数组或集合可能包含多个商店或产品。您确实不需要注释的第二至第四条规则。只是
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Product", mappedBy="store")
*/
和
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Store", inversedBy="product")
*/
可以。它告诉我们您使用双向的ManyToMany关系。 “商店”和“产品”实体都拥有相反实体的列表。因此,您可以查询具有产品集合的商店或具有商店集合的产品。
在控制器中使用$ store-> getProducts()的正确方法是什么?
因此在第一个答案中交换产品,反之亦然:
public function getStore($sid)
{
return $this->createQueryBuilder('s')
->join('s.product', 'p')
->addSelect('p')
->andWhere('s.id = :sid')
->orderBy('p.name', 'ASC')
->setParameter('sid', $sid);
->getQuery()
->getResult()
;
}
控制器:
/**
* @Route("/{id}", name="store_show", methods={"GET"})
*/
public function show($id): Response
{
$em = $this->getDoctrine()->getManager();
$em->getRepository('App:Store')->getStore($id);
if(null === $store) {
throw $this->createNotFoundException('Store not found.');
}
return $this->render('store/show.html.twig', [
'store' => $store,
]);
}
嫩枝:
{% extends 'base.html.twig' %}
{% block title %}Store{% endblock %}
{% block body %}
<h1>{{ store.name }}</h1>
<table class="table">
<thead>
<tr>
<th>ProductId</th>
<th>ProductName</th>
</tr>
</thead>
<tbody>
{% for product in store.products %} {# loop through all products in store #}
<tr>
<td>{{ product.id }}</td>
<td>{{ product.name }}</td>
</tr>
{% else %}
<tr>
<td colspan="4">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}