发布于 2015-08-27 16:40:25 | 141 次阅读 | 评论: 0 | 来源: 网络整理
The Form component provides a structured process to let you customize your forms, by making use of the EventDispatcher component. Using form events, you may modify information or fields at different steps of the workflow: from the population of the form to the submission of the data from the request.
Registering an event listener is very easy using the Form component.
For example, if you wish to register a function to the FormEvents::PRE_SUBMIT
event, the following code lets you add a field, depending on the request values:
// ...
use SymfonyComponentFormFormEvent;
use SymfonyComponentFormFormEvents;
$listener = function (FormEvent $event) {
// ...
};
$form = $formFactory->createBuilder()
// add form fields
->addEventListener(FormEvents::PRE_SUBMIT, $listener);
// ...
FormEvents::PRE_SET_DATA
and FormEvents::POST_SET_DATA
)¶Two events are dispatched during pre-population of a form, when Form::setData()
is called: FormEvents::PRE_SET_DATA
and FormEvents::POST_SET_DATA
.
FormEvents::PRE_SET_DATA
Event¶The FormEvents::PRE_SET_DATA
event is dispatched at the beginning of the Form::setData()
method. It can be used to:
Data Type | Value |
---|---|
Model data | null |
Normalized data | null |
View data | null |
警告
During FormEvents::PRE_SET_DATA
, Form::setData()
is locked and will throw an exception if used. If you wish to modify data, you should use FormEvent::setData()
instead.
FormEvents::POST_SET_DATA
Event¶The FormEvents::POST_SET_DATA
event is dispatched at the end of the Form::setData()
method. This event is mostly here for reading data after having pre-populated the form.
Data Type | Value |
---|---|
Model data | Model data injected into setData() |
Normalized data | Model data transformed using a model transformer |
View data | Normalized data transformed using a view transformer |
FormEvents::PRE_SUBMIT
, FormEvents::SUBMIT
and FormEvents::POST_SUBMIT
)¶Three events are dispatched when Form::handleRequest()
or Form::submit()
are called: FormEvents::PRE_SUBMIT
, FormEvents::SUBMIT
, FormEvents::POST_SUBMIT
.
FormEvents::PRE_SUBMIT
Event¶The FormEvents::PRE_SUBMIT
event is dispatched at the beginning of the Form::submit()
method.
It can be used to:
Data Type | Value |
---|---|
Model data | Same as in FormEvents::POST_SET_DATA |
Normalized data | Same as in FormEvents::POST_SET_DATA |
View data | Same as in FormEvents::POST_SET_DATA |
FormEvents::SUBMIT
Event¶The FormEvents::SUBMIT
event is dispatched just before the Form::submit()
method transforms back the normalized data to the model and view data.
It can be used to change data from the normalized representation of the data.
Data Type | Value |
---|---|
Model data | Same as in FormEvents::POST_SET_DATA |
Normalized data | Data from the request reverse-transformed from the request using a view transformer |
View data | Same as in FormEvents::POST_SET_DATA |
警告
At this point, you cannot add or remove fields to the form.
FormEvents::POST_SUBMIT
Event¶The FormEvents::POST_SUBMIT
event is dispatched after the Form::submit()
once the model and view data have been denormalized.
It can be used to fetch data after denormalization.
Data Type | Value |
---|---|
Model data | Normalized data reverse-transformed using a model transformer |
Normalized data | Same as in FormEvents::POST_SUBMIT |
View data | Normalized data transformed using a view transformer |
警告
At this point, you cannot add or remove fields to the form.
In order to be able to use Form events, you need to create an event listener or an event subscriber, and register it to an event.
The name of each of the “form” events is defined as a constant on the FormEvents
class. Additionally, each event callback (listener or subscriber method) is passed a single argument, which is an instance of FormEvent
. The event object contains a reference to the current state of the form, and the current data being processed.
Name | FormEvents Constant |
Event’s Data |
---|---|---|
form.pre_set_data |
FormEvents::PRE_SET_DATA |
Model data |
form.post_set_data |
FormEvents::POST_SET_DATA |
Model data |
form.pre_bind |
FormEvents::PRE_SUBMIT |
Request data |
form.bind |
FormEvents::SUBMIT |
Normalized data |
form.post_bind |
FormEvents::POST_SUBMIT |
View data |
2.3 新版功能: Before Symfony 2.3, FormEvents::PRE_SUBMIT
, FormEvents::SUBMIT
and FormEvents::POST_SUBMIT
were called FormEvents::PRE_BIND
, FormEvents::BIND
and FormEvents::POST_BIND
.
警告
The FormEvents::PRE_BIND
, FormEvents::BIND
and FormEvents::POST_BIND
constants will be removed in version 3.0 of Symfony. The event names still keep their original values, so make sure you use the FormEvents
constants in your code for forward compatibility.
An event listener may be any type of valid callable.
Creating and binding an event listener to the form is very easy:
// ...
use SymfonyComponentFormFormEvent;
use SymfonyComponentFormFormEvents;
$form = $formFactory->createBuilder()
->add('username', 'text')
->add('show_email', 'checkbox')
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$user = $event->getData();
$form = $event->getForm();
if (!$user) {
return;
}
// Check whether the user has chosen to display his email or not.
// If the data was submitted previously, the additional value that is
// included in the request variables needs to be removed.
if (true === $user['show_email']) {
$form->add('email', 'email');
} else {
unset($user['email']);
$event->setData($user);
}
})
->getForm();
// ...
When you have created a form type class, you can use one of its methods as a callback for better readability:
// ...
class SubscriptionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('username', 'text');
$builder->add('show_email', 'checkbox');
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
array($this, 'onPreSetData')
);
}
public function onPreSetData(FormEvent $event)
{
// ...
}
}
Event subscribers have different uses:
use SymfonyComponentEventDispatcherEventSubscriberInterface;
use SymfonyComponentFormFormEvent;
use SymfonyComponentFormFormEvents;
class AddEmailFieldListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => 'onPreSetData',
FormEvents::PRE_SUBMIT => 'onPreSubmit',
);
}
public function onPreSetData(FormEvent $event)
{
$user = $event->getData();
$form = $event->getForm();
// Check whether the user from the initial data has chosen to
// display his email or not.
if (true === $user->isShowEmail()) {
$form->add('email', 'email');
}
}
public function onPreSubmit(FormEvent $event)
{
$user = $event->getData();
$form = $event->getForm();
if (!$user) {
return;
}
// Check whether the user has chosen to display his email or not.
// If the data was submitted previously, the additional value that
// is included in the request variables needs to be removed.
if (true === $user['show_email']) {
$form->add('email', 'email');
} else {
unset($user['email']);
$event->setData($user);
}
}
}
To register the event subscriber, use the addEventSubscriber() method:
// ...
$form = $formFactory->createBuilder()
->add('username', 'text')
->add('show_email', 'checkbox')
->addEventSubscriber(new AddEmailFieldListener())
->getForm();
// ...