php - Symonfy2 验证 : define constraints in yml, 并验证一个数组

标签 php forms validation symfony

我想做的是:

  1. 在yml中定义约束

  2. 用它来验证数组

比如说,一个产品数组:

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

怎么做?

最佳答案

首先,您需要知道 Symfony2 验证器还没有准备好轻松做到这一点。我花了一些时间和一些 Symfony2 源代码阅读来为你的案例找到一个可行的解决方案,而我的解决方案并不是那么自然。

我制作了一个包含验证器、您的数组和您的 yaml 配置文件的类,因此您将能够执行您期望的操作。此类扩展了 Symfony 的 YamlFileLoader 以访问 protected parseNodes 方法:这并不漂亮,但这是我发现将自定义 Yaml 配置文件转换为数组的唯一方法约束对象。

所以我们到了。我给你我的代码,你需要根据自己的上下文替换一些 namespace 。

首先,为我们的演示创建一个 Controller :

    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');
    }

然后创建一个名为 ArrayValidator.php 的类。同样,请注意命名空间。

<?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;
    }

}

最后,使用 $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."
  }
}

希望这对您有所帮助。

关于php - Symonfy2 验证 : define constraints in yml, 并验证一个数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12527481/

相关文章:

javascript - 引导问题中的单选按钮 onclick

php - 更新用于 HTML 表单和 php 的语法

javascript - 如何防止页面在表单提交后重新加载 - JQuery

c# - 当模型包含另一个类的对象作为使用 DataAnnotations 的属性时,如何在控制台应用程序中验证 .Net Core 3.1 中的模型?

javascript - 为什么这个handleBlur函数带有事件参数,而函数内部没有使用事件参数呢?

c - 如何验证用户输入?

php - 将两个 MySQL 查询与 PHP 结合起来

php - 如何使用返回值的存储过程从MySQL返回总记录数

ruby-on-rails - 如何在选择表单中使用 attr_accessor?

Javascript 表单验证可能不起作用