How it works
use Potager\Grape\Grape; $schema = Grape::schema([ 'name' => Grape::string()->trim()->minLength(2)->required(), 'email' => Grape::string()->trim()->lowercase()->email()->required(), 'age' => Grape::integer()->min(18)->optional(), ]); // Validates and returns clean, typed data: $data = $schema->validate($_POST);
Core capabilities
Declarative Validation
Declare strict constraints with IDE-autocompleted chainable methods. Enforce length boundaries, regex patterns, email formats, and presence requirements (required() / nullable()).
$validator = Grape::schema([ 'username' => Grape::string()->minLength(3)->maxLength(20)->required(), 'email' => Grape::string()->email()->required(), 'age' => Grape::integer()->min(18)->optional(), ]);
In-Place Data Sanitization
Clean and normalize values directly during validation. Methods like trim(), lowercase(), clamp(), and compact() transform the data so your domain receives sanitized output.
$clean = Grape::schema([ 'search' => Grape::string()->trim()->lowercase(), 'limit' => Grape::integer()->clamp(1, 100), ])->validate($_GET);
Strict & Loose Type Coercion
Loose mode (default) seamlessly coerces HTTP form strings like "28" → 28 and "true" → true. For strict JSON APIs, pass strict: true to enforce exact native types without casting.
Grape::number(); // Loose (casts numeric strings) Grape::number(strict: true); // Strict (int & float only) Grape::boolean(strict: true); // Strict (bool only)
First-Class Composition
Nest associative schemas, homogeneous collections, and fixed-size tuples. Collections support deduplication (distinct()), invalid item skipping (skipInvalids()), and index normalization.
$order = Grape::schema([ 'tags' => Grape::collection(Grape::string())->distinct(), 'coordinates' => Grape::tuple([Grape::float(), Grape::float()]), ]);
Non-Throwing Result Option
Choose your error handling style. Throw structured ValidationException or use the functional check() method returning [$error, $data] to handle errors without try/catch blocks.
[$error, $data] = $schema->check($payload); if ($error !== null) { return response()->json($error->getMessages(), 422); }