2012-11-13 18 views
14

私はこの制約を受け入れるためにdbのTWOフォームフィールドから値を検証する必要があるカスタムバリデータを作成しています。ビルドSymfony 2複数のフィールドを使用するカスタムバリデータ

私の質問はこれです:ContractValidatorのvalidateメソッドはそのシグネチャに1つの$値しか持たないので、検証のために複数のフィールドから値にアクセスするにはどうしたらいいですか?ここで

は、典型的なカスタムバリデータである:

namespace Acme\WebsiteBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\ConstraintValidator; 

class MyCustomValidator extends ConstraintValidator 
{ 
    public function validate($value, Constraint $constraint) 
    { 
    // check $value and return an error 
    // but in my case, i want the value from more than one form field to do a validation 
    // why? i'm checking that two pieces of information (ssn + dob year) match 
    // the account the user is registering for 
    } 
} 

はここで設定され、いくつかの検証を持つフォームクラスの例です:

namespace ACME\WebsiteBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 
use Symfony\Component\Validator\Constraints\Collection; 
use Symfony\Component\Validator\Constraints\MinLength; 
use Symfony\Component\Validator\Constraints\NotBlank; 
use Symfony\Component\Validator\Constraints\Regex; 
use ACME\WebsiteBundle\Validator\Constraints\UsernameAvailable; 

class AccountRegistration extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
    $builder->add('ssn', 'number', array(
     'max_length' => 9, 
     'required' => true, 
     'error_bubbling' => true) 
    ); 

    $builder->add('year_of_birth', 'choice', array(
     'choices' => range(date("Y") - 100, date("Y")), 
     'required' => true, 
     'empty_value' => 'Select ...', 
     'label' => 'Year of Birth', 
     'error_bubbling' => true) 
    ); 

    $builder->add('username', 'text', array(
     'required' => true, 
     'error_bubbling' => true) 
    ); 

    $builder->add('password', 'password', array(
     'max_length' => 25, 
     'required' => true, 
     'error_bubbling' => true) 
    ); 

    $builder->add('security_question', 'choice', array(
     'empty_value' => 'Select ...', 
     'choices' => array(), 
     'label' => 'Security Question', 
     'required' => true, 
     'error_bubbling' => true) 
    ); 

    $builder->add('security_question_answer', 'text', array(
     'label' => 'Answer', 
     'required' => true, 
     'error_bubbling' => true) 
    ); 
    } 

    public function getName() 
    { 
    return 'account_registration'; 
    } 

    public function getDefaultOptions(array $options) 
    { 

    $collectionConstraint = new Collection(array(
     'allowExtraFields' => true, 
     'fields' => array(
     'ssn' => array(new MinLength(array('limit' => 9, 'message' => 'too short.')), new NotBlank()), 
     'year_of_birth' => array(new NotBlank()), 
     'username' => array(new NotBlank(), new UsernameAvailable()), 
     'password' => array(new NotBlank(), new Regex(array(
      'message' => 'password must be min 8 chars, contain at least 1 digit', 
      'pattern' => "((?=.*\d)(?=.*[a-z]).{8,25})")) 
     ), 
     'security_question' => array(new NotBlank()), 
     'security_question_answer' => array(new NotBlank())) 
    ) 
    ); 

    return array(
     'csrf_protection' => true, 
     'csrf_field_name' => '_token', 
     'intention'  => 'account_registration', 
     'validation_constraint' => $collectionConstraint 
    ); 
    } 
} 

答えて

4

あなたはcookbooksで説明したようにCLASS_CONSTRAINTを使用する必要があります。その後、クラス全体を渡し、このクラスの任意のプロパティを使用できます。上記の例では、これは、文字列/整数が$valueではなく、検証するオブジェクト全体であることを意味します。

変更する必要があるのは、getTargets()の機能です(self::CLASS_CONSTRAINTを返す必要があります)。

また、プロパティレベルではなく、クラスレベルでバリデータを定義するようにしてください。あなたは注釈を使用している場合、これはバリデータがない一つの特定の属性定義上、クラスdefnition、上述しなければならないことを意味します:ConstraintValidator拡張

/** 
    * @MyValidator\SomeValidator 
    */ 
class MyClass { 

} 
+0

$contextは、あなたが提出したデータにアクセスすることができますExecutionContextのインスタンスです。私は単なるスタンドアロンのAbstractTypeフォームを作成しています。 – doremi

+0

しかし、検証しているオブジェクトがありますか?そうでない場合、バリデーションの設定方法に関するコードを表示できますか? – Sgoettschkes

+0

追加されました。あなたは全体を見るためにスクロールする必要がありますが、これはアカウント登録フォームです。既に追加した検証制約を下に表示することができます。 – doremi

16

任意のカスタムバリデータは$contextプロパティへのアクセス権を持っています。

例:私はクラスに対して検証していないよ

<?php 

namespace My\Bundle\MyBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\ConstraintValidator; 


class AppointorRoleValidator extends ConstraintValidator 
{ 

    public function validate($value, Constraint $constraint) 
    { 
     $values = $this->context->getRoot()->getData(); 
     /* ... */ 
    } 
} 
+3

$ values = $ this-> context-> getRoot() - > getData() –

+0

ありがとうございました –

+0

本当に$ values = $ this-> context-> getRoot()が必要でした可能だった –

関連する問題