Reputation: 2285
I have a problem with serializing entity with many relations using groups. I have a problem with serializing related entities this way.
Let's say I have two entities: Product and related Element.
/**
*
* @Serializer\ExclusionPolicy("none")
*/
class Product {
/**
* Primary key
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Serializer\Groups({"list","details"})
* @Serializer\Type("integer")
*/
protected $id;
/**
* @Serializer\Groups({"list","details"})
* @Serializer\Type("string")
*/
protected $name;
/**
* @ORM\Column(name="description", type="string", length=4096, nullable=true)
*
* @Serializer\Groups({"details"})
* @Serializer\Type("string")
*/
protected $description;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Madden\ProjectBundle\Entity\ProjectResource", mappedBy="project")
* @Serializer\Groups({"details"})
* @Serializer\Type("ArrayCollection<Element>")
*/
protected $details1;
/**
* Relation to project tasks
* @ORM\OneToMany(targetEntity="Madden\ProjectBundle\Entity\ProjectTask", mappedBy="project")
* @Serializer\Exclude()
* @Serializer\Type("ArrayCollection<Element>")
*/
protected $details2;
...
}
Element entity has a similar structure:
/**
*
* @Serializer\ExclusionPolicy("none")
*/
class Element {
/**
* Primary key
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Serializer\Groups({"list","details"})
* @Serializer\Type("integer")
*/
protected $id;
/**
* @Serializer\Groups({"list","details"})
* @Serializer\Type("string")
*/
protected $name;
/**
* @ORM\Column(name="description", type="string", length=4096, nullable=true)
*
* @Serializer\Groups({"details"})
* @Serializer\Type("string")
*/
protected $description;
...
}
My problem is that when I'm serializing Product with 'details' group entity I want to serialize only id's of Elements but as you see entity has defined same groups as Product (in case that I would need details of element object) because I want have unified groups on all my entities and prevent making hundreds of groups like 'product_details','element_details', and so on.
Is there a way to eventualy change serialization group when I visit relation or something like that? Handler maybe or something like that?
Regards and thanks for any help
Upvotes: 9
Views: 7810
Reputation: 329
You need to use setGroups
.
The _group
suffix used in the official documentation is not needed.
$context->setGroups([
'Default', //if you want
// use this linked entity but show only its id
'group_of_linked_field',
'group_of_linked_field' => [
'id' // you will need to define this group first
],
// use this linked entity and show fields as described
'group_of_other_linked_field',
'group_of_other_linked_field' => [
// just as an example
'Default',
'details',
],
]);
This does not work with addGroup
or addGroups
! Both of them won't accept associative arrays. setGroups
is your (only?) solution.
Upvotes: 0
Reputation: 1598
A solution for this is actually described in the official documentation.
That being said the solution proposed by @aferber seems better on many points: easier to maintain, less verbose, more flexible...
Upvotes: 2
Reputation: 1151
Unfortunately, you can't really (but keep reading ;-)), well at least not without changes to the serializer library. The culprit is that the list of groups is fixed within a GroupExclusionStrategy
(which is referenced by the Context
) the minute you start the serialization process. There is actually an assertion within the code that prevents modification of the exclusion strategy once the (de-)serialization is running.
But as it happens, I had the exact same problem in a project of mine as well, and I hacked the necessary changes into the serializer code. I have cleaned the code up a bit and uploaded it to Github (https://github.com/andreasferber/serializer/tree/recursion-groups).
It adds new property metadata with which you can add, remove or override the groups when descending into subobjects. With annotations it looks like this:
/**
* @Serializer\RecursionGroups(set={"foo", "bar"}, add={"baz"}, remove={"Default"})
*/
private $myProperty;
You should be able to use XML or Yaml metadata as well, however this is untested since I don't use them and I haven't added test cases yet. Have a look at the reference documentation. Since I haven't done any optimizations yet either, if your entities are really large and deeply nested, it might have a noticable performance impact.
Please let me know if you find this useful, or if you have any suggestions, because if this isn't only needed by me, I will add some tests and try to submit it upstream.
Upvotes: 7