@templton1982

DQL запрос в symfony (связь много ко многим)?

Имею 2 сущности:
user - пользователи
stock - акции пользователя

<?php
namespace Stocker\StockBundle\Entity;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="Stocker\StockBundle\Entity\Repository\UserRepository")
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    
     /**
     * @ORM\ManyToMany(targetEntity="Userstock", inversedBy="users")
     * @ORM\JoinTable(name="userstocks")
     */
    private $userstocks;

    public function __construct()
    {
        parent::__construct();
        $this->userstocks=new ArrayCollection();
    }


<?php
namespace Stocker\StockBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="Stocker\StockBundle\Entity\Repository\UserstockRepository")
 * @ORM\Table(name="userstock")
 */
class Userstock
{
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->users = new ArrayCollection();
    }
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\Column(type="string",length=255)
     */
    protected $stockname;
    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="userstocks")
     */
    protected $users;


Я могу получить список пользователь с акциями и, наоборот, акции со списком пользователей.

А как получить список акций, которых нет у заданного пользователя?

На чистом sql это выглядит так:
SELECT us.stockname
FROM userstock us
LEFT JOIN userstocks u_s ON us.id=u_s.userstock_id AND u_s.user_id=1
WHERE u_s.user_id IS null


Но я не могу получить доступ к промежуточной таблице userstocks, т.к. для нее нет сущности. И создать сущность с привязкой к таблице userstocks тоже не могу, так как таблица уже создана.
Можно, конечно, сделать через обычный SQL, но как сделать через doctrine?
Еще можно сделать разбор на php (взять все акции и вычесть те, что есть у пользователя), но это тоже вариант так себе. Надо сразу получить готовый результат средствами DQL.
  • Вопрос задан
  • 924 просмотра
Решения вопроса 2
@templton1982 Автор вопроса
Правильно будет так:
$qb=$this->createQueryBuilder('q')
                ->select('q','d')
                ->leftJoin('q.users', 'd')
                ->where('d.id!=:userid OR d.id is null')
                ->setParameter('userid', $userid);
Ответ написан
@romashka_sky
SELECT stock FROM StockBundle:Userstock stock WHERE :user NOT MEMBER OF stock.users
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
А как получить список акций, которых нет у заданного пользователя?


Перефразируя. Вам нужен список акций всех пользователей кроме конкретного, нет?

SELECT s.stockname FROM Stocker\StockBundle\Entity\Userstock s
WHERE s.user != :user


где :user это id юзера.

Вообще такая штука. Если вы хотите оперировать SQL и т.д. то оперируйте. Напишите свой native query и т.д. А еще лучше - откажитесь от доктрины. Она хороша тогда, когда вы погружаетесь в предметную область и больше тратите время не на SQL/базы данные а на грамотное выстраивание взаимоотношений ваших сущностей.

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

p.s. StockBundle это плохая идея. По сути если у вас есть что-то типа CoreBundle (общий бандл) - то вы уже проиграли в плане разделения логики на "отдельные части". Границы проведены неверно.
Ответ написан
@Latunov
А как в doctrine выполнить запрос к нескольким таблицам вида
SELECT t2.* FROM `table1` AS t1, `table2` AS t2, `table_links` AS t3 WHERE t1.id='".$id."' AND t1.id=t3.link1 AND t2.id=t3.link2

?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы