Form Requests

The toolkit provides a base FormRequest class that extends Laravel's with support for query parameter validation and strict unknown parameter rejection.

Basic Usage

use BlueBeetle\ApiToolkit\Http\Requests\FormRequest;

class ListProductsRequest extends FormRequest
{
    public function queryParamRules(): array
    {
        return [
            'filter.name'   => ['sometimes', 'string', 'max:255'],
            'filter.status'  => ['sometimes', 'in:active,archived,draft'],
            'page.size'      => ['sometimes', new ValidPageSize()],
            'include'        => ['sometimes', new ValidInclude(['category', 'tags'])],
        ];
    }

    public function queryParamMessages(): array
    {
        return [
            'filter.status.in' => 'Status must be one of: active, archived, draft.',
        ];
    }

    public function queryParamAttributes(): array
    {
        return [
            'filter.name' => 'product name',
        ];
    }
}

Strict Parameter Checking

Unlike standard Laravel form requests, the toolkit's FormRequest rejects unknown parameters with a 400 Bad Request. If a client sends ?filter[foo]=bar and foo isn't in your rules, the request is rejected immediately — before validation rules run.

This applies to both query parameters and request body fields.

{
  "errors": [
    {
      "status": "400",
      "code": "invalid_request_error",
      "title": "Bad Request",
      "detail": "Received unknown parameter: foo"
    }
  ]
}

Body Validation

For write operations, use the standard rules() method:

class CreateProductRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name'        => ['required', 'string', 'max:255'],
            'description' => ['sometimes', 'string'],
            'price'       => ['required', 'numeric', 'min:0'],
            'category_id' => ['required', 'exists:categories,id'],
        ];
    }
}

Combining Query and Body Rules

class UpdateProductRequest extends FormRequest
{
    public function queryParamRules(): array
    {
        return [
            'include' => ['sometimes', new ValidInclude(['category'])],
        ];
    }

    public function rules(): array
    {
        return [
            'name'  => ['sometimes', 'string', 'max:255'],
            'price' => ['sometimes', 'numeric', 'min:0'],
        ];
    }
}

Using in Controllers

Type-hint the form request in your controller method — Laravel handles the rest:

public function index(ListProductsRequest $request)
{
    return QueryBuilder::for(Product::class, $request)
        ->fromResource(ProductResource::class)
        ->paginate();
}