Api-платформа - Виртуальная собственность - Денормализация коллекции - PullRequest
0 голосов
/ 26 января 2019

У меня есть объект Reservation, который содержит некоторую коллекцию ReservationRev (isions).ReservationRev содержит коллекцию PersonStay.

В Reservation у меня есть виртуальное свойство personStays (getter, add, remove, setter).

Когда я пытаюсь POST Reservation с personStays, я получаю ошибку - не удается найти денормализатор для Collection.

класс Reservation

/**
 * @var Collection
 * @Doctrine\ORM\Mapping\OneToMany(
 *     targetEntity="Zakjakub\OswisAccommodationBundle\Entity\ReservationRev",
 *     mappedBy="container",
 *     cascade={"all"},
 *     orphanRemoval=true
 * )
 */
protected $revisions;

public function __construct(Nameable $nameable, ...) {
    $this->revisions = new ArrayCollection();
    $this->addRevision(new ReservationRev($nameable));
    ...
}

final public function addPersonStay(?PersonStay $personStay): void
{
    if (!$this->getPersonStays()->contains($personStay)) {
        $newRevision = clone $this->getRevisionByDate();
        $newRevision->addPersonStay($personStay);
        $this->addRevision($newRevision);
    }
}

final public function getPersonStays(?\DateTime $dateTime = null): Collection
{
    return $this->getRevisionByDate($dateTime)->getPersonStays() ?? new ArrayCollection();
}

final public function removePersonStay(?PersonStay $personStay): void
{
    if ($this->getPersonStays()->contains($personStay)) {
        $newRevision = clone $this->getRevisionByDate();
        $newRevision->removePersonStay($personStay);
        $this->addRevision($newRevision);
    }
}

final public function setPersonStays(?Collection $personStays): void
{
    $newRevision = clone $this->getRevisionByDate();
    $newRevision->setPersonStays($personStays ?? new ArrayCollection());
    $this->addRevision($newRevision);
}

класс ReservationRev

/**
 * @var Collection
 * @Doctrine\ORM\Mapping\ManyToMany(
 *     targetEntity="Zakjakub\OswisAccommodationBundle\Entity\PersonStay",
 *     inversedBy="reservationRevisions",
 *     cascade={"all"}
 * )
 * @Doctrine\ORM\Mapping\JoinTable(name="accommodation_reservations_person_stays")
 */
protected $personStays;

/**
 * @var Reservation
 * @Doctrine\ORM\Mapping\ManyToOne(
 *     targetEntity="Zakjakub\OswisAccommodationBundle\Entity\Reservation",
 *     inversedBy="revisions"
 * )
 * @Doctrine\ORM\Mapping\JoinColumn(name="container_id", referencedColumnName="id")
 */
protected $container;

public function __construct(Nameable $nameable, ...) {
    $this->personStays = new ArrayCollection();
    ...
}

final public function addPersonStay(?PersonStay $personStay): void
{
    if ($personStay) {
        return;
    }
    if (!$this->personStays->contains($personStay)) {
        $this->personStays->add($personStay);
        $personStay->addReservationRevision($this);
    }
}

final public function removePersonStay(?PersonStay $personStay): void
{
    if ($personStay) {
        return;
    }
    if ($this->personStays->removeElement($personStay)) {
        $personStay->removeReservationRevision($this);
    }
}

final public function setPersonStays(Collection $personStays): void
{
    foreach ($this->personStays as $personStay) {
        if (!$personStays->contains($personStay)) {
            $this->removePersonStay($personStay);
        }
    }
    foreach ($personStays as $personStay) {
        if (!$this->personStays->contains($personStay)) {
            $this->addPersonStay($personStay);
        }
    }
}

/**
 * @return Collection
 */
final public function getPersonStays(): Collection
{
    return $this->personStays ?? new ArrayCollection();
}

класс PersonStay

/**
 * @var Person
 * @Doctrine\ORM\Mapping\ManyToOne(
 *     targetEntity="Zakjakub\OswisAccommodationBundle\Entity\Person",
 *     inversedBy="personStays",
 *     cascade={"all"}
 * )
 * @Doctrine\ORM\Mapping\JoinColumn(name="person_id", referencedColumnName="id")
 */
protected $person;

/**
 * @var Collection
 * @Doctrine\ORM\Mapping\ManyToMany(
 *     targetEntity="Zakjakub\OswisAccommodationBundle\Entity\ReservationRev",
 *     mappedBy="personStays"
 * )
 */
protected $reservationRevisions;

/**
 * @var Room
 * @Doctrine\ORM\Mapping\ManyToOne(
 *     targetEntity="Zakjakub\OswisAccommodationBundle\Entity\Room",
 *     inversedBy="personStays",
 *     cascade={"persist"}
 * )
 * @Doctrine\ORM\Mapping\JoinColumn(name="room_id", referencedColumnName="id")
 */
protected $room;

public function __construct(
    ?Person $person = null,
    ?ReservationRev $reservationRevision = null,
    ?Room $room = null,
    ...
) {
    $this->setPerson($person);
    $this->reservationRevisions = new ArrayCollection();
    $this->addReservationRevision($reservationRevision);
    $this->setRoom($room);
    ...
}

/**
 * @param ReservationRev|null $reservationRev
 */
final public function addReservationRevision(?ReservationRev $reservationRev): void
{
    if (!$reservationRev) {
        return;
    }
    if (!$this->reservationRevisions->contains($reservationRev)) {
        $this->reservationRevisions->add($reservationRev);
        $reservationRev->addPersonStay($this);
    }
}

/**
 * @return Person
 */
final public function getPerson(): ?Person
{
    return $this->person;
}

/**
 * Set person.
 *
 * @param Person|null $person
 */
final public function setPerson(?Person $person): void
{
    if (null !== $this->person) {
        $this->person->removePersonStay($this);
    }
    if ($person && $this->person !== $person) {
        $person->addPersonStay($this);
        $this->person = $person;
    }
}

/**
 * @return Room|null
 */
final public function getRoom(): ?Room
{
    return $this->room;
}

/**
 * @param Room|null $room
 */
final public function setRoom(?Room $room): void
{
    if (null !== $this->room) {
        $this->room->removePersonStay($this);
    }
    if ($room && $this->room !== $room) {
        $room->addPersonStay($this);
        $this->room = $room;
    }
}

/**
 * @return Collection
 */
final public function getReservationRevisions(): Collection
{
    return $this->reservationRevisions ?? new ArrayCollection();
}

/**
 * @param ReservationRev|null $reservationRev
 */
final public function removeReservationRevision(?ReservationRev $reservationRev): void
{
    if (!$reservationRev) {
        return;
    }
    if ($this->reservationRevisions->removeElement($reservationRev)) {
        $reservationRev->removePersonStay($this);
    }
}

POST

{ "personStays": null (or [] or [<some person stays>]), "description": "string", "note": "string" }

Ошибка

Could not denormalize object of type Doctrine\\Common\\Collections\\Collection, no supporting normalizer found.

Symfony 4.2.2

Api-платформа 2.3.6

...