Laravel resource toArray() not working properly

Viewed 959

I've created a new API resource called UserResource:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        /** @var User $this */
        return [
            'first_name' => $this->first_name,
            'last_name' => $this->last_name,
            'email_verified_at' => $this->email_verified_at,
        ];
    }
}

And then I'm trying to get current user object and pass it to the resource:

class UserController extends Controller
{
    public function index(Request $request)
    {
        /** @var User $user */
        $user = $request->user();

        return new UserResource($user);
    }
}

But it always throws an exception Trying to get property 'first_name' of non-object. $user variable contains current user.

I'm using Xdebug and I checked that the resource contains formatted json in $this->resource, but not current user's model: enter image description here

So why? Laravel's documentation says that I'll be able to get current resource (User model in my case) in $this->resource parameter, but it does not work. Any ideas?

UPDATE: here is break point for xbedug in UserResource: enter image description here

3 Answers

It seems strange to me that you get the User object from the index's request and I reckon that somethings probably wrong there.

Normally, the index method is used to return a listing of all instances of the resp. model, e.g. something like

public function index() {
    return UserResource::collection(User::all());
}

Try to return a user object (as resource) which you are sure exists

$user = Users::findOrFail(1);
return new UserResource($user);

and see if the error still persists. If it does not, something is wrong with the data you pass in the request.

I had a look at the JsonResource Class. Look at the contructor:

public function __construct($resource)
    {
        $this->resource = $resource;
    }

Seems like the $user is saved to $this->resource. So you have to change your return statement to:

    return [
        'first_name' => $this->resource->first_name,
        'last_name' => $this->resource->last_name,
        'email_verified_at' => $this->resource->email_verified_at,
    ];

Does that work?

As @Clément Baconnier said in comments to the question, the right way to fix it is reinstalling vendor folder. The problem is that project has been created via Laravel new command from local with php 7.2, but there's php 7.4 in container.

Related