2014-10-22 2 views
2

У меня возникли проблемы с закрытием некоторых ограничений проверки, если в форме выбран определенный параметр. Эта опция не связана с моделью и не устанавливается с помощью опции data_class.Symfony, входящий в форму необязательно при отправке

В моей форме содержатся две встроенные формы адресов, которые точно такие же, как в одном адресе счета и одном адресе на отправку. Если выбрана альтернативная опция, я хочу сделать форму адреса отправки необходимой для проверки. Если альтернативный вариант не выбран, форма адреса отправления не требует проверки и должна быть оставлена ​​в покое.

CustomerCheckoutForm

class CustomerCheckoutForm extends AbstractType 
{ 

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('id', 'hidden') 
     ->add('firstName', 'text') 
     ->add('nameAdditions', 'text') 
     ->add('lastName', 'text') 
     ->add('gender', 'choice', array('expanded' => true, 'choices' => array('m' => 'M', 'f' => 'F'))) 
     ->add('birthDate', 'date', array(
      'required' => true, 
      'input' => 'string', 
      'widget' => 'choice', 
      'years' => range(DATE_CURRENT_YEAR - 80, DATE_CURRENT_YEAR - 18), 
      'empty_value' => array('year' => 'Year', 'month' => 'Month', 'day' => 'Day') 
     )) 
     ->add('invoiceAddress', new AddressForm($options['countryMapper']), array(
      'label' => false, 
      'required' => true, 
     )) 
     ->add('alternative_shipment_address', 'choice', array(
      'expanded' => true, 
      'choices' => array(0 => 'Delivery on the current address', 1 => 'Alternative shipping address'), 
      'mapped' => false, 
      'required' => true, 
      'label' => 'Delivery address', 
      'data' => 0, 
     )) 
     ->add('shipmentAddress', new AddressForm($options['countryMapper']), array(
      'label' => false, 
      'required' => false, 
     )) 
     ->add('Continue', 'submit'); 

    $this->registerListeners($builder); 
} 

private function registerListeners(FormBuilderInterface $builder) 
{ 
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) { 
     $customer = $event->getData(); 
     $form = $event->getForm(); 

     if (!$customer || $customer->getId() === null) { 
      $form->add('password', 'password'); 
     } 
    }); 
} 

/** 
* {@inheritdoc} 
*/ 
public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'EHV\SharedBundle\Model\Customer', 
     'countryMapper' => null, 
     'validation_groups' => array(
      'Default', 
      'checkout', 
     ), 
    )); 
} 

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

} 

AddressForm

class AddressForm extends AbstractType 
{ 

private $countryMapper; 

public function __construct(CountryMapper $countryMapper) 
{ 
    $this->countryMapper = $countryMapper; 
} 

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $transformer = new CountryToIdTransformer($this->countryMapper); 
    $countries = $this->countryMapper->getAll(); 
    $data[''] = 'Make a choice...'; 

    /** @var Country $country */ 
    foreach ($countries as $country) { 
     $data[$country->getId()] = $country->getName(); 
    } 

    $builder 
     ->add('id', 'hidden') 
     ->add('streetName', 'text') 
     ->add('streetNumber', 'text') 
     ->add('streetNumberAddition', 'text') 
     ->add('postalCode', 'text') 
     ->add('city', 'text') 
     ->add(
      $builder->create('country', 'choice', array('choices' => $data)) 
       ->addModelTransformer($transformer) 
     ); 
} 

/** 
* {@inheritdoc} 
*/ 
public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'EHV\SharedBundle\Model\Address', 
    )); 
} 

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

} 

Обе модели имеют свои собственные ограничения устанавливаются с помощью функции:

public static function loadValidatorMetadata(ClassMetaData $metadata) {} 

ответ

1

заказ обратного звонка Ограничения http://symfony.com/doc/current/reference/constraints/Callback.html

Вы можете прочитать стоимость своих адресов и при необходимости повысить погрешность.

+0

Это будет работать, только если у меня есть свойство «alternative_shipment_address» как свойство в модели «Customer». Или есть некоторая возможность получить доступ к не отображаемым переменным в Model Constraints? – stixx

0

Мне удалось использовать Form event listener с Constraint Callback, на который ответил Hpatoio, подробнее.

CustomerCheckoutForm

$builder->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) { 
     $form = $event->getForm(); 
     $customer = $event->getData(); 

     if ($form->get('alternative_shipment_address')->getData() === 0) { 
      $customer->setShipmentAddress(null); 
     } 
    }); 

CustomerConstraint

$callback = function($customer) use ($metadata) { 
     $metadata->addPropertyConstraint('invoiceAddress', new Valid()); 

     /** @var Customer $customer */ 
     if ($customer->getShipmentAddress() !== null) { 
      $metadata->addPropertyConstraint('shipmentAddress', new Valid()); 
     } 
    }; 

    $metadata->addConstraint(new Callback($callback)); 

Кредиты на Hpatoio для указывая правильное направление.

+1

Ты слишком милый. Я все еще копал, чтобы дать вам полный ответ, но вы были быстрее! – Hpatoio

+0

Для записи ** не используйте ** cascade_validation => true' в качестве опции, так как ограничения Customer обрабатывают проверку адреса. – stixx