2012-11-13 16 views
14

Bu kısıtlamanın geçmesi için db'deki TWO form alanlarındaki değeri doğrulaması gereken özel bir doğrulayıcıyı yapıyorum.Building Symfony 2 Birden Fazla Alan Kullanan Özel Doğrulama Aracı

Soruma şudur: ContractValidator'ın doğrulama yöntemi yalnızca imzasında bir $ değerine sahiptir, bu nedenle doğrulama için tek bir alandan daha fazla değerlere nasıl erişebilirim?

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

İşte ayarlanmış bazı doğrulamaları bir form sınıfının bir örnek::

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

cevap

4

Sen cookbooks anlatıldığı gibi CLASS_CONSTRAINT kullanmak gerekir

İşte tipik özel doğrulayıcı olduğunu. Daha sonra tüm sınıfı geçip bu sınıfın herhangi bir özelliğini kullanabilirsiniz. Yukarıdaki örneğinizde, bu, $value bir dizgi/tamsayı yerine, doğrulamak istediğiniz nesnenin tamamı olacağı anlamına gelir.

Değiştirmeniz gereken tek şey, dönmek zorunda olan getTargets() işlevlerdir. Ayrıca, değerleme aracınızı özellik düzeyinde değil, sınıf düzeyinde tanımladığınızdan emin olun. Eğer ek açıklamalar kullanırsanız bu doğrulayıcı değil belirli bir nitelik tanımı yukarıda, sınıf defnition yukarıda açıklanan gerektiği anlamına gelir: ConstraintValidator uzanır

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

} 
+0

$context Eğer sunulan verilere erişim sağlar ExecutionContext bir örneğidir. Ben sadece soyut bir SoyutType formu yaratıyorum. – doremi

+0

Ancak, doğruladığınız bir nesneyiniz var mı? Değilse, doğrulamaları nasıl belirlediğinize ilişkin kodu gösterebilir misiniz? – Sgoettschkes

+0

Eklendi. Her şeyi görmek için kaydırmanız gerekir, ancak bu hesap kayıt formudur. Altta zaten eklediğim doğrulama kısıtlamalarını görebilirsiniz. – doremi

16

Herhangi özel doğrulayıcı $context özelliğine erişimi vardır.

Örnek: Bir sınıfa karşı doğrulayarak değilim

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

$ değerler = $ this-> context-> getRoot() -> getData() –

+0

için çok teşekkür ederim. –

+0

'a gerçekten ihtiyacım var. Gerçekten gerekli $ değerleri = $ this-> context-> getRoot() mümkün oldu –