Antes que nada, necesita saber que los validadores Symfony2 no están listos para hacerlo fácilmente. Me tomó algo de tiempo y algo de lectura de Symfony2 para obtener una solución de trabajo para su caso, y mi solución no es tan natural.
Hice una clase que tiene el validador, su matriz y su archivo de configuración yaml para que pueda hacer lo que espera. Esta clase amplía el YamlFileLoader
de Symfony para acceder al método parseNodes
protegido: esto no es hermoso, pero esa es la única forma que encontré para transformar un archivo de configuración personalizado de Yaml en una matriz del objeto Constraint
.
Así que aquí estamos. Te doy mi código, deberás reemplazar algunos espacios de nombres según tu propio contexto.
primer lugar, crear un controlador para nuestra demostración:
public function indexAction()
{
// We create a sample validation file for the demo
$demo = <<< EOT
name:
- NotBlank: ~
- MinLength: { limit: 3 }
- MaxLength: { limit: 10 }
date:
- NotBlank: ~
- Regex: "/^[0-9]{4}\-[0-9]{2}$/"
price:
- Min: 0
EOT;
file_put_contents("/tmp/test.yml", $demo);
// We create your array to validate
$product = array();
$product['name'] = 'A book';
$product['date'] = '2012-09';
$product['price'] = '21.5';
$validator = $this->get('validator');
$service = new \Fuz\TestsBundle\Services\ArrayValidator($validator, $product, "/tmp/test.yml");
$errors = $service->validate();
echo '<pre>';
var_dump($errors);
die();
return $this->render('FuzTestsBundle:Default:index.html.twig');
}
A continuación, cree una clase llamada ArrayValidator.php. Nuevamente, cuida el espacio de nombres.
<?php
namespace Fuz\TestsBundle\Services;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
/**
* This class inherits from YamlFileLoader because we need to call the
* parseNodes() protected method.
*/
class ArrayValidator extends YamlFileLoader
{
/* the @validator service */
private $validator;
/* The array to check */
private $array;
/* The file that contains your validation rules */
private $validationFile;
public function __construct(ValidatorInterface $validator, array $array = array(), $validationFile)
{
$this->validator = $validator;
$this->array = $array;
$this->validationFile = $validationFile;
}
/* The method that does what you want */
public function validate()
{
$yaml = file_get_contents($this->validationFile);
// We parse the yaml validation file
$parser = new Parser();
$parsedYaml = $parser->parse($yaml);
// We transform this validation array to a Constraint array
$arrayConstraints = $this->parseNodes($parsedYaml);
// For each elements of the array, we execute the validation
$errors = array();
foreach ($this->array as $key => $value)
{
$errors[$key] = array();
// If the array key (eg: price) has validation rules, we check the value
if (isset($arrayConstraints[$key]))
{
foreach ($arrayConstraints[$key] as $constraint)
{
// If there is constraint violations, we list messages
$violationList = $this->validator->validateValue($value, $constraint);
if (count($violationList) > 0)
{
foreach ($violationList as $violation)
{
$errors[$key][] = $violation->getMessage();
}
}
}
}
}
return $errors;
}
}
Finalmente, pruébela con diferentes valores en su matriz de $ productos.
Por defecto:
pantalla
$product = array();
$product['name'] = 'A book';
$product['date'] = '2012-09';
$product['price'] = '21.5';
Will:
array(3) {
["name"]=>
array(0) {
}
["date"]=>
array(0) {
}
["price"]=>
array(0) {
}
}
Si cambiamos los valores de:
$product = array();
$product['name'] = 'A very interesting book';
$product['date'] = '2012-09-03';
$product['price'] = '-21.5';
que obtendrá:
array(3) {
["name"]=>
array(1) {
[0]=>
string(61) "This value is too long. It should have 10 characters or less."
}
["date"]=>
array(1) {
[0]=>
string(24) "This value is not valid."
}
["price"]=>
array(1) {
[0]=>
string(31) "This value should be 0 or more."
}
}
Espero que esto ayude.
Esto es para validar un objeto entidad, no lo que quiero –