digitalrevolution/symfony-validation-shorthand
Installation:
composer require digitalrevolution/symfony-validation-shorthand
Ensure your project meets the requirements: PHP ≥ 8.1 and Symfony ≥ 6.2.
Basic Setup:
Import the ConstraintFactory and Validation components:
use DigitalRevolution\SymfonyValidationShorthand\ConstraintFactory;
use Symfony\Component\Validator\Validation;
First Use Case: Validate a simple form submission:
$rules = [
'email' => 'required|email',
'age' => 'integer|min:18'
];
$constraint = (new ConstraintFactory())->fromRuleDefinitions($rules);
$validator = Validation::createValidator();
$violations = $validator->validate($data, $constraint);
Check violations:
foreach ($violations as $violation) {
echo $violation->getPropertyPath() . ': ' . $violation->getMessage() . "\n";
}
required|string|min:5).name.first_name).? to field names (e.g., tags?.* for optional arrays).Form Validation:
$rules = ['username' => 'required|string|max:255|unique:users'];
$constraint = (new ConstraintFactory())->fromRuleDefinitions($rules);
$validator = Validation::createValidator();
$errors = $validator->validate($request->all(), $constraint);
API Request Validation:
$rules = [
'data.*' => 'required|array',
'data.*.name' => 'required|string',
];
Dynamic Rules:
$dynamicRules = [];
foreach ($user->roles as $role) {
$dynamicRules["role_{$role->id}"] = 'required|string';
}
$constraint = (new ConstraintFactory())->fromRuleDefinitions($dynamicRules);
Symfony Forms: Use with Symfony’s ValidatorInterface in form types:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('email', EmailType::class, [
'constraints' => [(new ConstraintFactory())->fromRuleDefinitions(['email' => 'required|email'])],
]);
}
Custom Constraints: Extend ConstraintFactory to add custom rules:
class CustomConstraintFactory extends ConstraintFactory {
protected function registerCustomRules(): void {
$this->addRule('custom_rule', CustomConstraint::class);
}
}
Nested Arrays:
tags?.* require the field to be an array and non-empty if present. Test edge cases:
$data = ['tags' => []]; // Will fail if `required` is set.
Regex Rules:
regex:/^020\d+$/) or delimiters (e.g., regex:/pattern/). Avoid unescaped slashes in patterns.Unique Constraints:
unique rule requires a table name and column (e.g., unique:users,email). Ensure your database connection is configured.Case Sensitivity:
Name.first ≠ name.first).Constraint Tree: Inspect the generated constraint for debugging:
$constraint = (new ConstraintFactory())->fromRuleDefinitions($rules);
dump($constraint); // Use a dumper like Symfony's VarDumper
Validation Groups: Use Validation::createValidator()->validate($data, $constraint, null, ['group' => 'custom']) for grouped validation.
Reusable Rules: Create a helper method to standardize rule definitions:
protected function getValidationRules(): array {
return [
'email' => 'required|email',
'password' => 'required|confirmed',
];
}
Custom Error Messages:
Override default messages via Symfony’s Constraint classes or use the message parameter:
$rules = ['email' => 'required|email:message=The email is invalid.'];
Performance:
Reuse the ConstraintFactory and Validator instances where possible to avoid rebuilding constraints:
$factory = new ConstraintFactory();
$validator = Validation::createValidator();
foreach ($requests as $request) {
$constraint = $factory->fromRuleDefinitions($rules);
$validator->validate($request->all(), $constraint);
}
Testing:
Mock the ConstraintFactory and Validator in unit tests:
$factory = $this->createMock(ConstraintFactory::class);
$factory->method('fromRuleDefinitions')->willReturn($constraint);
Extension Points:
ConstraintFactory to add custom rules or modify existing behavior.Constraint and ConstraintValidator interfaces to create reusable validation logic.How can I help you explore Laravel packages today?