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.
- 🌊 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: Easily integrate custom validation logic with Symfony's Validator system.
- 💬 Translations support: Translate validation error messages into multiple languages.
- PHP 8.2 or higher.
Install via Composer:
composer require programmatordev/fluent-validatorSimple 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 }Constraints autocompletion is available in IDEs like PhpStorm. 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.
All 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) { // exception message will always be the first error thrown $message = $exception->getMessage(); // value that failed validation $value = $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 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.
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.