Reputation: 859
I have Post and User model with one to one relation and it works well:
//User.php
public function post(){
return $this->hasOne(Post::class);
}
// Post.php
public function user() {
return $this->belongsTo(User::class);
}
now I create API resources:
php artisan make:resource Post
php artisan make:resource User
I need to return all post with an API call then I set my route:
//web.php: /resource/posts
Route::get('/resource/posts', function () {
return PostResource::collection(Post::all());
});
This is my Posts resource class:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
use App\Http\Resources\User as UserResource;
class Posts extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'bodys' => $this->body,
'users' => UserResource::collection($this->user),
'published' => $this->published,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
This is the error:
Call to undefined method Illuminate\Database\Query\Builder::mapInto()
if I remove:
'users' => UserResource::collection($this->user),
it works but I need to include relations in my API JSON, I have read and followed the doc at https://laravel.com/docs/5.5/collections.
This is my User resource class:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class User extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'user_id' => $this->user_id,
'name' => $this->name,
'lastname' => $this->lastname,
'email' => $this->email
];
}
}
Any ideas where I am wrong?
Upvotes: 61
Views: 69503
Reputation: 2573
use make
instead of collection
;
because your relation is belongTo
(one to one) and it is one record ** is not a collection** .when relation is hasMany
or morphTomany
use collection
.
use
UserResource::make($this->user)
instead
UserResource::collection($this->user)
Upvotes: 1
Reputation: 1152
The issue is that you use UserResource::collection($this->user) and you have just one element come from database, not list of collection. It would be solved if you used new UserResource($this->user) like this:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
use App\Http\Resources\User as UserResource;
class Posts extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'bodys' => $this->body,
'users' => new UserResource($this->user),
'published' => $this->published,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
Upvotes: 5
Reputation: 281
this problem is that you use UserResource::collection($this->user)
it mean you have many users but and you have just one element for the a single resource and not a collection so you can replace it with new UserResource($this->user)
Upvotes: 14
Reputation: 81
when you have just one element and not a collection use new Resouce
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'user' => new UserResource($this->whenLoaded('user')),
];
and give a try to use the eager loading for better perfomance not just this. using the method whenLoaded and put the relations name in ( ).
Resource::collection is used when the model has hasMany relation. If your model has hasOne relation use Resource::make(Book::all())
Upvotes: 6
Reputation: 426
In Laravel 8.5.*, you can use the static method make
on the collection to get the same result. It would be like UserResource::make($this->user)
Upvotes: 13
Reputation: 11083
The problem is that you use UserResource::collection($this->user)
and you have just one element not a collection so you can replace it with new UserResource($this->user)
like this :
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'bodys' => $this->body,
'users' => new UserResource($this->user),
'published' => $this->published,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
Upvotes: 154