phplaravelapieloquentresources

Can't return multi-level resource/collection through API


Question: How do I return values of a resource through another resource? If I have a pivot table inbetween (many to many relationship), does something change, other than the model function $this->hasMany(AnotherModel::class, 'pivottable') ?

For example:

There's a table called "tags", and another table called "tagtranslations"

"tag" only has an ID and timestamps "tagtranslations" has id, tag_id, title, slug and timestamps

There are TagResource and TagTranslationResource

In TagTranslationResource I'm returning the "toArray"

public function toArray($request)
    {
        return parent::toArray($request);
    }
}

and in TagResource I'm returning

return          
        [
            'id' => $this->id,
            'title' => TagTranslationResource::collection($this->title),
            'slug' =>  TagTranslationResource::collection($this->slug)
        ];

and in Controller I'm calling back Tag with tagtranslations

public function index(Request $request)
    {

        $tags = Tag::with('tagtranslation')->get();
        //return $tags;

        return TagResource::collection($tags);
    }

when, in TagResource I call, for example


return [
  'title' => new TagResource($this->title),
  'slug'  => new TagResource($this->slug)
]

I only get null fields in my JSON api response

and the response I get for the

'title' => TagTranslationResource::collection($this->title)

is an error "Call to a member function first() on null"

Can someone please explain what's happening here? :D I also tried with TagResource::collection(TagTranslation::all())->$this->title

but it can't convert to string


Solution

  • If i understand it correctly the problem is: TagTranslationResource::collection() expect to receive a collection and you are passing just the title and the slug.

    How would I do it:

    Controller

    public function index(Request $request)
    {
      return TagResource::collection(
        Tag::with('tagtranslation')->get()
      );
    }
    

    TagResource:

    return [ 
      'id' => $this->id,
      'any_other_tag_field' => $this->any_other_tag_field, 
      'tagtranslation' => TagTranslationResource::collection($this->tagtranslation),
    ];
    

    TagTranslationResource:

    return [
      'title' => $this->title,
      'slug'  => $this->slug
    ]
    

    If you want to know a bit more, here is the link of the official docs

    And here an article I wrote about api resources.

    I hope it help you.