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();
}