# API Response Trait - Usage Guide

This guide explains how to use the `HasApiResponse` trait for standardized API responses.

## Overview

The `HasApiResponse` trait provides consistent JSON response formatting across all API controllers. It handles:
- Success responses with data
- Error responses with proper status codes
- Paginated responses
- Collection responses
- Validation errors
- Standard HTTP status codes

## Installation

The base API controller is already available at `app/Http/Controllers/API/BaseController.php`. All API controllers should extend this base controller.

## Basic Usage

### 1. Extend BaseController

All API controllers should extend `BaseController` instead of `Controller`. The `BaseController` already includes the `HasApiResponse` trait, so you don't need to add it manually.

```php
<?php

namespace App\Http\Controllers\API\Admin;

use App\Http\Controllers\API\BaseController;
use App\Models\User;
use App\Http\Resources\Admin\UserResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class UserController extends BaseController
{
    // ... your methods
    // All response methods (successResponse, errorResponse, etc.) are available
}
```

**Note:** The `BaseController` automatically provides all response methods from the `HasApiResponse` trait, so you don't need to add `use HasApiResponse;` in your controllers.

## Response Methods

### Success Responses

#### `successResponse()`
Generic success response with data.

```php
public function show(int $id): JsonResponse
{
    $user = User::findOrFail($id);
    return $this->successResponse(
        new UserResource($user),
        'User retrieved successfully'
    );
}
```

**Response:**
```json
{
    "success": true,
    "message": "User retrieved successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com"
    }
}
```

#### `createdResponse()`
For created resources (201 status).

```php
public function store(StoreUserRequest $request): JsonResponse
{
    $user = User::create($request->validated());
    return $this->createdResponse(
        new UserResource($user),
        'User created successfully'
    );
}
```

**Response:**
```json
{
    "success": true,
    "message": "User created successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com"
    }
}
```
*Status Code: 201*

#### `updatedResponse()`
For updated resources.

```php
public function update(UpdateUserRequest $request, int $id): JsonResponse
{
    $user = User::findOrFail($id);
    $user->update($request->validated());
    return $this->updatedResponse(
        new UserResource($user),
        'User updated successfully'
    );
}
```

#### `deletedResponse()`
For deleted resources.

```php
public function destroy(int $id): JsonResponse
{
    $user = User::findOrFail($id);
    $user->delete();
    return $this->deletedResponse('User deleted successfully');
}
```

**Response:**
```json
{
    "success": true,
    "message": "User deleted successfully"
}
```

### Paginated Responses

#### `paginatedResponse()`
For paginated data (automatically extracts pagination metadata).

```php
public function index(Request $request): JsonResponse
{
    $users = User::paginate(15);
    return $this->paginatedResponse($users, 'Users retrieved successfully');
}
```

**Response:**
```json
{
    "success": true,
    "message": "Users retrieved successfully",
    "data": [
        {
            "id": 1,
            "name": "John Doe"
        },
        {
            "id": 2,
            "name": "Jane Doe"
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 10,
        "per_page": 15,
        "total": 150,
        "from": 1,
        "to": 15
    }
}
```

#### Using with Resources

```php
public function index(Request $request): JsonResponse
{
    $users = User::with('roles')->paginate(15);
    
    // Transform items using Resource
    $transformedData = UserResource::collection($users->items());
    
    return $this->successResponse(
        $transformedData,
        'Users retrieved successfully',
        200,
        [
            'current_page' => $users->currentPage(),
            'last_page' => $users->lastPage(),
            'per_page' => $users->perPage(),
            'total' => $users->total(),
        ]
    );
}
```

### Collection Responses

#### `collectionResponse()`
For collections (non-paginated lists).

```php
public function all(): JsonResponse
{
    $users = User::all();
    return $this->collectionResponse($users, 'All users retrieved');
}
```

### Error Responses

#### `errorResponse()`
Generic error response.

```php
public function store(StoreUserRequest $request): JsonResponse
{
    try {
        $user = User::create($request->validated());
        return $this->createdResponse(new UserResource($user));
    } catch (\Exception $e) {
        return $this->errorResponse(
            $e->getMessage(),
            400
        );
    }
}
```

**Response:**
```json
{
    "success": false,
    "message": "Error message here"
}
```

#### `validationErrorResponse()`
For validation errors (422 status).

```php
public function store(Request $request): JsonResponse
{
    $validator = Validator::make($request->all(), [
        'email' => 'required|email|unique:users',
        'name' => 'required|string|max:255',
    ]);

    if ($validator->fails()) {
        return $this->validationErrorResponse($validator->errors()->toArray());
    }

    // ... create user
}
```

**Response:**
```json
{
    "success": false,
    "message": "Validation failed",
    "errors": {
        "email": ["The email has already been taken."],
        "name": ["The name field is required."]
    }
}
```
*Status Code: 422*

#### `notFoundResponse()`
For not found errors (404 status).

```php
public function show(int $id): JsonResponse
{
    $user = User::find($id);
    
    if (!$user) {
        return $this->notFoundResponse('User not found');
    }
    
    return $this->successResponse(new UserResource($user));
}
```

**Response:**
```json
{
    "success": false,
    "message": "User not found"
}
```
*Status Code: 404*

#### `unauthorizedResponse()`
For authentication errors (401 status).

```php
public function show(int $id): JsonResponse
{
    if (!auth()->check()) {
        return $this->unauthorizedResponse('Please login to continue');
    }
    
    // ... rest of logic
}
```

#### `forbiddenResponse()`
For authorization errors (403 status).

```php
public function destroy(int $id): JsonResponse
{
    $user = User::findOrFail($id);
    
    if (!auth()->user()->can('delete', $user)) {
        return $this->forbiddenResponse('You do not have permission to delete this user');
    }
    
    $user->delete();
    return $this->deletedResponse();
}
```

#### `serverErrorResponse()`
For server errors (500 status).

```php
public function complexOperation(): JsonResponse
{
    try {
        // Complex operation
    } catch (\Exception $e) {
        \Log::error('Complex operation failed', ['error' => $e->getMessage()]);
        return $this->serverErrorResponse('An unexpected error occurred');
    }
}
```

## Complete Controller Example

```php
<?php

namespace App\Http\Controllers\API\Admin;

use App\Http\Controllers\API\BaseController;
use App\Http\Requests\Admin\StoreUserRequest;
use App\Http\Requests\Admin\UpdateUserRequest;
use App\Http\Resources\Admin\UserResource;
use App\Services\Admin\UserService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class UserController extends BaseController
{

    protected UserService $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    /**
     * Display a listing of users
     */
    public function index(Request $request): JsonResponse
    {
        $users = $this->userService->getAllUsers($request->all());
        return $this->paginatedResponse($users, 'Users retrieved successfully');
    }

    /**
     * Store a newly created user
     */
    public function store(StoreUserRequest $request): JsonResponse
    {
        try {
            $user = $this->userService->createUser($request->validated());
            return $this->createdResponse(
                new UserResource($user),
                __('users.created')
            );
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 400);
        }
    }

    /**
     * Display the specified user
     */
    public function show(int $id): JsonResponse
    {
        try {
            $user = $this->userService->getUserById($id);
            return $this->successResponse(
                new UserResource($user),
                'User retrieved successfully'
            );
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->notFoundResponse('User not found');
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 500);
        }
    }

    /**
     * Update the specified user
     */
    public function update(UpdateUserRequest $request, int $id): JsonResponse
    {
        try {
            $user = $this->userService->updateUser($id, $request->validated());
            return $this->updatedResponse(
                new UserResource($user),
                __('users.updated')
            );
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->notFoundResponse('User not found');
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 400);
        }
    }

    /**
     * Remove the specified user
     */
    public function destroy(int $id): JsonResponse
    {
        try {
            $this->userService->deleteUser($id);
            return $this->deletedResponse(__('users.deleted'));
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->notFoundResponse('User not found');
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 400);
        }
    }
}
```

## Global Exception Handling

The application is configured to automatically handle exceptions for API requests in `bootstrap/app.php`. The following exceptions are automatically converted to JSON responses:

### Handled Exceptions

1. **ValidationException** (422)
   ```json
   {
       "success": false,
       "message": "Validation failed",
       "errors": {
           "email": ["The email field is required."]
       }
   }
   ```

2. **AuthenticationException** (401)
   ```json
   {
       "success": false,
       "message": "Unauthenticated"
   }
   ```

3. **AuthorizationException** (403)
   ```json
   {
       "success": false,
       "message": "Forbidden"
   }
   ```

4. **ModelNotFoundException** (404)
   ```json
   {
       "success": false,
       "message": "Resource not found"
   }
   ```

5. **NotFoundHttpException** (404)
   ```json
   {
       "success": false,
       "message": "Route not found"
   }
   ```

6. **MethodNotAllowedHttpException** (405)
   ```json
   {
       "success": false,
       "message": "Method not allowed"
   }
   ```

7. **All Other Exceptions** (500)
   - In **development** (APP_DEBUG=true): Includes exception details, file, line, and trace
   - In **production** (APP_DEBUG=false): Generic "Internal server error" message

### Benefits of Global Exception Handling

1. **No need for try-catch in controllers** - Exceptions are automatically handled
2. **Consistent error format** - All errors follow the same structure
3. **Security** - Production errors don't expose sensitive information
4. **Less boilerplate** - Cleaner controller code

### Example Without Try-Catch

```php
public function show(int $id): JsonResponse
{
    // ModelNotFoundException is automatically handled
    $user = $this->userService->getUserById($id);
    return $this->successResponse(
        new UserResource($user),
        'User retrieved successfully'
    );
}
```

If `getUserById()` throws `ModelNotFoundException`, it's automatically converted to:
```json
{
    "success": false,
    "message": "Resource not found"
}
```
*Status Code: 404*

## Response Format Standards

### Success Response Structure
```json
{
    "success": true,
    "message": "Optional message",
    "data": {},
    "meta": {}  // Optional metadata
}
```

### Error Response Structure
```json
{
    "success": false,
    "message": "Error message",
    "errors": {}  // Optional validation errors
}
```

## Best Practices

1. ✅ **Extend BaseController** - All API controllers should extend `BaseController` instead of `Controller`
2. ✅ **Use appropriate methods** - Use `createdResponse()` for POST, `updatedResponse()` for PUT/PATCH
3. ✅ **Include messages** - Always provide user-friendly messages
4. ✅ **Use Resources** - Transform data using Laravel Resources
5. ✅ **Let exceptions bubble** - Don't catch exceptions unless you need custom handling
6. ✅ **Use i18n** - Use `__()` for translatable messages
7. ✅ **Consistent status codes** - Use appropriate HTTP status codes

## Migration from Old Code

### Before (Old Pattern)
```php
use App\Http\Controllers\Controller;
use App\Traits\HasApiResponse;

class UserController extends Controller
{
    use HasApiResponse;
    
    public function store(Request $request): JsonResponse
    {
        try {
            $user = User::create($request->validated());
            return response()->json([
                'success' => true,
                'message' => 'User created',
                'data' => new UserResource($user)
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 400);
        }
    }
}
```

### After (New Pattern)
```php
use App\Http\Controllers\API\BaseController;

class UserController extends BaseController
{
    public function store(StoreUserRequest $request): JsonResponse
    {
        $user = User::create($request->validated());
        return $this->createdResponse(
            new UserResource($user),
            __('users.created')
        );
    }
}
```

**Benefits:**
- ✅ Cleaner code
- ✅ Consistent format
- ✅ Automatic validation error handling
- ✅ Less boilerplate

---

**Last Updated**: 2025-01-XX

