milwad/laravel-validate
Enhanced Laravel validation with a large set of custom rule classes and helper methods for faster, cleaner advanced validation. Includes localization support and works with Laravel 9+ (PHP 8+), with community-contributed language packs.
Installation:
composer require milwad/laravel-validate
Ensure your project meets the requirements (PHP >= 8.0, Laravel >= 9.0).
First Use Case: Validate a phone number in a form request:
use Milwad\LaravelValidate\Rules\ValidPhoneNumber;
public function rules()
{
return [
'phone' => ['required', new ValidPhoneNumber()],
];
}
Quick Start with String Rules:
Publish the config to enable string-based rule usage (e.g., ValidPhone):
php artisan vendor:publish --tag="laravel-validate-config"
Update config/laravel-validate.php:
'using_container' => true,
Now use rules directly in validation strings:
'phone' => 'required|ValidPhone',
Rule Instantiation: Prefer instantiating custom rules for complex logic:
$validator = Validator::make($data, [
'field' => [new ValidCreditCard(), 'required'],
]);
Chaining Rules: Combine built-in and custom rules for granular validation:
'email' => [
'required',
'email',
new ValidDomain(), // Ensure domain is valid
],
Dynamic Rule Parameters: Pass parameters to custom rules via constructors:
new ValidDuplicate(['field' => 'other_field']) // Check for duplicates in another field
Form Request Integration:
Extend FormRequest to centralize validation logic:
use Milwad\LaravelValidate\Rules\ValidIranPostalCode;
public function rules()
{
return [
'postal_code' => ['required', new ValidIranPostalCode()],
];
}
API Validation: Use in API resources or DTOs for consistent validation:
use Milwad\LaravelValidate\Rules\ValidJwt;
public function validateJwt($jwt)
{
return (new ValidJwt())->passes($jwt);
}
Localization: Publish language files for custom messages:
php artisan vendor:publish --tag="validate-lang-en"
Override messages in resources/lang/en/validation.php:
'valid_phone_number' => 'The :attribute must be a valid phone number.',
Custom Rule Extensions: Extend existing rules for project-specific needs:
namespace App\Rules;
use Milwad\LaravelValidate\Rules\ValidEmail;
class ValidCompanyEmail extends ValidEmail
{
public function passes($attribute, $value)
{
return parent::passes($attribute, $value)
&& str_ends_with($value, '@company.com');
}
}
Testing:
Test rules in isolation using Laravel’s TestCase:
public function test_valid_phone_number()
{
$rule = new ValidPhoneNumber();
$this->assertTrue($rule->passes('phone', '+1234567890'));
$this->assertFalse($rule->passes('phone', 'invalid'));
}
Performance: Cache rule instances if reused frequently (e.g., in middleware):
$rule = app()->make(ValidIban::class); // Resolve once and reuse
Container Resolution:
using_container is false, string rules (e.g., ValidPhone) won’t work. Ensure the config is set correctly:
'using_container' => true,
config('laravel-validate.using_container') in a Tinker session if rules fail silently.Rule Overrides:
ValidEmail) will shadow Laravel’s native rules. Prefix custom rules to avoid conflicts:
namespace App\Rules;
class ValidCustomEmail extends \Milwad\LaravelValidate\Rules\ValidEmail { ... }
Locale-Specific Rules:
ValidIranPostalCode) are region-specific. Ensure the input matches the expected format (e.g., 3354355599 for Iran).Parameter Handling:
ValidDuplicate(['field' => 'other_field'])) must be instantiated with the correct arguments. Missing parameters may cause UndefinedArrayKeyException.Deprecation:
Validation Failures:
Validator::extend() to debug custom rules:
Validator::extend('custom_rule', function ($attribute, $value, $parameters) {
\Log::debug("Validating $attribute: $value with params: " . json_encode($parameters));
return true; // or false
});
Rule Instantiation Errors:
composer dump-autoload
ValidPhoneNumber vs. ValidPhone).Localization Issues:
php artisan config:clear
after publishing.Performance Bottlenecks:
ValidJwt with large payloads).Custom Rule Categories:
Group rules by domain (e.g., Financial, Geographic) in a service provider:
public function boot()
{
Validator::extend('financial', function ($attribute, $value, $rule, $parameters) {
return app("App\Rules\\Financial\\{$rule}")->passes($attribute, $value);
});
}
Dynamic Rule Generation:
Use the package’s Rule facade to create rules programmatically:
use Milwad\LaravelValidate\Facades\Rule;
$rule = Rule::make('ValidCreditCard')->withMessage('Invalid card.');
Rule Macros: Extend Laravel’s validator with custom macros for reusable logic:
Validator::macro('validateIranianId', function ($attribute, $value, $message, $customAttributes) {
return (new ValidIranianId())->passes($attribute, $value);
});
Usage:
'national_id' => 'required|validateIranianId',
Event-Based Validation:
Trigger validation rules on model events (e.g., saving):
use Milwad\LaravelValidate\Rules\ValidEmail;
public function saving()
{
$validator = Validator::make(['email' => $this->email], [
'email' => new ValidEmail(),
]);
if ($validator->fails()) {
throw new \Exception($validator->errors()->first());
}
}
Testing Rule Logic: Mock rule instances in tests to isolate validation logic:
$rule = $this->createMock(ValidPhoneNumber::class);
$rule->method('passes')->willReturn(true);
$validator = Validator::make($data, ['phone' => $rule]);
How can I help you explore Laravel packages today?