laravel-json-api / laravel

JSON:API for Laravel applications

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Relationship not showing up

genyded opened this issue · comments

OK, we're probably missing something simple here, but cannot seem to figure out what. We have two models User & Profile with a one-to-one relationship. The relationships work fine outside of JSONAPI (just standard Laravel). Our schemas are set up for both as follows:

<?php

namespace App\JsonApi\V1\Users;

use App\Models\User;
use LaravelJsonApi\Eloquent\Contracts\Paginator;
use LaravelJsonApi\Eloquent\Fields\DateTime;
use LaravelJsonApi\Eloquent\Fields\ID;
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
use LaravelJsonApi\Eloquent\Pagination\PagePagination;
use LaravelJsonApi\Eloquent\Schema;
use LaravelJsonApi\Eloquent\Fields\Relations\HasOne;

class UserSchema extends Schema
{

    /**
     * The model the schema corresponds to.
     *
     * @var string
     */
    public static string $model = User::class;


    /**
     * Get the resource fields.
     *
     * @return array
     */
    public function fields(): array
    {
        return [
            ID::make(),
            Str::make('firstName', 'first_name'),
            Str::make('lastName', 'last_name'),
            Str::make('email', 'email'),
            Str::make('password')->hidden()->hidden()->deserializeUsing(
                static fn($value) => bcrypt($value)
            ),
            Str::make('password_confirmation')->hidden(),
            Str::make('verification_token')->hidden(),
            Str::make('verified')->hidden(),
            Str::make('admin')->hidden(),
            DateTime::make('createdAt')->sortable()->readOnly(),
            DateTime::make('updatedAt')->sortable()->readOnly(),
            HasOne::make('profile')->readOnly()
        ];
    }

    /**
     * Get the resource filters.
     *
     * @return array
     */
    public function filters(): array
    {
        return [
            WhereIdIn::make($this),
        ];
    }

    /**
     * Get the resource paginator.
     *
     * @return Paginator|null
     */
    public function pagination(): ?Paginator
    {
        return PagePagination::make();
    }

}
<?php

namespace App\JsonApi\V1\Profiles;

use App\Models\Profile;
use LaravelJsonApi\Eloquent\Contracts\Paginator;
use LaravelJsonApi\Eloquent\Fields\DateTime;
use LaravelJsonApi\Eloquent\Fields\ID;
use LaravelJsonApi\Eloquent\Fields\Relations\BelongsTo;
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
use LaravelJsonApi\Eloquent\Pagination\PagePagination;
use LaravelJsonApi\Eloquent\Schema;

class ProfileSchema extends Schema
{

    /**
     * The model the schema corresponds to.
     *
     * @var string
     */
    public static string $model = Profile::class;

    /**
     * Get the resource fields.
     *
     * @return array
     */
    public function fields(): array
    {
        return [
            ID::make(),
            Str::make('avatar'),
            Str::make('bio'),
            DateTime::make('createdAt')->sortable()->readOnly(),
            DateTime::make('updatedAt')->sortable()->readOnly(),
            BelongsTo::make('user')->readOnly(),
        ];
    }

    /**
     * Get the resource filters.
     *
     * @return array
     */
    public function filters(): array
    {
        return [
            WhereIdIn::make($this),
        ];
    }

    /**
     * Get the resource paginator.
     *
     * @return Paginator|null
     */
    public function pagination(): ?Paginator
    {
        return PagePagination::make();
    }

}

When we query a user though, there is no reference at all to the profile:

{
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "http://localhost/api/users/1"
  },
  "data": {
  "type": "users",
   "id": "1",
   "attributes": {
     "firstName": "User",
     "lastName": "One",
      "email": "user1@email.com"
    },
    "links": {
      "self": "http://localhost/api/users/1"
    }
  }
}

There are no errors, and from the JSONAPI tutorial, we think we have all the pieces in place for this to work. So, what are we missing here?

By default you need to explicitly require the profile relationship in order for it to be included.

http://localhost/api/users/1?include=profile

https://jsonapi.org/format/#fetching-includes

Actually, that is for inclusion of the related data, not the links. Anyway, we figured it out. We had to add the relationships in the JSONAPI Resource files, but it seems the tutorial skips over that part. Closing since resolved.

<?php

namespace App\JsonApi\V1\Users;

use Illuminate\Http\Request;
use LaravelJsonApi\Core\Resources\JsonApiResource;

class UserResource extends JsonApiResource
{

    /**
     * Get the resource's attributes.
     *
     * @param Request|null $request
     * @return iterable
     */
    public function attributes($request): iterable
    {
        return [
            'firstName' => $this->first_name,
            'lastName' => $this->last_name,
            'email' => $this->email,
            $this->mergeWhen(auth('api')->user() && auth('api')->user()->isAdmin(), [
                'admin' => $this->admin,
                'createdAt' => $this->created_at,
                'updatedAt' => $this->updated_at

            ]),


            //'verificationToken' => $this->when($this->isAdmin() || (auth('api')->user() && auth('api')->user()->isAdmin()), $this->admin),
            //'createdAt' => $this->when(auth('api')->user() && auth('api')->user()->isAdmin(), $this->created_at),
            //'updatedAt' => $this->when(auth('api')->user() && auth('api')->user()->isAdmin(), $this->updated_at)
        ];
    }

    /**
     * Get the resource's relationships.
     *
     * @param Request|null $request
     * @return iterable
     */
    public function relationships($request): iterable
    {
        return [
            $this->relation('profile'),
        ];
    }

}