2012-09-21 9 views

Respuesta

-1

en su validation.yml:

Acme\DemoBundle\Entity\AcmeEntity: 
    properties: 
     price: 
      - NotBlank: ~ 
      - Acme\DemoBundle\Validator\Constraints\ContainsAlphanumeric: ~ 

y su ContainsAlphanumeric:

<?php 
    namespace Acme\DemoBundle\Validator\Constraints; 
    use Symfony\Component\Validator\Constraint; 
    use Symfony\Component\Validator\ConstraintValidator; 

    class ContainsAlphanumericValidator extends ConstraintValidator 
    { 
     public function validate($value, Constraint $constraint) 
     { 
      if (!preg_match('/^[a-zA-Za0-9]+$/', $value, $matches)) { 
       $this->context->addViolation($constraint->message, array('%string%' => $value)); 
      } 
     } 
    } 
?> 
+1

Esto es para validar un objeto entidad, no lo que quiero –

1

la forma de validar una matriz es fácil, lo he aprendido en silex documentation

use Symfony\Component\Validator\Constraints as Assert; 

... 
... 

$constraint = new Assert\Collection(array(
    'Name' => new Assert\MinLength(10), 
    'author' => new Assert\Collection(array(
     'first_name' => array(new Assert\NotBlank(), new Assert\MinLength(10)), 
     'last_name' => new Assert\MinLength(10), 
    )), 
)); 
$errors = $this->get('validator')->validateValue($book, $constraint); 

o puede crear formularios directamente con restricciones

$form = $this->get('form.factory')->createBuilder('form',array(),array(
    'csrf_protection'  => false, 
    'validation_constraint' => new Assert\Collection(array(
     'name'  => new Assert\NotBlank(array(
      'message' => 'Can\'t be null' 
     )), 
     'email'  => new Assert\Email(array(
      'message' => 'Invalid email' 
     )), 
    )) 
)) 
->add('name', 'text') 
->add('email', 'email') 
->getForm(); 

} 

este código puede resolver su segundo punto, pero para el primer punto le sugiero que escriba una clase personalizada que transforma su definición yaml a una matriz de restricciones válidas con restricción de validación instanciado objetos o tal vez que le da una forma directa!

No sé de una clase lista para hacer esto en symfony2.

Lo he hecho en otros proyectos que no tienen un buen modelo de datos, pero en Symfony puedes crear tus modelos y definir la validación asociada.

+0

Gracias, pero ¿es posible definir restricciones en yml? –

+0

Como puede ver las restricciones son una simple matriz de objetos, puede definir esta matriz en un archivo yaml, luego cargar el archivo yaml en una matriz y crear una instancia de los objetos por sus nombres. Lo siento pero tienes que hacerlo con una clase/método personalizado que necesites crear, te dije cómo debería ser :) –

4

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.

+0

gracias, esta es una gran respuesta/explicación. Dios te bendiga;) – lexeme

Cuestiones relacionadas