Advanced Features#
Message Overrides and Placeholders#
Use setCustomMessages() to override rule messages.
Supported key styles:
field.rule(exact rule for exact field)field.*(any rule for a field)*.rule(same rule on any field)field(fallback for a field)rule(global fallback by rule name)Wildcard field paths (for example
contacts.*.email.required)
$validator->setCustomMessages([
'email.required' => ':field is required.',
'*.min' => ':field must be at least :min.',
'contacts.*.email.email' => 'Each contact email must be valid.',
]);
Common placeholders:
:field/:attribute(resolved alias):rule:valueRule parameters such as
:min,:max,:size,:other,:values
Locale Packs#
Use locale packs when you want centralized message translation.
$validator
->addLocalePack('es', [
'required' => 'El campo :field es obligatorio.',
'*' => 'El campo :field no es valido.',
])
->setLocale('es');
You can also replace all packs with setLocalePacks().
Locale fallback supports variants like en_US to base en.
Sanitize + Validate Pipeline#
ReqShield can sanitize automatically before validation.
$validator = Validator::make([
'username' => [
'rules' => 'required|alpha_dash|min:3',
'sanitize' => ['trim', 'lowercase'],
],
'email' => 'required|email',
])->setSanitizers([
'email' => ['trim', 'lowercase'],
]);
Global setSanitizers() merges with schema-level sanitize/sanitizers.
Wildcard pipelines are supported (example: contacts.*.email).
Conditional Rules#
Use sometimes() for field-targeted rule activation.
$validator->sometimes(
'vat',
'required',
fn (array $data): bool => ($data['type'] ?? null) === 'business',
);
Use when() to inject dynamic rule arrays.
$validator->when(
fn (array $data): bool => ($data['country'] ?? null) === 'US',
fn (): array => ['state' => 'required|string'],
fn (): ?array => null, // optional default callback
);
The callback must return array or null.
After Validation Hooks#
Use after() for cross-field checks that do not fit a single rule.
use Infocyph\ReqShield\Support\ValidationContext;
$validator->after(function (ValidationContext $ctx): void {
if ((string) $ctx->get('start_date') > (string) $ctx->get('end_date')) {
$ctx->addError('end_date', 'End date must be after start date.');
}
});
Enum Rules and Enum Casting#
Use enum rules with either string syntax or rule objects.
use App\Enums\OrderStatus;
use Infocyph\ReqShield\Rule;
$validator = Validator::make([
'status' => 'required|enum:' . OrderStatus::class,
'state' => ['required', Rule::enum(OrderStatus::class)],
])->setCasts([
'status' => OrderStatus::class,
]);
Compiled Validator Wrapper#
Validator::compile() returns a reusable validator wrapper.
$compiled = Validator::compile([
'email' => 'required|email',
'age' => 'required|integer|min:18',
]);
$result = $compiled->validate($input);
Schema Fragments and Composition#
Reuse schema pieces across endpoints.
Validator::defineFragment('address', [
'line1' => 'required|string',
'zip' => 'required|digits:5',
]);
$validator = Validator::make(['name' => 'required|string'])
->useFragment('address', 'billing');
Static helpers:
Validator::fragment($name, $prefix = '')Validator::hasFragment($name)Validator::composeSchemas(...$schemas)
Typed Output and DTO Mapping#
Use setCasts() to convert validated values and setDtoClass() for DTO output.
$validator = Validator::make([
'age' => 'required|integer',
'active' => 'required|boolean',
])->setCasts([
'age' => 'integer',
'active' => 'boolean',
])->setDtoClass(App\DTO\UserInput::class);
$result = $validator->validate($input);
$typed = $result->typed();
$dto = $result->toDTO();
Failure Metadata#
For API/UI mapping, use structured failures.
$result->failures();
// [
// ['field' => 'email', 'rule' => 'email', 'message' => '...', 'value' => 'bad'],
// ]
$result->failuresFor('email');
Schema Export and Introspection#
Supported exports:
exportSchema('json_schema')exportSchema('openapi')exportSchema('introspection')
Introspection is also available through schemaIntrospection() and rule stats through getSchemaStats().