Utiliser la validation Symfony en dehors du contexte des formulaires
Publié le 30/01/2019 • Actualisé le 30/01/2019
Il est parfois utile de pouvoir utiliser la validation Symfony en dehors du contexte des formulaires. Dans un controller ou dans un service par exemple. Ci-dessous, on valide une liste de chaines sur deux contraintes différentes. Chaque contrainte ayant son propre message d'erreur.
<?php
declare(strict_types=1);
namespace App\Controller\Snippet;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\Url;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
* Ce code doit être apellé d'un contrôleur Symfony étendant AbstractController (depuis Symfony 4.2)
* ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
* Les services sont injectés dans le constructeur du contrôleur principal.
*
* @property ValidatorInterface $validator
*/
trait Snippet14Trait
{
/**
* @see https://symfony.com/doc/current/reference/constraints/Url.html#relativeprotocol
*/
public function snippet14(): void
{
$urls = [
'toto/foo/notanURL', // NOK: Will violate both constraints (length = 17)
'//example.com?foo=bar', // OK: valid with relative protocol URL
'https://www.strangebuzz.com/en/snippets/using-the-symfony-validation-outside-of-the-form-context', // OK: Standard URL
];
$constraints = [
new Url(['relativeProtocol' => true]), // Allow relative protocol
new Length(['min' => 20]), // Min len
];
foreach ($urls as $url) {
$violations = $this->validator->validate($url, $constraints);
if ($violations->count() > 0) {
foreach ($violations as $violation) {
if ($violation instanceof ConstraintViolation) {
$message = $violation->getMessage();
echo \sprintf('❌ The "%s" value is NOT valid: "%s"', $url, \is_string($message) ? $message : '').PHP_EOL;
}
}
} else {
echo \sprintf('✅ The "%s" value is valid.', $url).PHP_EOL;
}
}
// That's it! 😁
}
}
Exécuter le snippet ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫ Plus sur Stackoverflow Snippet aléatoire
<?php
declare(strict_types=1);
namespace App\Tests\Integration\Controller\Snippets;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\Url;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @see Snippet14Trait
*/
final class Snippet14Test extends KernelTestCase
{
private ValidatorInterface $validator;
protected function setUp(): void
{
$this->validator = self::getContainer()->get('validator');
}
/**
* @return iterable<int, array{0: string, 1: bool, 2: int}>
*/
public function provide(): iterable
{
yield ['toto/foo/notanURL', false, 2];
yield ['//example.com?foo=bar', true, 0];
yield ['https://www.strangebuzz.com/en/snippets/using-the-symfony-validation-outside-of-the-form-context', true, 0];
}
/**
* @see Snippet14Trait::snippet14
*
* @dataProvider provide
*/
public function testSnippet14(string $url, bool $isValid, int $count): void
{
$constraints = [
new Url(['relativeProtocol' => true]),
new Length(['min' => 20]),
];
$violations = $this->validator->validate($url, $constraints);
self::assertSame($isValid, $violations->count() === 0);
self::assertCount($count, $violations);
}
}