Laravel cookbook · Beginner

Validate requests with Form Requests

Controllers fill up with validation and authorization code, and rules differ between create and update.

Create a free account to save this page, take notes and track your progress. Sign in

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 true from authorize() 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

Was this page helpful?