Doctrine 自定义实体存储库 (QueryBuilder)
Doctrine custom entity repository (QueryBuilder)
我们为 Room 实体创建自定义存储库 QueryBuilder, 将 return 两个日期之间的所有可用房间。我有两个实体 Room.php 和 Reservation.php
在 RoomRepository.php 我创建 function findAvailableRooms($from, $to)
Hove 我创建查询生成器谁 return 所有在选定的时间段内没有预订的房间? Tnx
Room.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\AvailableRoom;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Uid\Uuid;
use App\Repository\RoomRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Controller\AvailableRoomController;
/**
* @ApiResource(
* normalizationContext={"groups"={"room:read"}},
* denormalizationContext={"groups"={"room:write"}},
* attributes={
* "pagination_client_items_per_page"=true
* },
* collectionOperations={
* "get",
* "post",
* "get_available"={
* "method"="GET",
* "path"="/rooms/available/{from}/{to}",
* "controller"=AvailableRoomController::class
* }
* }
* )
* @ORM\Entity(repositoryClass=RoomRepository::class)
*/
class Room
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidV4Generator::class)
* @Groups({"room:read"})
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"room:read", "room:write", "reservation:read"})
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
* @Gedmo\Slug(fields={"name"})
* @Groups({"room:read", "room:write"})
*/
private $slug;
/**
* @ORM\Column(type="text", nullable=true)
* @Groups({"room:read", "room:write"})
*/
private $description;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
* @Groups({"room:read", "room:write"})
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
* @Groups({"room:read", "room:write"})
*/
private $updatedAt;
/**
* @ORM\OneToMany(targetEntity=Reservation::class, mappedBy="room")
* @Groups({"room:read", "room:write"})
*/
private $reservations;
public function __construct()
{
$this->reservations = new ArrayCollection();
}
public function getId(): ?Uuid
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* @return Collection|Reservation[]
*/
public function getReservations(): Collection
{
return $this->reservations;
}
public function addReservation(Reservation $reservation): self
{
if (!$this->reservations->contains($reservation)) {
$this->reservations[] = $reservation;
$reservation->setRoom($this);
}
return $this;
}
public function removeReservation(Reservation $reservation): self
{
if ($this->reservations->removeElement($reservation)) {
// set the owning side to null (unless already changed)
if ($reservation->getRoom() === $this) {
$reservation->setRoom(null);
}
}
return $this;
}
}
Reservation.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter;
use App\Repository\ReservationRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Uid\Uuid;
/**
* @ApiResource(
* normalizationContext={"groups"={"reservation:read"}},
* denormalizationContext={"groups"={"reservation:write"}},
* attributes={
* "pagination_client_items_per_page"=true
* }
* )
* @ApiFilter(DateFilter::class, properties={"dateFrom"})
* @ORM\Entity(repositoryClass=ReservationRepository::class)
*/
class Reservation
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidV4Generator::class)
* @Groups({"reservation:read"})
*/
private $id;
/**
* @ORM\Column(type="date")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $dateFrom;
/**
* @ORM\Column(type="date")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $dateTo;
/**
* @ORM\Column(type="json", nullable=true)
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $meta = [];
/**
* @ORM\ManyToOne(targetEntity=Room::class, inversedBy="reservations")
* @Groups({"reservation:read", "reservation:write"})
*/
private $room;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $updatedAt;
public function getId(): ?Uuid
{
return $this->id;
}
public function getDateFrom(): ?\DateTimeInterface
{
return $this->dateFrom;
}
public function setDateFrom(\DateTimeInterface $dateFrom): self
{
$this->dateFrom = $dateFrom;
return $this;
}
public function getDateTo(): ?\DateTimeInterface
{
return $this->dateTo;
}
public function setDateTo(\DateTimeInterface $dateTo): self
{
$this->dateTo = $dateTo;
return $this;
}
public function getMeta(): ?array
{
return $this->meta;
}
public function setMeta(?array $meta): self
{
$this->meta = $meta;
return $this;
}
public function getRoom(): ?Room
{
return $this->room;
}
public function setRoom(?Room $room): self
{
$this->room = $room;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}
类似于以下放置在您的 ReservationRepository
中的方法将获取具有 Reservation
与指定日期范围重叠的 Room
的 ID:
/**
* @param \DateTimeInterface $start
* @param \DateTimeInterface $end
*
* @return array
*/
public function findRoomIdsReservedInDateRange(\DateTimeInterface $start, \DateTimeInterface $end)
{
$result = $this
->createQueryBuilder('r')
->select('r.room.id')
->andWhere('r.dateFrom < :end')
->andWhere('r.dateTo > :start')
->setParameter('start', $start)
->setParameter('end', $end)
->orderBy('r.room.id', 'ASC')
->getQuery()
->getScalarResult()
; // [['id' => 1], ['id' => 2], ['id' => 2], ['id' => 5]]
return array_unique(array_column($result, 'id')); // [1, 2, 5]
}
然后您可以从 RoomRepository
中调用该方法
$exclude = $reservationRepository->findRoomIdsReservedInDateRange($start, $end);
return $this
->createQueryBuilder('room')
->andWhere('room.id not in :array')
->setParameter('array', $exclude)
->getQuery()
->getResult()
;
我们为 Room 实体创建自定义存储库 QueryBuilder, 将 return 两个日期之间的所有可用房间。我有两个实体 Room.php 和 Reservation.php
在 RoomRepository.php 我创建 function findAvailableRooms($from, $to)
Hove 我创建查询生成器谁 return 所有在选定的时间段内没有预订的房间? Tnx
Room.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\AvailableRoom;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Uid\Uuid;
use App\Repository\RoomRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Controller\AvailableRoomController;
/**
* @ApiResource(
* normalizationContext={"groups"={"room:read"}},
* denormalizationContext={"groups"={"room:write"}},
* attributes={
* "pagination_client_items_per_page"=true
* },
* collectionOperations={
* "get",
* "post",
* "get_available"={
* "method"="GET",
* "path"="/rooms/available/{from}/{to}",
* "controller"=AvailableRoomController::class
* }
* }
* )
* @ORM\Entity(repositoryClass=RoomRepository::class)
*/
class Room
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidV4Generator::class)
* @Groups({"room:read"})
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"room:read", "room:write", "reservation:read"})
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
* @Gedmo\Slug(fields={"name"})
* @Groups({"room:read", "room:write"})
*/
private $slug;
/**
* @ORM\Column(type="text", nullable=true)
* @Groups({"room:read", "room:write"})
*/
private $description;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
* @Groups({"room:read", "room:write"})
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
* @Groups({"room:read", "room:write"})
*/
private $updatedAt;
/**
* @ORM\OneToMany(targetEntity=Reservation::class, mappedBy="room")
* @Groups({"room:read", "room:write"})
*/
private $reservations;
public function __construct()
{
$this->reservations = new ArrayCollection();
}
public function getId(): ?Uuid
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* @return Collection|Reservation[]
*/
public function getReservations(): Collection
{
return $this->reservations;
}
public function addReservation(Reservation $reservation): self
{
if (!$this->reservations->contains($reservation)) {
$this->reservations[] = $reservation;
$reservation->setRoom($this);
}
return $this;
}
public function removeReservation(Reservation $reservation): self
{
if ($this->reservations->removeElement($reservation)) {
// set the owning side to null (unless already changed)
if ($reservation->getRoom() === $this) {
$reservation->setRoom(null);
}
}
return $this;
}
}
Reservation.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter;
use App\Repository\ReservationRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Uid\Uuid;
/**
* @ApiResource(
* normalizationContext={"groups"={"reservation:read"}},
* denormalizationContext={"groups"={"reservation:write"}},
* attributes={
* "pagination_client_items_per_page"=true
* }
* )
* @ApiFilter(DateFilter::class, properties={"dateFrom"})
* @ORM\Entity(repositoryClass=ReservationRepository::class)
*/
class Reservation
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidV4Generator::class)
* @Groups({"reservation:read"})
*/
private $id;
/**
* @ORM\Column(type="date")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $dateFrom;
/**
* @ORM\Column(type="date")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $dateTo;
/**
* @ORM\Column(type="json", nullable=true)
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $meta = [];
/**
* @ORM\ManyToOne(targetEntity=Room::class, inversedBy="reservations")
* @Groups({"reservation:read", "reservation:write"})
*/
private $room;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
* @Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $updatedAt;
public function getId(): ?Uuid
{
return $this->id;
}
public function getDateFrom(): ?\DateTimeInterface
{
return $this->dateFrom;
}
public function setDateFrom(\DateTimeInterface $dateFrom): self
{
$this->dateFrom = $dateFrom;
return $this;
}
public function getDateTo(): ?\DateTimeInterface
{
return $this->dateTo;
}
public function setDateTo(\DateTimeInterface $dateTo): self
{
$this->dateTo = $dateTo;
return $this;
}
public function getMeta(): ?array
{
return $this->meta;
}
public function setMeta(?array $meta): self
{
$this->meta = $meta;
return $this;
}
public function getRoom(): ?Room
{
return $this->room;
}
public function setRoom(?Room $room): self
{
$this->room = $room;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}
类似于以下放置在您的 ReservationRepository
中的方法将获取具有 Reservation
与指定日期范围重叠的 Room
的 ID:
/**
* @param \DateTimeInterface $start
* @param \DateTimeInterface $end
*
* @return array
*/
public function findRoomIdsReservedInDateRange(\DateTimeInterface $start, \DateTimeInterface $end)
{
$result = $this
->createQueryBuilder('r')
->select('r.room.id')
->andWhere('r.dateFrom < :end')
->andWhere('r.dateTo > :start')
->setParameter('start', $start)
->setParameter('end', $end)
->orderBy('r.room.id', 'ASC')
->getQuery()
->getScalarResult()
; // [['id' => 1], ['id' => 2], ['id' => 2], ['id' => 5]]
return array_unique(array_column($result, 'id')); // [1, 2, 5]
}
然后您可以从 RoomRepository
$exclude = $reservationRepository->findRoomIdsReservedInDateRange($start, $end);
return $this
->createQueryBuilder('room')
->andWhere('room.id not in :array')
->setParameter('array', $exclude)
->getQuery()
->getResult()
;