sajadsdi/laravel-rest-response
## Getting Started
### Minimal Setup
1. **Installation**
Run `composer require sajadsdi/laravel-rest-response` in your Laravel project.
Publish the config (optional): `php artisan vendor:publish --provider="Sajadsdi\LaravelRestResponse\RestResponseServiceProvider"`.
2. **First Use Case**
Extend your controller with `RestController`:
```php
use Sajadsdi\LaravelRestResponse\RestController;
class UserController extends RestController
{
public function index()
{
return $this->successResponse(['users' => User::all()]);
}
}
successResponse(), errorResponse(), notFound(), badRequest(), etc.{
"status": "success",
"data": {...},
"message": "Operation completed successfully",
"meta": { "version": "1.0.0" }
}
config/rest-response.php for customizing default responses (e.g., status codes, messages).CrudApi for standardized CRUD operations (see Implementation Patterns).Extend RestController in your base controller to inherit all response methods:
class ApiController extends RestController
{
// All response methods (successResponse, errorResponse, etc.) are available here.
}
CrudApi TraitUse the CrudApi trait to standardize CRUD responses:
use Sajadsdi\LaravelRestResponse\Traits\CrudApi;
class PostController extends RestController
{
use CrudApi;
protected $model = Post::class;
protected $serializer = PostResource::class; // Optional: for API resources.
// Automatically handles index, store, show, update, destroy with standardized responses.
}
createResponse() or deleteResponse() to modify behavior.
Example:
protected function createResponse($data)
{
return $this->successResponse($data, 'Post created with custom message', 201);
}
Use BaseRequest for requests to automatically format validation/authorization errors:
use Sajadsdi\LaravelRestResponse\BaseRequest;
class StorePostRequest extends BaseRequest
{
public function rules()
{
return ['title' => 'required|max:255'];
}
public function failedValidation($validator)
{
return $this->errorResponse($validator->errors(), 'Validation failed', 422);
}
public function authorize()
{
return auth()->check(); // Custom authorize logic.
}
protected function failedAuthorization()
{
return $this->errorResponse(null, 'Unauthorized', 403);
}
}
failedValidation(): Handles validation errors.failedAuthorization(): Handles auth failures.authorize(): Custom logic (returns true/false).Override default response structure via config or methods:
// In config/rest-response.php:
'response' => [
'status_key' => 'result',
'data_key' => 'payload',
],
successResponse($data, $message = null, $status = 200, $headers = []) to customize per endpoint.
Example:
return $this->successResponse(
['user' => $user],
'User fetched successfully',
200,
['X-Custom-Header' => 'value']
);
Include API version in responses via config:
// config/rest-response.php:
'version' => 'v1',
getVersion() in RestController:
protected function getVersion()
{
return request()->header('Accept-Version') ?? 'v1';
}
Combine with Laravel’s API Resources for structured data:
use Sajadsdi\LaravelRestResponse\RestController;
use App\Http\Resources\PostResource;
class PostController extends RestController
{
public function show(Post $post)
{
return $this->successResponse(new PostResource($post));
}
}
Use the package’s error responses in App\Exceptions\Handler:
public function render($request, Throwable $exception)
{
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
return $this->app->make(RestController::class)->notFound();
}
return parent::render($request, $exception);
}
RestController.Assert responses in tests using the package’s structure:
$response = $this->get('/api/users');
$response->assertStatus(200)
->assertJsonStructure([
'status', 'data', 'message', 'meta' => ['version']
]);
Overriding Default Methods
successResponse() or errorResponse() in a child controller, ensure you call parent::method() to retain default behavior where needed.protected function successResponse($data, $message = null, $status = 200, $headers = [])
{
$response = parent::successResponse($data, $message, $status, $headers);
$response->header('X-Processed-By', 'CustomController');
return $response;
}
Config File Not Published
status_key), publish the config first:
php artisan vendor:publish --provider="Sajadsdi\LaravelRestResponse\RestResponseServiceProvider" --tag=config
CRUD Trait Conflicts
CrudApi trait assumes standard route names (index, store, etc.). Rename routes or override methods if your API uses custom actions (e.g., bulkDestroy).public function destroy($id)
{
$this->authorize('delete', $this->model);
$deleted = $this->model::destroy($id);
return $this->deleteResponse($deleted);
}
BaseRequest Validation Errors
BaseRequest formats validation errors as an array. If you need JSON:API-style errors, extend the trait and override failedValidation():
public function failedValidation($validator)
{
return $this->errorResponse([
'errors' => $validator->errors()->toArray()
], 'Validation errors', 422);
}
Versioning Headers
Accept-Version header for dynamic versioning may conflict with other versioning strategies (e.g., URI paths like /v1/users). Decide on a single approach and document it.Check Response Structure
Use dd($this->successResponse($data)) to inspect the raw response object before sending it.
Log Custom Responses Add debug logs in overridden methods:
protected function errorResponse($data, $message = null, $status = 400, $headers = [])
{
\Log::debug("Error Response: " . json_encode(compact('data', 'message', 'status')));
return parent::errorResponse($data, $message, $status, $headers);
}
Validate Config
Ensure config/rest-response.php matches your expected response structure. Test with:
$this->get('/health')->assertJson(['status' => config('rest-response.response.status_key')]);
Sajadsdi\LaravelRestResponse\RestResponse) to add reusable logic:
namespace App
How can I help you explore Laravel packages today?