Не могу понять, как сделать правильный метод хранилища, который мне нужен - PullRequest
0 голосов
/ 30 октября 2019

Я пытаюсь создать QueryBuilder с объединением моего продукта сущности и моего магазина сущностей. Я хотел бы отобразить все продукты, связанные с OneStore. Они имеют отношение многие ко многим. Я не могу понять, как получить удостоверения личности. Welp, пожалуйста. Заранее спасибо!

вот скриншот моей таблицы product_store:

https://imgur.com/a/wUZMEEn

Так что, если я достаточно ясен и мой английский законен, вы понимаете, что я 'хотелось бы отображать только товары, связанные с одним идентификатором магазина.

Давайте сделаем пример. Если я нахожусь на странице / store / detail / {1}, я хотел бы отобразить идентификатор продукта 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();
    }

$ продут в магазине сущность:


/**
     *
     * @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;

$ хранить в продукте:


/**
     * * @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,
        ));
    }

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

Вы можете лучше называть свои свойства $ store и $ products вместо единственной версии, чтобы было ясно, что мы говорим о массиве или коллекции с несколькими возможными магазинами или продуктами. Вы действительно не нуждаетесь в 2-4-м правиле ваших аннотаций. Просто

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\Product", mappedBy="store")
 */

и

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\Store", inversedBy="product")
 */

. Это говорит нам о том, что вы используете двунаправленное отношение ManyToMany. Объекты Store и Product содержат список противоположных объектов. Для этого вы можете запросить у Магазинов набор товаров или продуктов с набором магазинов.

и как правильно использовать $ 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 %}
0 голосов
/ 30 октября 2019

Мне непонятно, почему вы делаете специальный запрос, если хотите получить все товары из одного магазина.

Когда вы установили отношение ManyToMany (с надеждой на комплект производителя), вам также следовало добавить в 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();
}

Приведенный выше запрос должен вернуть все товары из одногоstore.
Кроме того, никогда не используйте where(), всегда andWhere(). Подробнее об этом читайте здесь.

[РЕДАКТИРОВАТЬ]

В ответ на ваши изменения. Как сказал Фрэнк Б., вы можете добиться большего успеха.
Во-первых, как я уже сказал, вам не нужен пользовательский запрос.
Вместо этого создайте геттер в 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;
    }
}

Теперь в вашем контроллере все, что вам нужно сделать, это позвонить вашему получателю.
Doctrine обработает запрос для вас:

/**
 * @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()), чтобы узнать, в каком магазине вы можете найти свой. продукт.

...