example-articles-api icon indicating copy to clipboard operation
example-articles-api copied to clipboard

Relationships returning incorrect data

Open genyded opened this issue 7 years ago • 0 comments

I believe that the 'relationships' urls are returning incorrect data per the JSON API spec. For example:

http://127.0.0.1:8000/api/articles/1/relationships/comments

currently returns (this is what http://127.0.0.1:8000/api/articles/1/comments should return and does):

{
  data: [
    {
      type: "comments",
      id: "1",
      attributes: {
        body: "Now you know.' 'I DON'T know,' said Alice, surprised at her own children. 'How should I 
        know?' said Alice, rather doubtfully, as she spoke; 'either you or your head must be getting 
        somewhere near."
      },
      relationships: {
        author: {
          data: {
            type: "people",
            id: "7"
          }
        }
      },
      links: {
        self: "http://127.0.0.1:8001/api/comments/1"
      }
    }
  ],
  links: {
    self: "http://127.0.0.1:8001/api/comments"
  },
  included: [
    {
      type: "people",
      id: "7",
      attributes: {
        first-name: "Neoma",
        last-name: "White",
        twitter: "clementine47"
      },
      links: {
        self: "http://127.0.0.1:8001/api/authors/7"
      }
    }
  ]
}

According to the spec. the relationship URL should return something like this:

{
  data: [
    {
      type: "comments",
      id: "1"
    }
  ],
  links: {
    self: "http://127.0.0.1:8001/api/articles/1/relationships/comments",
    related: "http://127.0.0.1:8001/api/articles/1/comments"
  }
}

The purpose being to allowing users to update, delete, etc the relationship(s) without affecting the actual underlying resource(s).

Fixing this would require a few changes:

  1. Modifying the route for this (or any relationship routes) to call a new controller method:
Route::get(
    'articles/{article}/relationships/comments',
    [
        'uses' => \App\Http\Controllers\ArticleRelationshipController::class . '@related_comments',
        'as' => 'articles.relationships.comments',
    ]
);
  1. Adding the controller method(s):
public function related_comments(Article $article)
{
    return new ArticleCommentsRelationshipResource($article->comments);
}
  1. Fixing another bug in the relationship resource file(s) to get the Article, and removing the 'with' in the relationship resource file(s):
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class ArticleCommentsRelationshipResource extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request
     *
     * @return array
     */
    public function toArray($request)
    {
        $article = $request->article; // this was $article = $this->additional['article'];

        return [
            'data'  => CommentIdentifierResource::collection($this->collection),
            'links' => [
                'self'    => route('articles.relationships.comments', ['article' => $article->id]),
                'related' => route('articles.comments', ['article' => $article->id]),
            ],
        ];
    }

    /* public function with($request)
    {
        return [
            'links' => [
                'self' => route('articles.index'),
            ],
        ];
    } */
}

genyded avatar Dec 14 '18 16:12 genyded