7

私がやろうとしているのは次のとおりです。

  1. yml で制約を定義する

  2. これを使用して配列を検証します

たとえば、製品配列:

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

どうやってするか?

4

3 に答える 3

4

まず第一に、Symfony2 バリデーターはそれを簡単に行う準備ができていないことを知っておく必要があります。あなたのケースの実用的な解決策を得るには、しばらく時間がかかり、Symfony2 のソースを読む必要がありました。私の解決策はそれほど自然ではありません。

バリデーター、配列、および yaml 構成ファイルを受け取るクラスを作成したので、期待どおりのことができるようになります。このクラスはYamlFileLoaderSymfony の を拡張して保護されたメソッドにアクセスします。これは美しくありませんが、カスタム Yaml 構成ファイルをオブジェクトparseNodesの配列に変換する唯一の方法です。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 \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."
  }
}

お役に立てれば。

于 2012-09-30T13:27:07.257 に答える
1

配列を検証する方法は簡単です。サイレックスのドキュメントで学びました

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

または、制約のあるフォームを直接作成できます

$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();

}

このコードは 2 番目のポイントを解決できますが、最初のポイントについては、インスタンス化された検証制約オブジェクトを使用して yaml 定義を有効な制約配列に変換するカスタム クラスを作成するか、フォームを直接提供することをお勧めします!

symfony2 でこれを行う準備ができているクラスを知りません。

私は良いデータモデルを持っていない他のプロジェクトでそれを行いましたが、symfony ではモデルを作成し、それに関連する検証を定義することができます。

于 2012-09-28T17:51:26.537 に答える