DEV Community

Cover image for Getting Started with Laravel API Resources for Clean JSON Responses In Laravel

Getting Started with Laravel API Resources for Clean JSON Responses In Laravel

“Clean code always looks like it was written by someone who cares.”
-- Michael Feathers

Key Takeaways

  • API Resources format and clean your JSON responses.
  • They help separate transformation logic from controller logic.
  • Supports nested relationships and conditional fields.
  • You can disable default data wrapping.
  • Adds meta information like API version easily.

Index

  1. What is a Resource?
  2. Creating a Resource
  3. make() vs collection()
  4. Loading Relationships with Resources
  5. Hiding Data with Resources
  6. Best Practices
  7. Interesting Facts
  8. FAQ’s
  9. Conclusion

1. What is a Resource?

A Resource in Laravel is a way to transform your Eloquent models into a customized array or JSON structure. It allows you to:

  • Hide sensitive fields
  • Format data (e.g., timestamps)
  • Include related models (relationships)
  • Maintain consistency in API responses

Default JSON without resource:

{ "id": 1, "name": "John", "email": "john@example.com", "email_verified_at": "2024-01-01", "created_at": "2024-01-01T00:00:00.000000Z", "updated_at": "2024-01-01T00:00:00.000000Z" } 
Enter fullscreen mode Exit fullscreen mode

With a resource:

{ "id": 1, "name": "John" } 
Enter fullscreen mode Exit fullscreen mode

2. Creating a Resource

Generate a resource with Artisan:

php artisan make:resource UserResource 
Enter fullscreen mode Exit fullscreen mode

It creates a file in:

app/Http/Resources/UserResource.php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class UserResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, ]; } } 
Enter fullscreen mode Exit fullscreen mode

Use it in a controller:

use App\Http\Resources\UserResource; use App\Models\User; public function show($id) { return new UserResource(User::findOrFail($id)); } 
Enter fullscreen mode Exit fullscreen mode

3. make() vs collection()

Using make() for a Single Model
Controller:

public function show($id) { $user = User::findOrFail($id); return UserResource::make($user); } 
Enter fullscreen mode Exit fullscreen mode

Output:

{ "id": 1, "name": "John Doe", "email": "john@example.com" } 
Enter fullscreen mode Exit fullscreen mode

Using collection() for Multiple Models
Controller:

public function index() { $users = User::all(); return UserResource::collection($users); } 
Enter fullscreen mode Exit fullscreen mode

Output:

[ { "id": 1, "name": "John Doe", "email": "john@example.com" }, { "id": 2, "name": "Jane Doe", "email": "jane@example.com" } ] 
Enter fullscreen mode Exit fullscreen mode

make() → single object
collection() → list of objects

4. Loading Relationships with Resources

Example: User has one Profile
User.php

public function profile() { return $this->hasOne(Profile::class); } 
Enter fullscreen mode Exit fullscreen mode

Profile.php

public function user() { return $this->belongsTo(User::class); } 
Enter fullscreen mode Exit fullscreen mode

Create ProfileResource

php artisan make:resource ProfileResource 
Enter fullscreen mode Exit fullscreen mode
class ProfileResource extends JsonResource { public function toArray($request) { return [ 'bio' => $this->bio, 'twitter' => $this->twitter, ]; } } 
Enter fullscreen mode Exit fullscreen mode

Include Profile in UserResource

use App\Http\Resources\ProfileResource; class UserResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'profile' => new ProfileResource($this->whenLoaded('profile')), ]; } } 
Enter fullscreen mode Exit fullscreen mode

Controller:

public function show($id) { $user = User::with('profile')->findOrFail($id); return UserResource::make($user); } 
Enter fullscreen mode Exit fullscreen mode

Output:

{ "id": 1, "name": "John Doe", "email": "john@example.com", "profile": { "bio": "Developer at Example", "twitter": "@johndoe" } } 
Enter fullscreen mode Exit fullscreen mode

Without with(‘profile’) in controller:

 { "id": 1, "name": "John Doe", "email": "john@example.com", "profile": null } 
Enter fullscreen mode Exit fullscreen mode

Why use whenLoaded() ?

  • Prevents unnecessary DB queries (lazy loading)
  • Allows optional inclusion of relationships based on controller logic

5. Hiding Data with Resources

Let’s say we want to hide the user’s password and timestamps:

public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, // Email is optional 'email' => $this->when(request()->user()->isAdmin(), $this->email), ]; } 
Enter fullscreen mode Exit fullscreen mode

You can also use:

  • when()
  • mergeWhen()
  • whenLoaded() for relationships

“Creativity is thinking up new things. Innovation is doing new things.”
-- Theodore Levitt

6. Best Practices

  • Use resources for APIs, not inside Blade views.
  • Keep transformations lightweight and readable.
  • Use nested resources for relationships.
  • Use whenLoaded() to avoid empty/null relationship issues.

“Success is the sum of small efforts, repeated day in and day out.”
-- Robert Collier

7. Interesting Facts

8. FAQ’s

Q: Should I use Resources in internal tools?
A: Yes, if they’re API-driven. It keeps things consistent.

Q: Can I return extra metadata?
A: Yes:

return (new UserResource($user))->additional([ 'meta' => ['version' => '1.0.0'] ]); 
Enter fullscreen mode Exit fullscreen mode

Q: Can I use a resource without a model?
A: Yes, you can wrap any array of data:

return JsonResource::make([ 'message' => 'Success', 'data' => [...] ]); 
Enter fullscreen mode Exit fullscreen mode

9. Conclusion

Laravel API Resources provide a powerful and clean way to structure JSON responses in APIs. They make your controllers leaner, your API more consistent, and your data transformation more manageable. Use them to deliver beautiful, reliable API output every time.

About the Author: Vatsal is a web developer at AddWebSolution. Building web magic with Laravel, PHP, MySQL, Vue.js & more.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.