A Symfony Validator wrapper that enables fluent-style validation for raw values, offering an easy-to-use and intuitive API to validate user input or other data in a concise and readable manner.
Note
This library will always (try to) be in sync with the latest Symfony Validator version.
- 🌊 Fluent-style validation: Chain validation methods for better readability and flow.
- 🤘 Constraints autocompletion: Enables IDE autocompletion for available constraints.
- 🔥 Three validation methods: Use
validate,assert, orisValidbased on the context (i.e., collect errors or throw exceptions). - ⚙️ Custom constraints: Integrate custom validation logic with Symfony's Validator system.
- 💬 Translations support: Translate validation error messages into multiple languages.
- PHP 8.4 or higher.
Install via Composer:
composer require programmatordev/fluent-validatorUse Fluent Validator when you want Symfony Validator constraints for raw values without setting up object metadata, attributes, forms, or a larger validation layer. It is useful for small input checks, command arguments, request fragments, webhook payload values, configuration values, and library code.
This package does not replace Symfony Validator. It wraps Symfony Validator and keeps its constraints, violation objects, groups, translations, and custom constraint model.
Simple usage example:
use ProgrammatorDev\FluentValidator\Validator;
// example: validate the user's age to ensure it's between 18 and 60
$errors = Validator::notBlank()
->greaterThanOrEqual(18)
->lessThan(60)
->validate($age);
if ($errors->count() > 0) {
// handle errors
}Use assert when invalid values should stop the current flow:
use ProgrammatorDev\FluentValidator\Exception\ValidationFailedException;
use ProgrammatorDev\FluentValidator\Validator;
try {
Validator::notBlank()->email()->assert($email, 'email');
}
catch (ValidationFailedException $exception) {
$message = $exception->getMessage();
// "email: This value is not a valid email address."
}Use isValid when you only need a boolean:
use ProgrammatorDev\FluentValidator\Validator;
if (!Validator::url()->isValid($website)) {
// handle invalid URL
}Constraint autocompletion is available in IDEs like PhpStorm. The suggested methods are generated from the installed Symfony Validator constraints. The method names match Symfony constraints but with a lowercase first letter:
NotBlank=>notBlankAll=>allPasswordStrength=>passwordStrength- ...and so on.
For all available constraints, check the Constraints section.
For all available methods, check the Methods section.
There is also a section for Custom Constraints and Translations.
Validation groups work the same way as in Symfony Validator:
use ProgrammatorDev\FluentValidator\Validator;
$validator = Validator::notBlank(groups: ['Default'])
->email(groups: ['registration']);
$validator->isValid('invalid-email', groups: ['Default']); // true
$validator->isValid('invalid-email', groups: ['registration']); // falseAll available constraints can be found on the Symfony Validator documentation.
For custom constraints, check the Custom Constraints section.
use Symfony\Component\Validator\Constraints\GroupSequence;
validate(mixed $value, ?string $name = null, string|GroupSequence|array|null $groups = null): ConstraintViolationListInterfaceReturns a ConstraintViolationList object, acting as an array of errors.
use ProgrammatorDev\FluentValidator\Validator;
$errors = Validator::email()->validate('test@email.com');
if ($errors->count() > 0) {
foreach ($errors as $error) {
$message = $error->getMessage();
// ...
}
}use Symfony\Component\Validator\Constraints\GroupSequence;
assert(mixed $value, ?string $name = null, string|GroupSequence|array|null $groups = null): voidThrows a ValidationFailedException when validation fails.
use ProgrammatorDev\FluentValidator\Exception\ValidationFailedException;
use ProgrammatorDev\FluentValidator\Validator;
try {
Validator::notBlank()->assert($name);
Validator::notBlank()->email()->assert($email);
}
catch (ValidationFailedException $exception) {
// the exception message will always be the first error thrown
$message = $exception->getMessage();
// value that failed validation
$invalidValue = $exception->getInvalidValue();
// get access to all errors
// returns a ConstraintViolationList object like in the validate method
$errors = $exception->getViolations();
// ...
}use Symfony\Component\Validator\Constraints\GroupSequence;
isValid(mixed $value, string|GroupSequence|array|null $groups = null): boolReturns a bool indicating if the value is valid.
use ProgrammatorDev\FluentValidator\Validator;
if (!Validator::email()->isValid($email)) {
// handle invalid email
}use Symfony\Component\Validator\Constraint;
/** @return Constraint[] */
toArray(): arrayReturns an array with all added constraints.
use ProgrammatorDev\FluentValidator\Validator;
$constraints = Validator::notBlank()->email()->toArray();It is useful for Composite constraints (i.e., a constraint that is composed of other constraints)
and keeps the fluent-style validation:
use ProgrammatorDev\FluentValidator\Validator;
// validate that the array should have at least one value
// and each value should be between 0 and 100
$errors = Validator::count(min: 1)
->all(Validator::range(min: 0, max: 100)->toArray())
->validate($value);addNamespace(string $namespace): voidUsed to add namespaces for custom constraints.
Check the Custom Constraints section.
use Symfony\Contracts\Translation\TranslatorInterface;
setTranslator(?TranslatorInterface $translator): voidUsed to add a translator for validation error message translations.
Check the Translations section.
reset(): voidClears globally registered custom constraint namespaces and translator configuration. Useful when changing global validator configuration in tests, workers, or other long-running PHP processes.
If you need a custom constraint, follow the Symfony Validator documentation: Creating Custom Constraints.
This class defines the error message and configurable options.
namespace App\Constraint;
use Symfony\Component\Validator\Constraint;
class ContainsAlphanumeric extends Constraint
{
// set configurable options
}The validator checks if the value complies with the constraint rules.
namespace App\Constraint;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class ContainsAlphanumericValidator extends ConstraintValidator
{
public function validate(mixed $value, Constraint $constraint): void
{
// custom validation logic
}
}Register the namespace where the custom constraints will be located in your project.
use ProgrammatorDev\FluentValidator\Validator;
Validator::addNamespace('App\Constraint');
Validator::notBlank()->containsAlphanumeric()->isValid('!'); // false
Validator::notBlank()->containsAlphanumeric()->isValid('v4l1d'); // trueYou can have multiple constraints in the same namespace or have multiple namespaces.
Note
Custom constraints will not be suggested in IDE autocompletion.
Set a global translator to handle error message translations.
use ProgrammatorDev\FluentValidator\Translator\Translator;
// set translator to Portuguese (Portugal) locale
Validator::setTranslator(new Translator('pt'));
// now all error messages will be in Portuguese
Validator::notBlank()->validate('');To add your own translations, you can integrate a custom translator.
Any form of contribution to improve this library (including requests) will be welcome and appreciated. Make sure to open a pull request or issue.
This project is licensed under the MIT license. Please see the LICENSE file distributed with this source code for further information regarding copyright and licensing.