Usage Guide
Comprehensive guide to the WPZylos Validation package.
Table of Contents
- 1. Basic Validation
- 2. Available Rules
- 3. Rule Syntax
- 4. Custom Error Messages
- 5. Custom Attribute Names
- 6. Nullable Fields
- 7. FormRequest
- 8. Sanitizer Types
- 9. Custom Rules
- 10. MessageBag API
- 11. ValidationException Handling
- 12. Service Provider Registration
1. Basic Validation
Create a Validator with data and rules, then check the result:
use WPZylos\Framework\Validation\Validator;
$validator = new Validator(
data: $request->all(),
rules: [
'name' => 'required|string|min:2|max:100',
'email' => 'required|email',
'age' => 'required|integer|min:18',
],
);
// Option 1: Check result
if ($validator->validate()) {
// Valid - validate() returns bool
$data = $validator->validated();
}
// Option 2: Check failure
if ($validator->fails()) {
$errors = $validator->errors();
}
// Option 3: Check success
if ($validator->passes()) {
// All good
}
Important:
validate()returnsbool, not an object. Data and rules are passed to the constructor.
Getting Validated Data
validated() returns only the fields that had rules defined. If validation fails, it throws ValidationException:
try {
$data = $validator->validated();
} catch (\WPZylos\Framework\Validation\ValidationException $e) {
$errors = $e->errors(); // MessageBag
}
2. Available Rules
Built-in Rules (Validator class)
These rules are handled internally by the Validator class:
| Rule | Example | Description |
|---|---|---|
required | 'required' | Field must be present, not null, not empty string, not empty array |
string | 'string' | Value must be a string |
integer | 'integer' | Value must be a valid integer (via FILTER_VALIDATE_INT) |
int | 'int' | Alias for integer |
numeric | 'numeric' | Value must be numeric (via is_numeric) |
boolean | 'boolean' | Value must be true, false, 0, 1, '0', '1', 'true', or 'false' |
array | 'array' | Value must be an array |
email | 'email' | Value must be a valid email (via FILTER_VALIDATE_EMAIL) |
url | 'url' | Value must be a valid URL (via FILTER_VALIDATE_URL) |
min | 'min:3' | Minimum: string length, array count, or numeric value |
max | 'max:255' | Maximum: string length, array count, or numeric value |
in | 'in:draft,published' | Value must be one of the listed values (strict comparison) |
regex | 'regex:/^[a-z]+$/' | Value must match the regex pattern |
nullable | 'nullable' | Field is optional. Skips all rules if value is null or empty string |
Standalone Rule Classes (Rules/ directory)
These 12 classes implement RuleInterface and can be registered via Validator::extend():
| Class | Description |
|---|---|
RequiredRule | Not null, not empty string, not empty array |
EmailRule | Valid email via FILTER_VALIDATE_EMAIL |
UrlRule | Valid URL via FILTER_VALIDATE_URL |
NumericRule | Numeric via is_numeric |
AlphaRule | Only alphabetic characters (Unicode letters \pL\pM) |
AlphaNumericRule | Only letters and numbers |
MinRule | Minimum string length / array count / numeric value |
MaxRule | Maximum string length / array count / numeric value |
BetweenRule | Value between min and max (string length / array count / numeric) |
InRule | Value in parameter list |
ConfirmedRule | Field matches {field}_confirmation |
RegexRule | Value matches regex pattern |
3. Rule Syntax
Pipe-Separated String
'name' => 'required|string|min:2|max:100'
Array Syntax
'name' => ['required', 'string', 'min:2', 'max:100']
Rule Parameters
Parameters follow a colon, multiple parameters are comma-separated:
'age' => 'min:18', // one parameter
'status' => 'in:active,inactive,banned', // multiple parameters
'code' => 'regex:/^[A-Z]{3}[0-9]+$/', // regex pattern
4. Custom Error Messages
Field-Specific Messages
Target a specific field + rule combination:
$validator = new Validator(
data: $data,
rules: ['email' => 'required|email'],
messages: [
'email.required' => 'We need your email address.',
'email.email' => 'That does not look like a valid email.',
],
);
Rule-Level Messages
Apply to all fields using that rule:
$validator = new Validator(
data: $data,
rules: $rules,
messages: [
'required' => 'The :attribute field cannot be blank.',
'email' => 'Please enter a valid email for :attribute.',
],
);
Message Placeholders
| Placeholder | Replaced With |
|---|---|
:attribute | Field name (underscores replaced with spaces) |
:param0 | First rule parameter |
:param1 | Second rule parameter |
:paramN | Nth rule parameter |
Message Resolution Order
- Field-specific custom message (e.g.,
email.required) - Rule-level custom message (e.g.,
required) - Extension custom message (from
RuleInterface::message()) - Default message (translated via
Translatorif available)
5. Custom Attribute Names
Replace field names in error messages with human-friendly labels:
$validator = new Validator(
data: $data,
rules: ['phone_number' => 'required'],
attributes: [
'phone_number' => 'phone number',
],
);
// Error: "The phone number field is required." instead of "The phone_number field is required."
6. Nullable Fields
Add nullable to make a field optional. If the value is null or an empty string, all other rules are skipped:
$rules = [
'name' => 'required|string',
'nickname' => 'nullable|string|min:2', // Only validated if present
'bio' => 'nullable|max:500',
];
7. FormRequest
FormRequest is an abstract class that combines authorization, sanitization, and validation. It lives in this package (WPZylos\Framework\Validation), not in wpzylos-http.
Creating a FormRequest
use WPZylos\Framework\Validation\FormRequest;
class UpdateSettingsRequest extends FormRequest
{
public function authorize(): bool
{
return current_user_can('manage_options');
}
public function rules(): array
{
return [
'site_title' => 'required|string|max:200',
'admin_email' => 'required|email',
'posts_per_page' => 'required|integer|min:1|max:100',
'enable_comments' => 'nullable|boolean',
];
}
public function sanitize(): array
{
return [
'site_title' => 'text',
'admin_email' => 'email',
'posts_per_page' => 'int',
'enable_comments' => 'bool',
];
}
public function messages(): array
{
return [
'site_title.required' => 'Your site needs a title.',
];
}
public function attributes(): array
{
return [
'admin_email' => 'administrator email',
'posts_per_page' => 'posts per page',
];
}
}
Using in a Controller
public function update(Request $request): Response
{
$form = new UpdateSettingsRequest($request);
if (!$form->authorize()) {
return Response::error('Unauthorized', 403);
}
if ($form->fails()) {
return Response::json([
'errors' => $form->errors()->toArray(),
], 422);
}
$data = $form->validated(); // Sanitized + validated data
// Save settings...
return Response::json(['status' => 'ok']);
}
How FormRequest Works
data()is called to get sanitized input from the HTTP request- Sanitizers from
sanitize()are applied to each field - A
Validatoris created with the sanitized data + rules + messages + attributes validate(),fails(),errors(),validated()all delegate to this internal Validator
8. Sanitizer Types
Used in FormRequest::sanitize() to map fields to WordPress sanitization functions:
| Type | WordPress Function | Description |
|---|---|---|
text (default) | sanitize_text_field() | Plain text, strips tags |
textarea | sanitize_textarea_field() | Multi-line text, preserves newlines |
html | wp_kses_post() | Rich HTML (post-content level tags) |
email | sanitize_email() | Valid email characters |
url | esc_url_raw() | Safe URL for database storage |
int / integer | (int) cast | Integer value |
absint | absint() | Non-negative integer |
float | filter_var(FILTER_SANITIZE_NUMBER_FLOAT) | Float value |
bool / boolean | filter_var(FILTER_VALIDATE_BOOLEAN) | Boolean value |
slug | sanitize_title() | URL-safe slug |
key | sanitize_key() | Lowercase alphanumeric with dashes and underscores |
Fields without a sanitizer mapping in sanitize() are passed through unchanged.
9. Custom Rules
Implementing RuleInterface
use WPZylos\Framework\Validation\RuleInterface;
class UniqueEmailRule implements RuleInterface
{
public function passes(string $field, mixed $value, array $parameters, array $data): bool
{
// $parameters[0] could be a table name, etc.
return !email_exists($value);
}
public function message(): string
{
return 'The :attribute is already taken.';
}
}
Important: The
passes()signature is(string $field, mixed $value, array $parameters, array $data). The$dataparameter gives access to all data being validated.
Registering Custom Rules
Use Validator::extend() with a rule name and a RuleInterface instance (not a closure):
use WPZylos\Framework\Validation\Validator;
Validator::extend('unique_email', new UniqueEmailRule());
Using Custom Rules
$validator = new Validator(
data: ['email' => '[email protected]'],
rules: ['email' => 'required|email|unique_email'],
);
Custom rules are registered globally and available to all Validator instances.
10. MessageBag API
MessageBag collects validation errors per field.
$errors = $validator->errors();
// Check for errors
$errors->hasErrors(); // bool - any errors at all?
$errors->has('email'); // bool - errors for this field?
// Get messages
$errors->first('email'); // ?string - first error for field
$errors->get('email'); // string[] - all errors for field
$errors->all(); // array<string, string[]> - all grouped by field
$errors->flatten(); // string[] - all messages as flat array
// Metadata
$errors->count(); // int - total error count
$errors->keys(); // string[] - field names with errors
$errors->toArray(); // array<string, string[]> - same as all()
Displaying Errors (Example)
if ($validator->fails()) {
foreach ($validator->errors()->all() as $field => $messages) {
foreach ($messages as $message) {
echo "<p class='error'>{$message}</p>";
}
}
}
11. ValidationException Handling
ValidationException is thrown by validated() when validation fails:
use WPZylos\Framework\Validation\ValidationException;
try {
$data = $validator->validated();
} catch (ValidationException $e) {
$errors = $e->errors(); // MessageBag
$message = $e->getMessage(); // "The given data was invalid."
}
The exception carries a MessageBag with all validation errors.
12. Service Provider Registration
The ValidationServiceProvider registers a validator factory with the container:
use WPZylos\Framework\Validation\ValidationServiceProvider;
$app->register(new ValidationServiceProvider());
What Gets Registered
| Binding | Type | Description |
|---|---|---|
'validator' | Factory | Returns a factory function for creating Validator instances |
Using the Factory
$makeValidator = $container->get('validator');
$validator = $makeValidator(
$data, // array - data to validate
$rules, // array - validation rules
$messages, // array - custom messages (optional)
$attributes, // array - custom attribute names (optional)
);
The factory automatically injects a Translator instance if one is registered in the container.