Validation de la présence et du type des clés d'un tableau avec Symfony
Publié le 07/08/2021 • Actualisé le 07/08/2021
Dans ce bout de code, nous voyons comment valider la présence et le type des clés d'un tableau avec le composant de validation Symfony. C'est assez direct à faire grâce aux contraintes collection et type. La documentation Symfony (lien en dessous) nous indique qu'on peut caster la variable $violations
en tant que chaine. Cela fonctionne, mais PHPStan, à partir du niveau deux, lève une erreur. C'est pourquoi l'utilise une fonction fléchée pour extraire et afficher les erreurs.
<?php
declare(strict_types=1);
namespace App\Controller\Snippet;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Validation;
/**
* 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.
*/
trait Snippet158Trait
{
public function snippet158(): void
{
$validator = Validation::createValidator();
$inputs = [
[ // valid
'bar' => 'string', // string
'babar' => true, // bool
'john' => 555, // int
'fab' => ['4545'], // array
],
[ // NOT valid
'bar' => false, // wrong type
'babar' => 'true', // wrong type
'john' => 0.1, // wrong type
'fab' => new \stdClass(), // wrong type
'extra' => null, // extra field
],
];
$constraints = new Assert\Collection([
'bar' => new Assert\Type('string'),
'babar' => new Assert\Type('bool'),
'john' => new Assert\Type('int'),
'fab' => new Assert\Type('array'),
]);
foreach ($inputs as $input) {
/** @var ConstraintViolationList $violations */
$violations = $validator->validate($input, $constraints);
if ($violations->count() > 0) {
echo \sprintf("❌ needed keys of the array\n\%s\nare NOT correct:\n%s", var_export($input, true), $violations).PHP_EOL;
} else {
echo \sprintf("✅ All needed keys of the array:\n%s\nare present and of the good type.\n", var_export($input, true)).PHP_EOL;
}
}
// That's it! 😁
}
}
Exécuter le snippet ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫ Plus sur Stackoverflow Lire la doc Plus sur le web
<?php
declare(strict_types=1);
namespace App\Tests\Integration\Controller\Snippets;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validation;
/**
* @see Snippet158Trait
*/
final class Snippet158Test extends KernelTestCase
{
/**
* @return iterable<int, array<mixed>>
*/
public function provide(): iterable
{
yield [
'✅ valid case' => [
'bar' => 'string',
'babar' => true,
'john' => 555,
'fab' => ['4545'],
],
true,
0,
];
yield [
'❌ invalid case' => [
'bar' => false,
'babar' => 'true',
'john' => 0.1,
'fab' => new \stdClass(),
'extra' => null,
],
false,
5,
];
}
/**
* @see Snippet158Trait::snippet158
*
* @param array<int, mixed> $array
*
* @dataProvider provide
*/
public function testSnippet158(array $array, bool $isValid, int $errorsCount): void
{
$validator = Validation::createValidator();
$constraints = new Assert\Collection([
'bar' => new Assert\Type('string'),
'babar' => new Assert\Type('bool'),
'john' => new Assert\Type('int'),
'fab' => new Assert\Type('array'),
]);
$violations = $validator->validate($array, $constraints);
self::assertSame($isValid, $violations->count() === 0);
self::assertCount($errorsCount, $violations);
}
}