首页 > 解决方案 > Symfony 将带有子实体的实体序列化为 XML

问题描述

我正在尝试使用 Symfony 的内置序列化程序将具有子实体的实体序列化为 XML 文件。问题是序列化程序没有按照我预期的方式格式化 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 的默认序列化程序来实现这一点。

标签: phpsymfonyserializationxml-serialization

解决方案


推荐阅读