resources
API resource classes that transform Eloquent models into JSON-ready arrays. Resources control exactly what is exposed in API responses and handle relationships, conditional attributes, and date format
SKILL.mdresources/boost/skills/resources/SKILL.md
GitHubResources
When to Apply
- Apply when API endpoints return Eloquent models or model collections as JSON.
- Apply when response fields must be explicitly whitelisted and conditionally included.
- Do not use for internal CLI output, file downloads, binary responses, or non-JSON rendering.
Preconditions
- Resource classes can be created in
app/Http/Resources/. - Models and required relationships are loaded before resource transformation.
- Controller/service owns query execution; resource owns serialization only.
Process
1. Create the Appropriate Resource Type
- Use
ModelResource(for exampleUserResource) for single entities. - Use
UserResource::collection(...)for simple lists. - Create a dedicated
ResourceCollectiononly when custom top-level meta is required.
2. Build a Safe toArray() Contract
- Expose only fields needed by API consumers.
- Use
whenLoaded()for relationships. - Use
when(),whenHas(),whenNotNull(), andmergeWhen()for conditional fields.
3. Keep Loading and Queries Outside Resources
- Eager-load in controllers/services before passing models to resources.
- Never trigger additional queries inside
toArray().
4. Verify Response Shape
- Check pagination and links by returning paginator instances directly.
- Confirm role/permission-based fields are hidden for unauthorized users.
Examples
class UserResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts' => PostResource::collection($this->whenLoaded('posts')),
'secret' => $this->when($request->user()->isAdmin(), $this->secret),
'bio' => $this->whenNotNull($this->bio),
'created_at' => DateHelper::format($this->created_at),
];
}
}
// Critical: eager-load in controller before passing to resource.
return UserResource::collection(User::with('posts')->paginate());
// Dedicated collection — only when custom meta is needed
class UserCollection extends ResourceCollection
{
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => ['self' => route('users.index')],
];
}
}
Checklists
- Resource exposes only required public API fields.
- Relationships are eager-loaded before resource transformation.
-
toArray()has no DB queries or lazy-load triggers. - Conditional fields use
when*helpers. - Pagination meta is framework-provided, not manually duplicated.
Anti-Patterns
- Exposing all model attributes without whitelisting
- Eager/lazy loading relationships inside
toArray()(causes N+1 query issues) - Using
ifstatements inside the response array instead ofwhen(),whenLoaded(),whenNotNull() - Creating a dedicated collection class just for a simple list (use
UserResource::collection()) - Putting business logic or database queries in a resource
- Manually adding pagination meta that Laravel already provides automatically
References
- Laravel API Resources
resources/boost/skills/controllers/SKILL.md(query/loading responsibilities)resources/boost/skills/helpers/SKILL.md(formatting helpers used in resources)