Несколько объединений в отношении ManyToMany - PullRequest
0 голосов
/ 01 мая 2019

У меня есть 3 объекта, Пользователь, Парковка и Voiture.Пользователь имеет отношение ManyToMany к парковке, в то время как у парковки есть ответ OneToMany с голосом.

что я пытаюсь сделать:

Получить автомобили (голоса), которые принадлежат всем парковкам, с которыми связан данный пользователь

как я пытаюсь это сделать:

Использование querybuilder, но я до сих пор не знаю, как заставить его работать

вот мои сущности

Пользователь Entity:

<?php

/**
 * @ORM\Entity
 * @UniqueEntity(fields="username", message="Username already taken")
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    public function getId()
    {
        return $this->id;
    }


    /**
     * @ORM\Column(type="string", length=191, unique=true)
     * @Assert\NotBlank()
     */
    private $username;


    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Parking", mappedBy="agents")
     */
    private $parkings;
    public function __construct()
    {
        $this->parkings = new ArrayCollection();
    }



    /**
     * @return Collection|Parking[]
     */
    public function getParkings(): Collection
    {
        return $this->parkings;
    }

    public function addParking(Parking $parking): self
    {
        if (!$this->parkings->contains($parking)) {
            $this->parkings[] = $parking;
            $parking->addAgent($this);
            return $this;
        }

        return $this;
    }

    public function removeParking(Parking $parking): self
    {
        if ($this->parkings->contains($parking)) {
            $this->parkings->removeElement($parking);
            $parking->removeAgent($this);
        }

        return $this;
    }
}

Парковка Entity:

<?php

/**
 * @ORM\Entity(repositoryClass="App\Repository\ParkingRepository")
 */
class Parking
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=55)
     */
    private $libelle;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\user", inversedBy="parkings")
     */
    private $agents;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Voiture", mappedBy="parking", orphanRemoval=true)
     */
    private $voitures;


    public function __construct()
    {
        $this->agents = new ArrayCollection();
        $this->voitures = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }


    /**
     * @return Collection|user[]
     */
    public function getAgents(): Collection
    {
        return $this->agents;
    }

    public function addAgent(user $agent): self
    {
        if (!$this->agents->contains($agent)) {
            $this->agents[] = $agent;
        }

        return $this;
    }

    public function removeAgent(user $agent): self
    {
        if ($this->agents->contains($agent)) {
            $this->agents->removeElement($agent);
        }

        return $this;
    }

    /**
     * @return Collection|Voiture[]
     */
    public function getVoitures(): Collection
    {
        return $this->voitures;
    }

    public function addVoiture(Voiture $voiture): self
    {
        if (!$this->voitures->contains($voiture)) {
            $this->voitures[] = $voiture;
            $voiture->setParking($this);
        }

        return $this;
    }

    public function removeVoiture(Voiture $voiture): self
    {
        if ($this->voitures->contains($voiture)) {
            $this->voitures->removeElement($voiture);
            // set the owning side to null (unless already changed)
            if ($voiture->getParking() === $this) {
                $voiture->setParking(null);
            }
        }

        return $this;
    }

}

И Voiture Entity

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\VoitureRepository")
 */
class Voiture
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=200)
     */
    private $matricule;


    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Parking", inversedBy="voitures")
     * @ORM\JoinColumn(nullable=false)
     */
    private $parking;

    /**
     * @ORM\Column(type="boolean")
     */
    private $parked;



    public function getId(): ?int
    {
        return $this->id;
    }

    public function getMatricule(): ?string
    {
        return $this->matricule;
    }

    public function setMatricule(string $matricule): self
    {
        $this->matricule = $matricule;

        return $this;
    }



    public function getParking(): ?Parking
    {
        return $this->parking;
    }

    public function setParking(?Parking $parking): self
    {
        $this->parking = $parking;

        return $this;
    }

}

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Я предлагаю добавить промежуточную сущность UserParking между сущностью User и Parking. Таким образом, у нас есть отношение OneToMany между User и UserParking и отношение OneToMany между Parking и UserParking вместо отношения ManyToMany между User и Parking.

Объекты будут похожи на код ниже:

Пользователь сущности:

<?php

/**
 * @ORM\Entity
 * @UniqueEntity(fields="username", message="Username already taken")
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    public function getId()
    {
        return $this->id;
    }


    /**
     * @ORM\Column(type="string", length=191, unique=true)
     * @Assert\NotBlank()
     */
    private $username;


    /**
     * @ORM\OneToMany(targetEntity="App\Entity\UserParking", mappedBy="agent")
     * @ORM\JoinColumn(nullable=true)
     */
    private $user_parking;

// getter and setter
}

Entity Parking:

<?php

/**
 * @ORM\Entity(repositoryClass="App\Repository\ParkingRepository")
 */
class Parking
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=55)
     */
    private $libelle;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\UserParking", mappedBy="parking")
     * @ORM\JoinColumn(nullable=true)
     */
    private $user_parking;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Voiture", mappedBy="parking", orphanRemoval=true)
     */
    private $voitures;

// getters and setters

}

Entity UserParking

/**
 * UserParking
 *
 * @ORM\Table(name="user_parking")
 * @ORM\Entity(repositoryClass="App\Repository\UserParkingRepository")
 */
class UserParking
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="user_parking")
     * @ORM\JoinColumn(nullable=false)
     */
    private $agent;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Parking", inversedBy="user_parking")
     * @ORM\JoinColumn(nullable=false)
     */
    private $parking;

    // getter and setter
}

И Entity Voiture

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\VoitureRepository")
 */
class Voiture
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=200)
     */
    private $matricule;


    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Parking", inversedBy="voitures")
     * @ORM\JoinColumn(nullable=false)
     */
    private $parking;

    /**
     * @ORM\Column(type="boolean")
     */
    private $parked;
}

Таким образом, чтобы получить автомобили (голоса), которые принадлежат всем парковкам, к которым относится текущий пользователь, необходимо:

1 - Получить текущий объект пользователя.

2 - Получить массив UserParking от объекта пользователя.

3- Получить объекты парковки из массива UserParking.

4- Получить машины с парковочных объектов.

Код будет похож на этот:

$em = $this->getDoctrine()->getManager();

/* Get user from the session */
$user = $this->getUser();

$userParkings = $user->getUserParking();
$parkings = [];
foreach ($userParkings as $item) {
    $parking = $item->getParking();
    $parkings[count($parkings)] = $parking;
}
// you can get voitures from parkings
1 голос
/ 02 мая 2019

Запуск от сущности Voiture и внутреннее объединение сущностей Parking и User с использованием их ассоциаций:

$queryBuilder = $this->getDoctrine()->getRepository('App:Voiture')->createQueryBuilder('v');
$queryBuilder->innerJoin('v.parking', 'p');
$queryBuilder->innerJoin('v.agents', 'a');

Наконец, вы можете отфильтровать отношение либо через условие:

$queryBuilder->where('a.id = :userId');
$queryBuilder->setParameter("userId", 1);

$cars = $queryBuilder->getQuery()->getResult();

или поместите условие в $queryBuilder->innerJoin('v.agents', 'a', 'WITH', 'a.id = :userId'); см. внутреннее соединение доктрины с условием

Ссылки

...