tuyakhov/yii2-json-api

Have question about relationships.

yoyhosoft opened this issue · 10 comments

Without parameter

GET /v1/user

Response result:

{  
   "data":{  
      "id":"23",
      "type":"user",
      "attributes":{  
         "id":23,
         "username":"test_user",
         "email":"test@test.com",
         "created-at":1504866581,
         "updated-at":1507177386,
         "last-login-at":1507177386
      }
   }
}

With parameter

GET /v1/user?include=profile

Response result:

{  
   "data":{  
      "id":"23",
      "type":"user",
      "attributes":{  
         "id":23,
         "username":"test_user",
         "email":"test@test.com",
         "created-at":1504866581,
         "updated-at":1507177386,
         "last-login-at":1507177386
      },
      "relationships":{  
         "profile":{  
            "data":{  
               "id":"23",
               "type":"profile"
            }
         }
      }
   },
   "included":[  
      {  
         "id":"23",
         "type":"profile",
         "attributes":{  
            "name":"yyyooo",
            "firstname":"xxx",
            "lastname":"xxx",
            "public-email":null,
            "gender":"male",
            "age":null,
            "avatar":null,
            "created-at":1504866582,
            "updated-at":1507030787
         }
      }
   ]
}

Here is my model code

User.php

<?php

namespace common\models\api;

use Yii;
use tuyakhov\jsonapi\ResourceTrait;
use tuyakhov\jsonapi\ResourceInterface;

/**
 */
class User extends \common\models\User implements ResourceInterface
{
    use ResourceTrait;

    public function fields()
    {
        $fields = [
            'id' => 'id',
            'username' => 'username',
            'email' => 'email',
            'created_at' => 'created_at',
            'updated_at' => 'updated_at',
            'last_login_at' => 'last_login_at',
        ];

        return $fields;
    }

    public function extraFields()
    {
        return ['profile'];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProfile()
    {
        return $this->hasOne(Profile::className(), ['user_id' => 'id']);
    }
}

Profile.php

<?php

namespace common\models\api;

use Yii;
use tuyakhov\jsonapi\ResourceTrait;
use tuyakhov\jsonapi\ResourceInterface;

/**
 *
 */
class Profile extends \common\models\Profile implements ResourceInterface
{
    use ResourceTrait;

    public function fields()
    {
        $fields = [
            'name' => 'name',
            'firstname' => 'firstname',
            'lastname' => 'lastname',
            'public_email' => 'public_email',
            'gender' => 'gender',
            'age' => 'age',
            'avatar' => 'avatar',
            'created_at' => 'created_at',
            'updated_at' => 'updated_at',
        ];

        return $fields;
    }
}

Questions:

  1. aways need '?include=profile'?
  2. Result is correct?

Hi @yoyhosoft
Thank you for reporting this. It seems like a bug. Are you using v0.1.4?

Hi,
in composer.json I use this:

{
    ....
    "minimum-stability": "stable",
    "require": {
        ...
        "tuyakhov/yii2-json-api": "*"
    }
}

I see. But it is also about composer.lock. Could you please run composer show -i tuyakhov/yii2-json-api and send over the output? So we can see the version that is actually installed.

Here is result:

name     : tuyakhov/yii2-json-api
descrip. : Implementation of JSON API specification for the Yii framework
keywords : JSON-API, api, json, json api, rest, yii2
versions : * v0.1.4
type     : yii2-extension
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
source   : [git] https://github.com/tuyakhov/yii2-json-api.git f2bee3dd7201d1e2bfe50a666582e53d401f7d0f
dist     : [zip] https://api.github.com/repos/tuyakhov/yii2-json-api/zipball/f2bee3dd7201d1e2bfe50a666582e53d401f7d0f f2bee3dd7201d1e2bfe50a666582e53d401f7d0f
names    : tuyakhov/yii2-json-api

autoload
psr-4
tuyakhov\jsonapi\ => src/
tuyakhov\jsonapi\tests\ => tests/

requires
yiisoft/yii2 ^2.0.10

requires (dev)
phpunit/phpunit 5.5.*

Ok. So the result you are getting from the API is correct. This is how it was designed at least :)
If you want your API to always return the relationships object you should add LinksInterface to your models. So, for example, your User model will look like this:

class User extends \common\models\User implements ResourceInterface, LinksInterface
{
    use ResourceTrait;
    .....
}

And if you want related resources to be included in the response add ?include=relation-name. See http://jsonapi.org/format/#fetching-includes for details.

Thanks, but here is result

{  
   "data":{  
      "id":"23",
      "type":"user",
      "attributes":{  
         "id":23,
         "username":"test_user",
         "email":"test@test.com",
         "created-at":1504866581,
         "updated-at":1507177386,
         "last-login-at":1507177386
      },
      "relationships":{  
         "profile":{  
            "data":{  
               "id":"23",
               "type":"profile"
            },
            "links":{  
               "self":{  
                  "href":"http://api.base.lo/v1/user/view?id=23/relationships/profile"
               },
               "related":{  
                  "href":"http://api.base.lo/v1/user/view?id=23/profile"
               }
            }
         }
      },
      "links":{  
         "self":{  
            "href":"http://api.base.lo/v1/user/view?id=23"
         }
      }
   },
   "included":[  
      {  
         "id":"23",
         "type":"profile",
         "attributes":{  
            "name":"yyyooo",
            "firstname":"xxx",
            "lastname":"xxx",
            "public-email":null,
            "gender":"male",
            "age":null,
            "avatar":null,
            "created-at":1504866582,
            "updated-at":1507030787
         },
         "links":{  
            "self":{  
               "href":"http://api.base.lo/v1/user/profile?id=23"
            }
         }
      }
   ],
}

There're not include relationships object

I am not sure what you mean. It looks ok for me.

What I mean is relationships object should be like below or not:

{  
   "data":{  
      "id":"23",
      "type":"user",
      "attributes":{  
         "id":23,
         "username":"test_user",
         "email":"test@test.com",
         "created-at":1504866581,
         "updated-at":1507177386,
         "last-login-at":1507177386
      },
      "relationships":{  
         "profile":{  
            "data":{  
               "id":"23",
               "type":"profile"

               "attributes":{  
                  "name":"yyyooo",
                  "firstname":"xxx",
                  "lastname":"xxx",
                  "public-email":null,
                  "gender":"male",
                  "age":null,
                  "avatar":null,
                  "created-at":1504866582,
                  "updated-at":1507030787
               },

            }
         }
}

No, it is not how it should be according to JSON API specification.
Please check the specification http://jsonapi.org/format/ for more details.

Ah, I see.
Thanks a lot !!!