Reputation: 8548
I would like to serialize my objects into text fields in order to store a representation of them for traceability.
What I really want is a JSON representation of the entity's properties, and whenever there is an object, I would like a JSON representation of that as well, but only on that first level, I don't want it to dig deeper into what possible objects and relations there is below that, I'm happy with the object ID's
Many objects reference other objects, and from this documentation https://symfony.com/doc/current/components/serializer.html#handling-circular-references it appears this can be easily handled by just storing the object's ID rather than serializing the entire object (again). But in my case it doesn't work =) Am I missing something critical here?
Entity
<?php
namespace App\Entity;
use App\Repository\RegularServiceHoursRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=RegularServiceHoursRepository::class)
*/
class RegularServiceHours
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="datetime")
*/
private $open;
/**
* @ORM\Column(type="datetime")
*/
private $close;
/**
* @var object \App\Entity\ACRGroup
*
* @ORM\ManyToOne(targetEntity="\App\Entity\ACRGroup", inversedBy="regularServiceHours")
* @ORM\JoinColumn(name="acr_group", referencedColumnName="id", nullable=false)
*/
protected $ACRGroup;
public function getId(): ?int
{
return $this->id;
}
public function getOpen(): ?\DateTimeInterface
{
return $this->open;
}
public function setOpen(\DateTimeInterface $open): self
{
$this->open = $open;
return $this;
}
public function getClose(): ?\DateTimeInterface
{
return $this->close;
}
public function setClose(\DateTimeInterface $close): self
{
$this->close = $close;
return $this;
}
/**
* Set aCRGroup
*
* @param \App\Entity\ACRGroup $aCRGroup
*
* @return DebitPeriod
*/
public function setACRGroup(\App\Entity\ACRGroup $aCRGroup)
{
$this->ACRGroup = $aCRGroup;
return $this;
}
/**
* Get aCRGroup
*
* @return \App\Entity\ACRGroup
*/
public function getACRGroup()
{
return $this->ACRGroup;
}
/**
* Get debitTimeSeconds
*
* @return int
*/
public function getTimeSeconds()
{
$open = $this->getOpen();
$close = $this->getClose();
$r = $close->format('U') - $open->format('U');
return $r;
}
}
Controller
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Serializer;
public function log($type,$message,$unit=null,$previous=null,$current=null) {
//We only log successful operations.
//If you want to log also errors, be very careful to not have anything persisted already, in que to be flushed. The flush below will store possible entities under conflict check and entities that sent you here due to a failed validation/conflict check, entities that weren't meant to be saved but rejected and forgotten.
if ($type == 'success') {
$encoder = new JsonEncoder();
$defaultContext = [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, $format, $context) {
return $object->getId();
},
];
$normalizer = new ObjectNormalizer(null, null, null, null, null, null, $defaultContext);
$serializer = new Serializer([$normalizer], [$encoder]);
dd($serializer->serialize($current, 'json'));
It never gets to the dump action, it chews for 30 seconds until memory is exhausted, and then it says:
Error: Maximum execution time of 30 seconds exceeded
Have I somehow missed where to set a default depth of 1? (I understood depth 1 to be the default when nothing was set).
Upvotes: 0
Views: 1417
Reputation: 2383
Pay attention to Serialization Groups Attributes. With this attribute you can select the desired data when serializing an object.
Specify groups to the desired object properties:
class RegularServiceHours
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({"default"})
*/
private $id;
/**
* @ORM\Column(type="datetime")
*/
private $open;
/**
* @ORM\Column(type="datetime")
* @Groups({"default"})
*/
private $close;
/**
* @var object \App\Entity\ACRGroup
*
* @ORM\ManyToOne(targetEntity="\App\Entity\ACRGroup", inversedBy="regularServiceHours")
* @ORM\JoinColumn(name="acr_group", referencedColumnName="id", nullable=false)
* @Groups({"default"})
*/
private $ACRGroup;
}
Also specify a group for the ACRGroup
identifier
class ACRGroup
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({"default"})
*/
private $id;
}
And just specify the group when serializing the object
$serializer->serialize($current, 'json', ['groups' => ['default']]);
I think that should solve your problem
Upvotes: 0