Laravel Smart code with Api
Laravel provides a lot of features out of the box for building APIs. To structure API-related code in a clean and efficient way, you can use API resource controllers, form requests for validation, API resources for transformation, and routes designed specifically for APIs. Here's how you can implement a smart and optimized API structure in Laravel.
1. API Routes
When building an API, you generally want to isolate your routes in the routes/api.php file, which Laravel automatically registers with the /api prefix.
// routes/api.php
use App\Http\Controllers\Api\ProductController;
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('products', ProductController::class);
});
Route::apiResource() is a shortcut to automatically create the typical CRUD routes (index, store, show, update, and destroy).auth:sanctum to protect your routes for authenticated users. 2. API Resource Controller
In API development, Laravel’s apiResource method helps streamline CRUD operations.
// app/Http/Controllers/Api/ProductController.php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreProductRequest;
use App\Http\Resources\ProductResource;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index()
{
$products = Product::paginate(10);
return ProductResource::collection($products);
}
public function store(StoreProductRequest $request)
{
$product = Product::create($request->validated());
return new ProductResource($product);
}
public function show(Product $product)
{
return new ProductResource($product);
}
public function update(StoreProductRequest $request, Product $product)
{
$product->update($request->validated());
return new ProductResource($product);
}
public function destroy(Product $product)
{
$product->delete();
return response()->json(null, 204);
}
}
ProductResource::collection() is used for paginated lists or collections of products.new ProductResource($product) is used for individual products.StoreProductRequest).3. Form Request for Validation
You should use form request classes to handle validation and authorization logic, keeping your controller clean.
// app/Http/Requests/StoreProductRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreProductRequest extends FormRequest
{
public function authorize()
{
// Authorization logic (can be customized)
return true;
}
public function rules()
{
return [
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0',
'stock' => 'required|integer|min:0',
];
}
}
Benefits:
- Clean validation separated from the controller.
- Custom authorization logic can be added to the
authorize()method.
4. API Resources for Response Transformation
API Resources in Laravel transform your model data to a structured JSON format, making it easy to modify the API output without changing the underlying model.
// app/Http/Resources/ProductResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'price' => $this->formatted_price,
'stock' => $this->stock,
'category' => new CategoryResource($this->whenLoaded('category')),
];
}
}
Benefits:
toArray()method provides flexibility for formatting responses.$this->whenLoaded()ensures relationships (e.g.,category) are included only if loaded, which prevents unnecessary database queries.
5. API Response Formatting
To follow REST standards and create consistent API responses, you can encapsulate your success and error responses in a helper trait or service.
// app/Http/Traits/ApiResponseTrait.php
namespace App\Http\Traits;
trait ApiResponseTrait
{
protected function successResponse($data, $message = null, $code = 200)
{
return response()->json([
'status' => 'success',
'message' => $message,
'data' => $data
], $code);
}
protected function errorResponse($message = null, $code = 400)
{
return response()->json([
'status' => 'error',
'message' => $message,
], $code);
}
}
Benefits:
- Encapsulating responses ensures consistent API response format.
- Provides flexibility for custom success/error messages.
6. Pagination for API
When returning a large dataset, it's good to paginate the response. Laravel makes it easy with the paginate() method:
// app/Http/Controllers/Api/ProductController.php
public function index()
{
$products = Product::paginate(15);
return ProductResource::collection($products);
}
current_page, total, last_page, per_page to the JSON response.7. Handling Filters and Sorting
You can implement query parameters like filtering, sorting, and searching in a clean way using scopes in models and query logic in the controller.
// app/Models/Product.php
public function scopeFilter($query, $filters)
{
if ($filters['price'] ?? null) {
$query->where('price', $filters['price']);
}
if ($filters['category'] ?? null) {
$query->whereHas('category', function ($q) use ($filters) {
$q->where('name', $filters['category']);
});
}
}
Usage:
bash# Example API request with filters
GET /api/products?price=100&category=Electronics
8. API Authentication with Sanctum
Laravel Sanctum provides a simple way to authenticate your API with tokens.
Installation:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Middleware Setup:// app/Http/Kernel.php
'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class,],Benefits:
- Versioning allows for backward compatibility as you make improvements to your API
No comments