Я пытаюсь сериализовать сущность с дочерними объектами в XML-файл с помощью встроенного сериализатора из Symfony. Проблема в том, что сериализатор не
отформатировать коллекцию детей в xml так, как я ожидал.
Я запускаю сериализатор следующим образом:
$normalizer = new ObjectNormalizer();
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getId();
});
$this->serializer = new Serializer(
[
$normalizer,
new GetSetMethodNormalizer(),
new ArrayDenormalizer()
],
[new XmlEncoder(), new JsonEncoder()]
);
И вызвать сериализатор так:
$this->serializer->serialize(
$entityCollection,
'xml',
[
'xml_format_output' => true,
'xml_root_node_name' => 'events'
]
);
Что приводит к следующему XML:
<item key="140">
<id/>
<name>Lorum ipsum</name>
<lastEdited/>
<url>Lorum ipsum</url>
<region>Limburg</region>
<description>Lorum ipsum</description>
<location/>
<contact/>
<content><![CDATA[<p>Lorum ipsum</p>]]></content>
<priceChild/>
<priceAdult/>
<startTime>15:00:00</startTime>
<endTime>15:45:00</endTime>
<eventDates/>
<eventImages>
<id/>
<url>herfstvoorstelling.jpg</url>
</eventImages>
<eventImages>
<id/>
<url>test.jpg</url>
</eventImages>
</item>
Как вы можете видеть <eventImages>
узел представлен дважды там, где я ожидал, что он будет иметь следующую структуру:
<eventImages>
<eventImage>
<id/>
<url>herfstvoorstelling.jpg</url>
</eventImage>
<eventImage>
<id/>
<url>test.jpg</url>
</eventImage>
</eventImages>
Используемые объекты:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* @ORM\Entity(repositoryClass="App\Repository\EventRepository")
*/
class Event
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
*/
private $lastEdited;
/**
* @ORM\Column(type="string", length=255)
*/
private $url;
/**
* @ORM\Column(type="string", length=255)
*/
private $region;
/**
* @ORM\Column(type="string", length=255)
*/
private $description;
/**
* @ORM\Column(type="string", length=255)
*/
private $location;
/**
* @ORM\Column(type="string", length=255)
*/
private $contact;
/**
* @ORM\Column(type="string", length=255)
*/
private $content;
/**
* @ORM\Column(type="string", length=255)
*/
private $priceChild;
/**
* @ORM\Column(type="string", length=255)
*/
private $priceAdult;
/**
* @ORM\Column(type="string", length=255)
*/
private $startTime;
/**
* @ORM\Column(type="string", length=255)
*/
private $endTime;
/**
* @ORM\OneToMany(targetEntity="App\Entity\EventDate", mappedBy="event")
*/
private $eventDates;
/**
* @MaxDepth(2)
* @ORM\OneToMany(targetEntity="App\Entity\EventImage", mappedBy="event")
*/
private $eventImages;
public function __construct()
{
$this->eventDates = new ArrayCollection();
$this->eventImages = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getLastEdited(): ?string
{
return $this->lastEdited;
}
public function setLastEdited(string $lastEdited): self
{
$this->lastEdited = $lastEdited;
return $this;
}
public function getUrl(): ?string
{
return $this->url;
}
public function setUrl(string $url): self
{
$this->url = $url;
return $this;
}
public function getRegion(): ?string
{
return $this->region;
}
public function setRegion(string $region): self
{
$this->region = $region;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getLocation(): ?string
{
return $this->location;
}
public function setLocation(string $location): self
{
$this->location = $location;
return $this;
}
public function getContact(): ?string
{
return $this->contact;
}
public function setContact(string $contact): self
{
$this->contact = $contact;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getPriceChild(): ?string
{
return $this->priceChild;
}
public function setPriceChild(string $priceChild): self
{
$this->priceChild = $priceChild;
return $this;
}
public function getPriceAdult(): ?string
{
return $this->priceAdult;
}
public function setPriceAdult(string $priceAdult): self
{
$this->priceAdult = $priceAdult;
return $this;
}
public function getStartTime(): ?string
{
return $this->startTime;
}
public function setStartTime(string $startTime): self
{
$this->startTime = $startTime;
return $this;
}
public function getEndTime(): ?string
{
return $this->endTime;
}
public function setEndTime(string $endTime): self
{
$this->endTime = $endTime;
return $this;
}
/**
* @return Collection|EventDate[]
*/
public function getEventDates(): Collection
{
return $this->eventDates;
}
public function addEventDate(EventDate $eventDate): self
{
if (!$this->eventDates->contains($eventDate)) {
$this->eventDates[] = $eventDate;
$eventDate->setEvent($this);
}
return $this;
}
public function removeEventDate(EventDate $eventDate): self
{
if ($this->eventDates->contains($eventDate)) {
$this->eventDates->removeElement($eventDate);
// set the owning side to null (unless already changed)
if ($eventDate->getEvent() === $this) {
$eventDate->setEvent(null);
}
}
return $this;
}
/**
* @return Collection|EventImage[]
*/
public function getEventImages(): Collection
{
return $this->eventImages;
}
public function addEventImage(EventImage $eventImage): self
{
if (!$this->eventImages->contains($eventImage)) {
$this->eventImages[] = $eventImage;
$eventImage->setEvent($this);
}
return $this;
}
public function removeEventImage(EventImage $eventImage): self
{
if ($this->eventImages->contains($eventImage)) {
$this->eventImages->removeElement($eventImage);
// set the owning side to null (unless already changed)
if ($eventImage->getEvent() === $this) {
$eventImage->setEvent(null);
}
}
return $this;
}
}
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\EventImageRepository")
*/
class EventImage
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $url;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Event", inversedBy="eventImages")
*/
private $event;
public function getId()
{
return $this->id;
}
public function getUrl(): ?string
{
return $this->url;
}
public function setUrl(?string $url): self
{
$this->url = $url;
return $this;
}
public function getEvent(): ?Event
{
return $this->event;
}
public function setEvent(?Event $event): self
{
$this->event = $event;
return $this;
}
}
Я не могу выяснить, чего мне не хватает или возможно ли добиться этого с помощью сериализатора по умолчанию от Symfony.
Задача ещё не решена.
Других решений пока нет …