Related resources of a relationship endpoint
jpoelmans opened this issue · comments
The Jsonapi specification states:
Furthermore, related resources can be requested from a relationship endpoint:
GET /articles/1/relationships/comments?include=comments.author HTTP/1.1
Accept: application/vnd.api+json
In this case, the primary data would be a collection of resource identifier objects that represent linkage to comments for an article, while the full comments and comment authors would be returned as included data.
But I can't get this working. Are includes on Resource Identifiers possible?
It seems to be a case nobody tried before 🎆
Currently, if you encode with identifiers you will get only identifiers and includes will be ignored. Here is a sample how it works (note despite EncodingParameters
has include for author
it is ignored)
public function testEncodeObjectAsResourceIdentityWithRelationships(): void
{
$comment = Comment::instance(1, 'One!');
$author = Author::instance(9, 'Dan', 'Gebhardt', [$comment]);
$comment->{Comment::LINK_AUTHOR} = $author;
$encoder = Encoder::instance([
Author::class => AuthorSchema::class,
Comment::class => CommentSchema::class,
], $this->encoderOptions);
$actual = $encoder->encodeIdentifiers($comment, new EncodingParameters(
// include `author` relationship
[Comment::LINK_AUTHOR]
));
$expected = <<<EOL
{
"data" : {
"type" : "comments",
"id" : "1"
}
}
EOL;
// remove formatting from 'expected'
$expected = json_encode(json_decode($expected));
$this->assertEquals($expected, $actual);
}
It looks like if include paths are given then encoder should put full resources into included.
Currently, the closest you can get is replacing encodeIdentifiers
with encodeData
. In this case you will get full comments
resources in data
section with authors
included.
Thanks for the response.
Using encodeData
is a solution for now, but it is not in compliance with the specification! Can this be a feature request for a next version?
Btw there's a PHPUnit assertion assertJsonStringEqualsJsonString
that can be used instead of doing that json_encode(json_decode(
trick.
@jpoelmans Before this point, it wasn't the case when we have the same resource in main data (type+id) and included (full resource). So it's likely to be more than just a small change. I'll keep this issue open as a task for the next major release.
I've got some update on this. I'm currently working on version 3 of the library. Currently, it's it is a promising prototype which can run the sample app (including performance test) and 75% of basic encoding tests (from EncodeSimpleObjectsTest.php
). So far performance is about +30% and it can encode correclty the test above
/**
* Test encode simple object as resource identity with included resources.
*/
public function testEncodeObjectAsResourceIdentityWithIncludes(): void
{
$comment = Comment::instance(1, 'One!');
$author = Author::instance(9, 'Dan', 'Gebhardt', [$comment]);
$comment->{Comment::LINK_AUTHOR} = $author;
$actual = Encoder::instance([
Author::class => AuthorSchema::class,
Comment::class => CommentSchema::class,
])
->withUrlPrefix('http://example.com')
->withIncludedPaths([Comment::LINK_AUTHOR])
->encodeIdentifiers($comment);
$expected = <<<EOL
{
"data" : {
"type" : "comments",
"id" : "1"
},
"included": [
{
"type" : "comments",
"id" : "1",
"attributes": {
"body": "One!"
},
"relationships": {
"author": {
"data": {
"type" : "people",
"id" : "9"
}
}
},
"links": {
"self": "http://example.com/comments/1"
}
}, {
"type" : "people",
"id" : "9",
"attributes": {
"first_name" : "Dan",
"last_name" : "Gebhardt"
},
"relationships": {
"comments": {
"data": [
{ "type" : "comments", "id" : "1" }
]
}
},
"links": {
"self": "http://example.com/people/9"
}
}
]
}
EOL;
self::assertJsonStringEqualsJsonString($expected, $actual);
}
BTW, @lindyhopchris thanks for assertJsonStringEqualsJsonString
it does look much better in IDE when comparing those jsons.
The issue is resolved in the next version of the library which is currently published in branch next
. Later it will be moved to develop
and then merged to master
.
merged to develop