Symonfy2验证:在yml中定义约束,并验证数组

我想要做的是:

  • 在yml中定义约束

  • 用它来验证一个数组

  • 说一个产品阵列:

    $product['name'] = 'A book';
    $product['date'] = '2012-09';
    $product['price'] = '21.5';
    

    怎么做?


    首先,您需要知道Symfony2验证程序尚未准备好轻松完成。 我花了一些时间和一些Symfony2源代码阅读来为你的案例找到一个可行的解决方案,而我的解决方案并不那么自然。

    我创建了一个需要验证器,你的数组和你的yaml配置文件的类,这样你就可以做你期望的。 这个类从Symfony扩展YamlFileLoader以访问受保护的parseNodes方法:这不是很美,但这是我发现将自定义Yaml配置文件转换为Constraint对象数组的唯一方法。

    所以我们就在这里。 我给你我的代码,你需要根据你自己的上下文来替换一些命名空间。

    首先,为我们的演示创建一个控制器:

        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 FuzTestsBundleServicesArrayValidator($validator, $product, "/tmp/test.yml");
            $errors = $service->validate();
    
            echo '<pre>';
            var_dump($errors);
            die();
    
            return $this->render('FuzTestsBundle:Default:index.html.twig');
        }
    

    然后创建一个名为ArrayValidator.php的类。 再次,照顾名称空间。

    <?php
    
    namespace FuzTestsBundleServices;
    
    use SymfonyComponentValidatorValidatorInterface;
    use SymfonyComponentYamlParser;
    use SymfonyComponentValidatorMappingLoaderYamlFileLoader;
    
    /**
     * 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;
        }
    
    }
    

    最后,在$ product数组中使用不同的值进行测试。

    默认 :

            $product = array ();
            $product['name'] = 'A book';
            $product['date'] = '2012-09';
            $product['price'] = '21.5';
    

    将显示:

    array(3) {
      ["name"]=>
      array(0) {
      }
      ["date"]=>
      array(0) {
      }
      ["price"]=>
      array(0) {
      }
    }
    

    如果我们将值更改为:

        $product = array ();
        $product['name'] = 'A very interesting book';
        $product['date'] = '2012-09-03';
        $product['price'] = '-21.5';
    

    你会得到 :

    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."
      }
    }
    

    希望这可以帮助。


    验证数组的方法很简单,我已经在IBM文档中学到了

    use SymfonyComponentValidatorConstraints as Assert;
    
    ...
    ...
    
    $constraint = new AssertCollection(array(
        'Name' => new AssertMinLength(10),
        'author' => new AssertCollection(array(
            'first_name' => array(new AssertNotBlank(), new AssertMinLength(10)),
            'last_name'  => new AssertMinLength(10),
        )),
    ));
    $errors = $this->get('validator')->validateValue($book, $constraint);
    

    或者您可以直接创建带约束的表单

    $form = $this->get('form.factory')->createBuilder('form',array(),array(
        'csrf_protection'       => false,
        'validation_constraint' => new AssertCollection(array(
            'name'       => new AssertNotBlank(array(
                'message' => 'Can't be null'
            )),
            'email'      => new AssertEmail(array(
                'message' => 'Invalid email'
            )),
        ))
    ))
    ->add('name', 'text')
    ->add('email', 'email')
    ->getForm();
    
    }
    

    这段代码可以解决你的第二点,但对于第一点,我建议你写一个自定义类,它将你的yaml定义转换为有效的约束数组,并带有实例化的验证约束对象,或者直接给出一个表单!

    我不知道在symfony2中准备好这样做的课程。

    我在其他没有良好数据模型的项目中完成了它,但是在symfony中,您可以创建模型并定义与其相关的验证。


    在你的validation.yml中:

    AcmeDemoBundleEntityAcmeEntity:
        properties:
            price:
                - NotBlank: ~
                - AcmeDemoBundleValidatorConstraintsContainsAlphanumeric: ~
    

    和您的ContainsAlphanumeric:

    <?php
        namespace AcmeDemoBundleValidatorConstraints;
        use SymfonyComponentValidatorConstraint;
        use SymfonyComponentValidatorConstraintValidator;
    
        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));
                }
            }
        }
    ?>
    
    链接地址: http://www.djcxy.com/p/64003.html

    上一篇: Symonfy2 validation: define constraints in yml, and validate an array

    下一篇: Missing Diagram folder in Database Explorer at Visual Studio 2012