Laravel API Resources: Use whenLoaded() to Conditionally Include Relationships

📖 2 minutes read

When building Laravel API resources, accessing relationships directly can trigger N+1 queries if those relationships aren’t eager loaded. The whenLoaded() method provides an elegant solution.

The Problem

Consider this resource implementation:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->profile->display_name,  // ❌ May trigger query
            'email' => $this->profile->email,        // ❌ May trigger query
        ];
    }
}

If profile isn’t eager loaded, every resource instance will execute a separate database query, creating the classic N+1 problem.

The Solution

Use whenLoaded() to check if the relationship exists before accessing it:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->whenLoaded('profile', fn() => $this->profile->display_name),
            'email' => $this->whenLoaded('profile', fn() => $this->profile->email),
            'post_count' => $this->whenLoaded('posts', fn() => $this->posts->count()),
        ];
    }
}

Now the resource only accesses profile data when it’s already loaded:

// Without eager loading - fields are omitted
UserResource::collection(User::all());

// With eager loading - fields are included
UserResource::collection(User::with('profile', 'posts')->get());

Why This Matters

  • Performance: Prevents accidental N+1 queries when relationships aren’t needed
  • Flexibility: Same resource works with or without eager loading
  • Clean errors: No cryptic “trying to get property of null” errors when relations are missing

This pattern is especially valuable in API endpoints where clients can request different levels of detail via query parameters.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *