night-commit / php-sanity
php package to validate incoming request data
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/night-commit/php-sanity
Requires (Dev)
- mockery/mockery: ^1.6
- phpunit/phpunit: ^12.3
README
A powerful and flexible PHP validation package that allows you to validate data by defining pre and post validation rules for specific request fields.
Features
- Extensible: Easy to extend with custom validation rules
- Comprehensive: Built-in rules for strings, numbers, booleans, dates, arrays, and files
- Flexible: Support for both class-based and closure-based custom rules
- File Validation: Dedicated file upload validation with size and type checking
- Type Safe: Strong type checking and validation
- Field Dependencies: Cross-field validation support
- Nested Validation: Support for dot notation (
user.name
) and wildcard patterns (authors.*.email
) - Array Validation: Validate complex nested arrays and objects
Installation
Install via Composer:
composer require night-commit/php-sanity
Quick Start
Basic Usage
Create a validator by extending the base Validator
class:
<?php use NightCommit\PHP\Sanity\Validator; class UserValidator extends Validator { /** * Define validation rules for your fields * * @return array<string, string[]> */ protected function rules(): array { return [ 'name' => ['nullable', 'string', 'min:2', 'max:50'], 'email' => ['required', 'email'], 'age' => ['required', 'int', 'more:0', 'less:120'], 'password' => ['required', 'string', 'min:8'], 'password_confirmation' => ['required', 'confirmed:password'], 'personal' => ['required', 'array'], 'personal.address' => ['required', 'string', 'max:100'], 'posts' => ['nullable', 'array'], 'posts.*.title' => ['required', 'string', 'min:3'], 'posts.*.content' => ['required', 'string', 'min:3', 'max:200'], ]; } }
Validating Data
// Sample data to validate $data = [ 'name' => 'John Doe', 'email' => 'john@example.com', 'age' => 25, 'password' => 'securepass123', 'password_confirmation' => 'securepass123', 'personal' => ['address' => 'some place'], 'posts' => [ ['title' => 'title-1', 'content' => 'lorem ipsum'], ['title' => 'title-1', 'content' => 'lorem ipsum'], ] ]; // Perform validation $validator = new UserValidator($data); if (! empty($validator->errors())) { // Handle validation errors } // get only validated data $validator->validated(); // get all data $validator->all();
Validation Rules
String Rules
Rule | Description | Example |
---|---|---|
string |
Validates that the value is a string | 'name' => ['string'] |
size:length |
Validates exact string length | 'code' => ['string', 'size:6'] |
min:limit |
Sets minimum string length | 'name' => ['string', 'min:2'] |
max:limit |
Sets maximum string length | 'name' => ['string', 'max:50'] |
json |
Validates JSON format | 'config' => ['json'] |
email |
Validates email format | 'email' => ['email'] |
regex:pattern |
Validates against regex pattern | 'phone' => ['regex:/^\d{10}$/'] |
Numeric Rules
Rule | Description | Example |
---|---|---|
int |
Validates integer values | 'age' => ['int'] |
float:precision |
Validates float with specified precision | 'price' => ['float:2'] |
less:value |
Sets maximum numeric value | 'age' => ['int', 'less:100'] |
more:value |
Sets minimum numeric value | 'age' => ['int', 'more:0'] |
unsigned |
Validates positive numbers | 'count' => ['int', 'unsigned'] |
Boolean Rules
Rule | Description | Example |
---|---|---|
boolean |
Validates boolean values | 'active' => ['boolean'] |
boolean:cast |
Validates boolean or 'yes'/'no' strings | 'consent' => ['boolean:cast'] |
Date Rules
Rule | Description | Example |
---|---|---|
date:format |
Validates date format (default: Y-m-d) | 'birthdate' => ['date'] or 'created_at' => ['date:Y-m-d H:i:s'] |
after:date |
Validates date is after specified date | 'end_date' => ['date', 'after:start_date'] |
before:date |
Validates date is before specified date | 'start_date' => ['date', 'before:end_date'] |
Array Rules
Rule | Description | Example |
---|---|---|
array |
Validates that value is an array | 'tags' => ['array'] |
array_unique |
Validates array contains unique values | 'categories' => ['array', 'array_unique'] |
array_length:length |
Validates exact array length | 'choices' => ['array', 'array_length:3'] |
Generic Rules
Rule | Description | Example |
---|---|---|
required |
Field must be present and not empty | 'name' => ['required'] |
nullable |
Field can be missing or null | 'middle_name' => ['nullable', 'string'] |
filled |
Field must not be empty if present | 'bio' => ['filled'] |
in:value1,value2 |
Value must be in specified list | 'status' => ['in:active,inactive,pending'] |
confirmed:field |
Value must match another field | 'password_confirmation' => ['confirmed:password'] |
File Validation
For file upload validation, implement the files()
method in your validator:
<?php use NightCommit\PHP\Sanity\Validator; class FileUploadValidator extends Validator { /** * Define file validation rules * * @return array<string, string[]> */ protected function files(): array { return [ 'avatar' => ['file', 'ftype:jpg,jpeg,png', 'fsize:0,2,mb'], 'document' => ['file', 'ftype:pdf,docx', 'fsize:0,10,mb'] ]; } }
File Rules
Rule | Description | Example |
---|---|---|
file |
Validates that field is a file | 'avatar' => ['file'] |
ftype:ext1,ext2 |
Validates file extension | 'image' => ['file', 'ftype:jpg,png,gif'] |
fsize:min,max,unit |
Validates file size | 'document' => ['file', 'fsize:0,5,mb'] |
File Size Units:
bt
- byteskb
- kilobytesmb
- megabytesgb
- gigabytes
Note: Use 0
for min or max to ignore that limit.
Custom Validation Rules
Method 1: Rule Class Implementation
Create a custom rule by extending the Rule
class:
<?php use NightCommit\PHP\Sanity\Rules\Rule; use NightCommit\PHP\Sanity\Rules\RuleFactory; class UniqueUsernameRule extends Rule { /** * Available properties: * @property \NightCommit\PHP\Sanity\Validator $validator * @property string $field - The field being validated * @property mixed $value - The field value * @property array $data - All request data * @property array $args - Rule parameters */ public function handle(): void { // Your validation logic here $username = $this->value; // Example: Check if username exists in database if ($this->usernameExists($username)) { $this->validator->addError($this->field, "Username '{$username}' is already taken"); return; // Stop further validation for this field } // Continue with other rules parent::handle(); } private function usernameExists(string $username): bool { // Your database check logic here return false; } } // Register the custom rule RuleFactory::register('unique_username', UniqueUsernameRule::class);
Method 2: Closure Function
Register a simple validation rule using a closure:
<?php use NightCommit\PHP\Sanity\Rules\RuleFactory; RuleFactory::register('strong_password', function (string $errorMessage = "Password is not strong enough", bool $continueValidation = true, mixed $value): bool { // Must contain at least one uppercase, lowercase, number, and special character $pattern = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/'; return preg_match($pattern, $value); } );
Using Custom Rules
class UserValidator extends Validator { protected function rules(): array { return [ 'username' => ['required', 'string', 'unique_username'], 'password' => ['required', 'string', 'min:8', 'strong_password'] ]; } }
Change Rules Error Messages
Define your own error messages in the sub validator $message static property
<?php use NightCommit\PHP\Sanity\Validator; class UserValidator extends Validator { /** * Custom error messages * * @var array<string, string> */ public static array $messages = [ 'required' => 'This field is mandatory, please fill it out', 'email' => 'Please provide a valid email address', 'min' => 'This field is too short', 'max' => 'This field is too long', 'int' => 'Please enter a valid number', 'string' => 'This field must be text only' ]; protected function rules(): array { return [ 'name' => ['required', 'string', 'min:2'], 'email' => ['required', 'email'], 'age' => ['required', 'int'] ]; } }
Error Handling
$validator = new UserValidator($data); if (! empty( $errors = $validator->errors() )) { // $errors structure: // [ // 'field_name' => ['Error message 1', 'Error message 2'], // 'another_field' => ['Error message'] // ] foreach ($errors as $field => $fieldErrors) { echo "Field '{$field}' has errors:\n"; foreach ($fieldErrors as $error) { echo " - {$error}\n"; } } }
Advanced Examples
Complex User Registration Validator
<?php use NightCommit\PHP\Sanity\Validator; class UserRegistrationValidator extends Validator { protected function rules(): array { return [ 'first_name' => ['required', 'string', 'min:2', 'max:30'], 'last_name' => ['required', 'string', 'min:2', 'max:30'], 'email' => ['required', 'email', 'max:255'], 'password' => ['required', 'string', 'min:8', 'strong_password'], 'password_confirmation' => ['required', 'confirmed:password'], 'age' => ['required', 'int', 'more:12', 'less:120'], 'phone' => ['nullable', 'string', 'regex:/^\+?[\d\s-()]+$/'], 'terms_accepted' => ['required', 'boolean:cast'], 'interests' => ['nullable', 'array', 'array_unique'], 'birth_date' => ['required', 'date', 'before:today'] ]; } protected function files(): array { return [ 'profile_picture' => ['nullable', 'file', 'ftype:jpg,jpeg,png', 'fsize:0,2,mb'] ]; } }
Requirements
- PHP 7.4 or higher
- Composer for installation
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This package is open-source software licensed under the MIT license.
Support
If you encounter any issues or have questions, please open an issue on GitHub.