---
title: Use API Resources for Response Transformation
impact: HIGH
impactDescription: prevents over-exposure of model fields, decouples DB schema from API contract, enables versioning
tags: api-resources, response, transformation, security, laravel
---

## Use API Resources for Response Transformation

Returning `$model->toArray()` or `response()->json($model)` exposes all model attributes including sensitive fields (`password`, `remember_token`, internal flags). API Resources control exactly what is serialized.

**Wrong:**

```php
// Exposes ALL columns including password, remember_token, internal flags
return response()->json($user);
return response()->json(User::all());
return response()->json($user->toArray());
```

**Correct:**

```bash
php artisan make:resource UserResource
php artisan make:resource UserCollection
```

```php
// app/Http/Resources/UserResource.php
class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id'         => $this->id,
            'name'       => $this->name,
            'email'      => $this->email,
            'avatar_url' => $this->avatar_url,
            'created_at' => $this->created_at->toIso8601String(),

            // Conditional fields
            'phone' => $this->when(
                $request->user()?->id === $this->id,
                $this->phone
            ),

            // Nested resource
            'posts_count' => $this->whenCounted('posts'),
        ];
    }
}

// Controller
public function show(User $user): UserResource
{
    return UserResource::make($user);
}

public function index(): JsonResponse
{
    $users = User::with('profile')->paginate(20);
    return UserResource::collection($users)->response();
}
```

**Password and sensitive fields must be in `$hidden`:**
```php
class User extends Model
{
    protected $hidden = ['password', 'remember_token', 'two_factor_secret'];
}
```
