neomerx / json-api

Framework agnostic JSON API (jsonapi.org) implementation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Include related resource into output in its entirety?

AnrDaemon opened this issue · comments

We're trying to reduce load on our backend by reducing the number of calls related to searching.
Search request itself is heavy enough already, but for each resource in the response, we need to provide parent object for identification.
The idea was to use $resource->setRelationship("parent", $parent), but the output only contains id and type of the relation, which is about as useful, as starlight at noon.
Is there a way to deliver the data in a more elegant and useful way?

  1. Prepare your data accordingly (your ancestors and antecedents should have links to each other).
  2. Add descriptions for those relationships to their Schemas.
  3. Encode data as you usually do.

For example,

// 1)
$comment = ...;
$author  = ...;

$comment->author = $author;
$author->comments = [$comment];

2)
// Modify your AuthorSchema::getRelationships and
// CommentSchema::getRelationships accordingly
//
// @link https://github.com/neomerx/json-api/wiki/Schemas

3)
// Encode $author
// @link https://github.com/neomerx/json-api/wiki#encode

Hmm... It's likely not related. If I understand it correctly, you have resources linked to each other (e.g. both comment and author have links/relationships to each other) and want to encode them exactly this way. The lib can encode such data with no probs and you can do it as I described earlier. The sample application demonstrates exactly this case here.

I want to provide both objects in a single response.
Right now, I have to hack it like

class ObjectSchema extends BaseSchema
{
    public function getAttributes($resource): iterable
    {
        // FIXME:jsonapi Fake object composition
        $parent = $resource->getRelationship("parent");
        if (!empty($parent)) {
            $parent = array_shift($parent);
            $attributes["parent_object"] = [
                "type" => $this->getType($parent),
                "id" => $this->getId($parent),
                "attributes" => $this->getAttributes($parent),
                //"links" => $this->getLinks($resource->parent),
            ];
        }

        return $attributes;

I don't have access to encoder directly, it's somewhere deep inside pipeline.

It's likely not related.

That's the code that runs when related objects are encoded in response. It simply not supposed to return objects' attributes, at all.

You'd better read the spec first. That's not how it works. Attributes contain neither parent's identifiers nor properties. The parent's identifiers go to relationships and their properties (attributes) go to included. I do recommend you have a look at least at JSON API examples, run the sample app I mentioned and understand the logic of how data are linked.

Given microscopic amount of relevant information in specification, and even smaller - in your library documentation, I'm unable to make any sense of your explanation, sorry.
And the fact our project uses zend-expressive stack does not make it any easier.
Specifically, I was reading https://jsonapi.org/format/#document-compound-documents , but were unable to make connections in your library API.

The library wiki implies that a reader understands the spec to a certain degree and helps to get the result as in the spec.
I think it would be easier to help you if you provide sample data resources, I can help to show how JSON API could be used to represent them and then how to use the lib to actually encode the data. Can you provide some data sample?

I can't promise a timely response, sorry. But I will see what I can cook up.

OK, let me know when you're ready and I'll reopen the issue. Lots of data is not needed. Just a few typical resources and relationships between them. Typical relationships are one-to-many, belongs-to, belongs-to-many.

Turned out, it had to have configuration in 3 different places to work, and even then require additional manual labor (but this one due to underlying database structure, since I'm not linking data by primary key).