cloudcreativity / laravel-json-api

JSON API (jsonapi.org) package for Laravel applications.
http://laravel-json-api.readthedocs.io/en/latest/
Apache License 2.0
780 stars 109 forks source link

Relationship hydrate: where? #523

Closed smarques closed 4 years ago

smarques commented 4 years ago

Hi and thanks for this great package. I am trying to understand how to include full data for a relation.

I have set the include param correctly in my GET request I have added

 public function getRelationships($product, $isPrimary, array $includeRelationships)
    {
        return [
            'supplier' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                self::SHOW_DATA => isset($includeRelationships['supplier']),
                self::DATA => function () use ($product) {
                    return $product->supplier;
                },
            ]
        ];
    }

to the schema file.

But all I am getting in the response is:

"relationships": {
                "supplier": {
                    "data": {
                        "type": "suppliers",
                        "id": "1"
                    },
                    "links": {
                        "self": "http://localhost/api/products/11/relationships/supplier",
                        "related": "http://localhost/api/products/11/supplier"
                    }
                }

I would like to hydrate the relation and send the full supplier record along, but I am not sure how to do it.

Also, I am very curious: where is the schema getRelationships() method called? (could not figure it out myself)

Thank you so much

ben221199 commented 4 years ago

Relationships only show id and type, no attributes or their relationships. If you want to hydrate the attributes and relationships of that resource, use the included thing at the root of the JSON: https://jsonapi.org/format/#fetching-includes

smarques commented 4 years ago

Thank you @ben221199

lironesamoun commented 4 years ago

I have already used include but I still get the id and the type of the relationship, not its attributes. What do you mean by "the root of the JSON" ?

ben221199 commented 4 years ago

When you have a resource (or an array of resources), they are placed under data in the root of the JSON. If you want to link a resource to other resources, they will be placed under relationships inside the resource. However, that resources under relationships will only show an id and a type. This is done to prevent infinite resource nesting. If you also want to see the attributes and relationships of the resource, the resource should be placed in the included array in the root of the JSON.

Example:

{
    "data":{
        "id": "1",
        "type": "book",
        "attributes":{
            "title": "My cool book title",
            "isbn": "987-90-1234-567-?"
        },
        "relationships":{
            "author":{
                "data":{
                    "id": "23",
                    "type": "user"
                }
            },
            "pages":{
                "data":[
                    {
                        "id": "124",
                        "type": "page"
                    },
                    {
                        "id": "125",
                        "type": "page"
                    }
                ]
            }
        }
    },
    "included": [
        {
            "id": "23",
            "type": "user",
            "attributes":{
                "name": "Cool author name",
                "age": 37
            }
        },
        {
            "id": "124",
            "type": "page",
            "attributes":{
                "number": 1
            },
            "relationships":{
                "book":{
                    "data":{
                        "id": "1",
                        "type": "book"
                    }
                }
            }
        },
        {
            "id": "125",
            "type": "page",
            "attributes":{
                "number": 2
            },
            "relationships":{
                "book":{
                    "data":{
                        "id": "1",
                        "type": "book"
                    }
                }
            }
        }
    ]
}

Here, data and included are in the root of the JSON, directly inside the beginning{ and ending }.

lindyhopchris commented 4 years ago

Yeah, just to follow on from that... the data member of a relationship is always a resource identifier - resource identifiers only contain type and id members.

If you use the include query parameter, the server returns a compound document. The primary data requested will be in the data member. Relationships that are included will have a data member with a resource identifier that references a resource that is contained in the top-level included member.

lironesamoun commented 4 years ago

@ben221199 yes I saw that on the Json API specification. However, I guess that I need to manually implemented as I did not see a way to do that with Laravel Json Api.

Thank guys for your clarification ! Make sense !

lindyhopchris commented 4 years ago

@lilouch include paths are fully supported by this package. You just need to use the include query parameter when requesting resources. Have you tried that?

lironesamoun commented 4 years ago

Yes but my bad, I did not noticed the included tag at the end as my response was long ! Thank a lot for this insight !