This package is in pre-release. The API may change before v1.0.

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;
use BlueBeetle\ApiToolkit\Rules\ValidInclude;
use BlueBeetle\ApiToolkit\Rules\ValidPageSize;

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',
        ];
    }
}

Available Methods

MethodPurpose
queryParamRules()Validation rules for query parameters
queryParamMessages()Custom error messages for query parameter validation
queryParamAttributes()Human-readable names for query parameters (used in error messages)
rules()Validation rules for request body (inherited from Laravel)
messages()Custom error messages for body validation (inherited from Laravel)

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:

use BlueBeetle\ApiToolkit\Http\Requests\FormRequest;

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

use BlueBeetle\ApiToolkit\Http\Requests\FormRequest;
use BlueBeetle\ApiToolkit\Rules\ValidInclude;

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

The toolkit includes custom validation rules like ValidInclude and ValidPageSize for common JSON:API parameters. See Validation Rules for the full list.

Type-hint the form request in your controller method. Laravel resolves and validates it automatically:

use App\Http\Requests\CreateProductRequest;
use App\Http\Requests\ListProductsRequest;
use App\Http\Resources\ProductResource;
use App\Models\Product;
use BlueBeetle\ApiToolkit\Http\Response;
use BlueBeetle\ApiToolkit\QueryBuilder;

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

    public function store(CreateProductRequest $request, Response $response)
    {
        $product = Product::create($request->validated());

        return $response->success($product, ProductResource::class)
            ->respond(201);
    }
}