I'm having a problem with Symfony form validation (using Silex). I have a repeated
input for a password reset form, which works fine if both passwords match. If they don't, however, $form->isValid()
still returns true. $form->getErrorsAsString()
is empty too.
After lots of googling and reading many answers to questions here that were more or less related, I still haven't found a solution.
Update: After checking out various versions from my Git repository, I eventually found out the feature broke when I updated Symfony from version 2.5.7
to version 2.6.0
released yesterday. I looked at the changelog and didn't see anything that would break this. I temporarily switched back, but would eventually like to be able to use version 2.6.0
...
Here's the buildForm
method defined for my PasswordResetType
:
function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('password', 'repeated', array(
'type' => 'password',
'invalid_message' => $this->app['translator']->trans('form_errors.pass_must_match'),
'required' => true,
'first_options' => array(
'constraints' => array(
new Assert\NotBlank()
),
),
'second_options' => array(
'constraints' => array(
new Assert\NotBlank()
)
)
))
;
}
}
The Twig template associated to my form:
{{ form_start(form) }}
{{ form_widget(form._token) }}
{{ form_errors(form) }}
<div class="form-group">
{{ form_label(form.password.first, 'user.new_password'|trans, {'label_attr': {'class': 'control-label'}}) }}
{{ form_errors(form.password.first) }}
{{ form_widget(form.password.first, {'attr': {'class': 'form-control', 'placeholder' : 'user.new_password'|trans}}) }}
</div>
<div class="form-group">
{{ form_label(form.password.second, 'user.new_password_confirmation'|trans, {'label_attr': {'class': 'control-label'}}) }}
{{ form_errors(form.password.second) }}
{{ form_widget(form.password.second, {'attr': {'class': 'form-control', 'placeholder' : 'user.new_password_confirmation'|trans}}) }}
</div>
<button type="submit" class="btn btn-primary btn-block">{{'user.reset_password'|trans}}</button>
{{ form_end(form) }}
The associated controllers:
$app->get('/{_locale}/reset_password/{token}', function(Request $request, $token) use ($app) {
/* ... */
$form = $app['form.factory']->createBuilder(new PasswordResetType($app), array())->getForm();
return $app['twig']->render('password_reset.twig', array(
'title' => 'Page title',
'form' => $form->createView()
));
})->bind('reset_password');
$app->post('/{_locale}/reset_password/{token}', function(Request $request, $token) use ($app) {
/* ... */
$form = $app['form.factory']->createBuilder(new PasswordResetType($app), array())->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$password = $data['password']; // this is line 113
/* ... */
}
});
This generates the following error when passwords don't match: Error: ContextErrorException in controllers_users.php line 113: Notice: Undefined index: password
. This indicates $form->isValid()
returned true
while it shouldn't have, since the passwords don't match.
Update: I opened a bug report: https://github.com/symfony/symfony/issues/12792