Laravel cookbook · Beginner
Validate requests with Form Requests
Controllers fill up with validation and authorization code, and rules differ between create and update.
Approach
Move rules and authorization into a Form Request class. The controller receives only validated data, invalid requests get a 422 with field errors (JSON for API clients), and unauthorized ones a 403.
Solution
<?php
// app/Http/Requests/StoreOrderRequest.php
namespace App\Http\Requests;
use App\Models\Order;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class StoreOrderRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()->can('create', Order::class);
}
public function rules(): array
{
return [
'product_id' => ['required', 'integer', Rule::exists('products', 'id')->where('active', true)],
'quantity' => ['required', 'integer', 'between:1,10'],
'coupon' => ['nullable', 'string', 'max:20'],
'shipping.country' => ['required', 'string', 'size:2'],
];
}
public function messages(): array
{
return ['product_id.exists' => 'That product is no longer available.'];
}
}
<?php
// app/Http/Controllers/OrderController.php
namespace App\Http\Controllers;
use App\Http\Requests\StoreOrderRequest;
use App\Http\Resources\OrderResource;
class OrderController extends Controller
{
public function store(StoreOrderRequest $request): OrderResource
{
$order = $request->user()->orders()->create($request->validated());
return new OrderResource($order);
}
}
Pitfalls
- Using
$request->all()after validation, which includes fields you didn't validate (mass assignment risk). - Returning
truefromauthorize()everywhere and forgetting to check permissions elsewhere. - Duplicating the same rules in store and update requests; share them in a trait or base class.
Variations
- Use
$request->safe()->only([...])to pick specific validated fields. - Add
prepareForValidation()to normalise input (trim, lowercase emails) before rules run.
Further reading: Form request validation
Reference: https://laravel.com/docs/13.x/validation#form-request-validation
More Laravel recipes
- Authorize actions with policies
- Cache expensive data with stale-while-revalidate
- Call external APIs with timeouts, retries and fakes
- Catch N+1 queries with strict Eloquent mode
- Delete old records automatically with prunable models
- Dispatch events and listeners after the transaction commits
- Issue scoped API tokens with Sanctum
- Make queued jobs reliable with retries, backoff and uniqueness