Hi,
I have a class Foo with field id and a parentId (which refer to a Foo object on ManyToOne) ,
itemOperations={
* "get"={"method"="GET", "normalization_context"={"groups"={"read"}}},
...
class Foo
{
/**
* @var int The id of this content
*
* @ORM\Id
* @ORM\Column(type="guid")
* @Assert\Uuid
* @Groups({"read"})
*/
private $id;
...
* @Groups({"read"})
private $name;
/**
* @var parentTranslateId[] The translate parent ID of this content
*
* @ORM\ManyToOne(targetEntity="Foo")
* @Groups({"read"})
*/
private $parentTranslateId;
}
If I want to add group on normalization context, the api result give me a Foo object embed to another Foo, or I want an IRI link
How to make serializer groups not recursive ?
Don't put a group on the ManyToOne relation. You can also use MaxDepth.
Hi @soyuka,
Thanks for your reply
I need groups because I have some fields to hide. Remove the group only hide the field but i need a IRI value.
MaxDepth is for object with multi level embed no ? For me it's at the first level of my main object, MaxDepth as no effect on my parentTranslate field.
Then you should use a second group for the relation.
itemOperations={
* "get"={"method"="GET", "normalization_context"={"groups"={"read", "read_child"}}},
* @Groups({"read", "read_child"})
private $id; //on id put the two groups
//rest properties only `read` group
* @ORM\ManyToOne(targetEntity="Foo")
* @Groups({"read_child"})
Should do the trick I think
I have already try it but it doesn't work
@soyuka if you want try I make an exemple : https://github.com/Tim59/api-platform.git
just a fork of api platform with a simple Entity Foo. With 2 differents groups read and read_child, it does not work
Ping @soyuka , sorry but i'm on a big project and I think your solution to use different groups may work but there is a bug
@Tim59 I'll take a look at your fork, were you able to reproduce the bug there?
@soyuka Thanks , Yes I have reproduce the bug on the fork
@soyuka have you time to try it ? thank's
So, indeed if I remove every groups I'm retrieving a simple string as id. Though, if there are groups, you'll get an object. I'm not sure that this should be considered as a bug or a feature.
May I ask why is it an issue to have an object instead of a string? Note that it won't get the full object back if the serialization group only uses the identifier.
ping @api-platform/core-team wdyt?
@soyuka , in fact , we have a very complex entity which refers to itself with a parent attribute.
If we let like this, when we do a get of this entity, API platform displays our complex structure json Entity including a complex structure json entity which is the parent attribute. Or we do not want to display the parent, only his IRI.
We use @Groups to select only field we want to display, including the parent attribute. But of course, recursively, the normalizer displays the parent's attribute....
Need advice about this part ^^
@jordscream As the Entity is referencing itself, it seems logic (to me) that the groups apply recursively, and therefore you'll get every fields serialized by the root entity. It might be that you'd have to write your own normalizer for this use case, or maybe @teohhanhui has a better solution?
Maybe https://github.com/api-platform/docs/issues/152 can be interesting.
@soyuka thank's but don't think that can help me, @dunglas or @teohhanhui any other ideas ?
I would use a custom normalizer storing the recursion level for such use case. I don't think we can use a generic solution for this.
Indeed I've tried to use max_depth and find it very limiting... At least there should be a way to normalize to IRI when max_depth is reached. And also max_depth 0 to indicate that we don't want to even recurse in (a.k.a. just serialize as IRI).
Once #1980 is fixed, this can be implemented as follows:
class Foo
{
/**
* @ORM\ManyToOne(targetEntity="Foo")
* @Groups({"read"})
* @ApiProperty(readableLink=false, writableLink=false)
*/
private $parent;
}
which will generate an IRI for the parent instead of embedding it (this will work for any property to control embedding, not only for self-referencing properties).
In the mean time, you can workaround #1980 and achieve the same result by using something like this https://gist.github.com/oxan/5a9ba44e72bbeae5fa1aee7d0be0b337 and applying the @NotEmbedded annotation to the $parent property (this works for any property as well).
@oxan I am using the latest version of api-platform but setting @ApiProperty(readableLink=false, writableLink=false) doesn't seem to be doing anything. Any advice on this? Thanks
@essencious I don't think the fix for #1980 has actually landed in a released version yet.
https://github.com/api-platform/core/commit/f7b9079057c8250e41f6dc36784b14ba74b3a98d it can't really be merged in 2.x because of https://github.com/api-platform/core/pull/1997#issuecomment-415184772 :|
@soyuka @oxan thanks for your responses. I'll keep an eye out for future releases.
Then you should use a second group for the relation.
itemOperations={ * "get"={"method"="GET", "normalization_context"={"groups"={"read", "read_child"}}}, * @Groups({"read", "read_child"}) private $id; //on id put the two groups //rest properties only `read` group * @ORM\ManyToOne(targetEntity="Foo") * @Groups({"read_child"})Should do the trick I think
@soyuka How do I do the child group to get only few properties in same entity reference ?
Most helpful comment
Once #1980 is fixed, this can be implemented as follows:
which will generate an IRI for the parent instead of embedding it (this will work for any property to control embedding, not only for self-referencing properties).
In the mean time, you can workaround #1980 and achieve the same result by using something like this https://gist.github.com/oxan/5a9ba44e72bbeae5fa1aee7d0be0b337 and applying the
@NotEmbeddedannotation to the$parentproperty (this works for any property as well).