“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
- What is a Resource?
- Creating a Resource
- make() vs collection()
- Loading Relationships with Resources
- Hiding Data with Resources
- Best Practices
- Interesting Facts
- FAQ’s
- 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" }
With a resource:
{ "id": 1, "name": "John" }
2. Creating a Resource
Generate a resource with Artisan:
php artisan make:resource UserResource
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, ]; } }
Use it in a controller:
use App\Http\Resources\UserResource; use App\Models\User; public function show($id) { return new UserResource(User::findOrFail($id)); }
3. make() vs collection()
Using make()
for a Single Model
Controller:
public function show($id) { $user = User::findOrFail($id); return UserResource::make($user); }
Output:
{ "id": 1, "name": "John Doe", "email": "john@example.com" }
Using collection()
for Multiple Models
Controller:
public function index() { $users = User::all(); return UserResource::collection($users); }
Output:
[ { "id": 1, "name": "John Doe", "email": "john@example.com" }, { "id": 2, "name": "Jane Doe", "email": "jane@example.com" } ]
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); }
Profile.php
public function user() { return $this->belongsTo(User::class); }
Create ProfileResource
php artisan make:resource ProfileResource
class ProfileResource extends JsonResource { public function toArray($request) { return [ 'bio' => $this->bio, 'twitter' => $this->twitter, ]; } }
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')), ]; } }
Controller:
public function show($id) { $user = User::with('profile')->findOrFail($id); return UserResource::make($user); }
Output:
{ "id": 1, "name": "John Doe", "email": "john@example.com", "profile": { "bio": "Developer at Example", "twitter": "@johndoe" } }
Without with(‘profile’) in controller:
{ "id": 1, "name": "John Doe", "email": "john@example.com", "profile": null }
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), ]; }
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
- You can nest as many resource layers as needed. (Laravel API Resources - Nested Resources)
- Can be reused between web and API if structured correctly. (Laravel API Resources Overview)
- Works well with Laravel Pagination for out-of-the-box data/links/meta output. (Laravel Pagination with Resources)
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'] ]);
Q: Can I use a resource without a model?
A: Yes, you can wrap any array of data:
return JsonResource::make([ 'message' => 'Success', 'data' => [...] ]);
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.