Skip to content

Commit 2b1e854

Browse files
committed
[Serializer] Handle circular references. symfony/symfony#12098.
1 parent 5d505bb commit 2b1e854

File tree

1 file changed

+94
-1
lines changed

1 file changed

+94
-1
lines changed

components/serializer.rst

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,107 @@ When serializing, you can set a callback to format a specific object property::
238238
$serializer->serialize($person, 'json');
239239
// Output: {"name":"cordoval", "age": 34, "createdAt": "2014-03-22T09:43:12-0500"}
240240

241+
Handling Circular References
242+
----------------------------
243+
244+
.. versionadded:: 2.6
245+
Handling of circular references was introduced in Symfony 2.6. In previous versions of Symfony, circular references
246+
lead to infinite loops.
247+
248+
Circular references are common when dealing with entities relations::
249+
250+
class Organization
251+
{
252+
private $name;
253+
private $members;
254+
255+
public function setName($name)
256+
{
257+
$this->name = $name;
258+
}
259+
260+
public function getName()
261+
{
262+
return $this->name;
263+
}
264+
265+
public function setMembers(array $members)
266+
{
267+
$this->members = $members;
268+
}
269+
270+
public function getMembers()
271+
{
272+
return $this->members;
273+
}
274+
}
275+
276+
class Member
277+
{
278+
private $name;
279+
private $organization;
280+
281+
public function setName($name)
282+
{
283+
$this->name = $name;
284+
}
285+
286+
public function getName()
287+
{
288+
return $this->name;
289+
}
290+
291+
public function setOrganization(Organization $organization)
292+
{
293+
$this->organization = $organization;
294+
}
295+
296+
public function getOrganization()
297+
{
298+
return $this->organization;
299+
}
300+
}
301+
302+
To avoid infinite loops, :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` throws a
303+
:class:`Symfony\\Component\\Serializer\\Exception\\CircularReferenceException` when such case is encountered::
304+
305+
$member = new Member();
306+
$member->setName('Kévin');
307+
308+
$org = new Organization();
309+
$org->setName('Les-Tilleuls.coop');
310+
$org->setMembers(array($member));
311+
312+
$member->setOrganization($kevin);
313+
314+
echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException
315+
316+
317+
The `setCircularReferenceLimit()` method of this normalizer set the number of times serializing the same object must
318+
occur before considering being in a circular reference. Its default value is `1`.
319+
320+
Instead of throwing an exception, circular references can also be handled by custom callables. This is especially useful
321+
when serializing entities having unique identifiers::
322+
323+
$encoder = new JsonEncoder();
324+
$normalizer = new GetSetMethodNormalizer();
325+
326+
$normalizer->setCircularReferenceHandler(function ($object) {
327+
return $object->getName();
328+
});
329+
330+
$serializer = new Serializer(array($normalizer), array($encoder));
331+
echo $serializer->serialize($org, 'json');
332+
// {"name":"Les-Tilleuls.coop","members":[{"name":"K\u00e9vin", organization: "Les-Tilleuls.coop"]}
333+
241334
JMSSerializer
242335
-------------
243336

244337
A popular third-party library, `JMS serializer`_, provides a more
245338
sophisticated albeit more complex solution. This library includes the
246339
ability to configure how your objects should be serialized/deserialized via
247340
annotations (as well as YAML, XML and PHP), integration with the Doctrine ORM,
248-
and handling of other complex cases (e.g. circular references).
341+
and handling of other complex cases.
249342

250343
.. _`JMS serializer`: https://github.com/schmittjoh/serializer
251344
.. _Packagist: https://packagist.org/packages/symfony/serializer

0 commit comments

Comments
 (0)