19

この制約を通過させるために、データベース内の2つのフォームフィールドからの値を検証する必要があるカスタムバリデーターを構築しています。

私の質問はこれです:ContractValidatorのvalidateメソッドの署名には$ valueが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

2 に答える 2

30

拡張するカスタムバリデーターはすべてConstraintValidator、プロパティにアクセスでき$contextます。送信されたデータへのアクセスを提供$contextするインスタンスです。ExecutionContext

例:

<?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();
        /* ... */
    }
}
于 2014-08-21T05:54:20.097 に答える
4

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

変更する必要があるのはgetTargets()関数だけで、これはを返す必要がありますself::CLASS_CONSTRAINT

また、プロパティレベルではなく、クラスレベルでバリデーターを定義するようにしてください。アノテーションを使用する場合、これは、バリデーターが1つの特定の属性定義の上ではなく、クラス定義の上に記述されている必要があることを意味します。

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

}
于 2012-11-13T16:15:21.463 に答える