В этом случае вы должны использовать группы проверки на основе отправленных данных. Этот метод доступен начиная с Symfony 2.1.
И вам не нужно тянуть события. Смотри сюда:
формы — http://symfony.com/doc/current/book/forms.html#groups-based-on-submitted-data
проверка — http://symfony.com/doc/current/book/validation.html#validation-groups
Попробуйте этот подход. И вы должны получить такой код:
Скрипт сущности с валидаторами: src/Acme/AcmeBundle/Entity/Url.php
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
...
/**
* @ORM\Column(name="port", type="integer")
* @Assert\NotBlank(groups={"validation_partial", "validation_full"})
*/
private $port;
/**
* @ORM\Column(name="protocol", type="string", length=10)
* @Assert\NotBlank(groups={"validation_full"})
*/
private $protocol;
...
Скрипт формы: src/Acme/AcmeBundle/Form/UrlType.php
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
...
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => function(FormInterface $form) {
$data = $form->getData();
if ('port' == $data->getType()) {
return array('validation_full');
} else {
return array('validation_partial');
}
},
));
}
Хорошо, я постараюсь подробно ответить на ваш вопрос. Например. У нас есть FormType вот так:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name') // Some text field 'Name'
;
$builder->addEventListener(FormEvents::PRE_BIND, function(FormEvent $event) use ($options) {
$event->getForm()->get('name')->addError(new FormError('*** ERROR PRE_BIND'));
});
$builder->addEventListener(FormEvents::BIND, function(FormEvent $event) use ($options) {
$event->getForm()->get('name')->addError(new FormError('*** ERROR BIND'));
});
$builder->addEventListener(FormEvents::POST_BIND, function(FormEvent $event) use ($options) {
$event->getForm()->get('name')->addError(new FormError('*** ERROR POST_BIND'));
});
}
Ты прав. Если добавить ошибки в прослушиватели для событий: PRE_BIND, BIND, POST_BIND. Вы получите только ошибки от событий BIND и POST_BIND. Чтобы понять, почему это так, нужно знать 2 момента.
Первое. Каждый элемент формы также является формой. В нашем случае наша основная форма имеет дочерние элементы «Имя» (текстовый элемент), которые также являются формой.
[Основная форма]
-> [ИмяФормы]
// могут быть дополнительные формы, если в вашей форме есть другие элементы
Второе: когда вы привязываете запрос к MainForm, вы вызываете функцию bind().
И эта функция вызывает функцию bind() для каждого дочернего элемента MainForm.
Ответ на ваш вопрос содержится в алгоритме этой функции. Алгоритм функции bind():
function bind($submittedData) {
1) clear all errors
2) dispatch event PRE_BIND
3) invoke bind() function for children
4) dispatch event BIND
5) dispatch event POST_BIND
}
Таким образом, на основе нашего примера программный поток будет таким:
Invoke bind() function for MainForm
1) MainForm - clear all errors
2) MainForm - dispatch event PRE_BIND // there our listener add error for child NameForm.
3) MainForm - invoke bind() function for child NameForm:
1) NameForm - clear all errors // is the answer for your question, error from event MainForm:PRE_BIND cleared!!!
2) NameForm - dispatch event PRE_BIND // no changes
3) NameForm - invoke bind() for children // this form does not have children, so will be passed
4) NameForm - dispatch event BIND // no changes
5) NameForm - dispatch event POST_BIND // no changes
4) MainForm - dispatch event BIND // there our listener add error to child NameForm
5) MainForm - dispatch event POST_BIND // there our listener add another error to child NameForm.
Я надеюсь, что это объяснение будет полезным для вас.
person
QArea
schedule
06.05.2013
isValid()
- person Patrick James McDougle   schedule 03.09.2015