Ask your Symfony questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Post Validators ONE AT A TIME Symfony


How can I execute post validators one at a time?

This can be explained by an example, I have a login form with a captcha.

There is a post validator to check that the username and password match, and another post validator to check that the captcha is correct.

If the username and passwords are correct but the captcha, I only get an error from the captcha, but this renders the captcha useless because it reveals that the user/password are correct.

Is there a way to execute them in order so that the user/password validator is only executed once the captcha has been validated?

Answers (5)


Jimish Gamit answers:

try with 'halt_on_error'. by default it's false.

Symfony tests all the validators and declares the validation failed if at least one of them fails. And even if some of the rules of the validation file fail, symfony will still look for a validateXXX() method and execute it. So the two validation techniques are complementary. The <strong>advantage</strong> is that, in a form with multiple failures, all the error messages are shown.

new sfValidatorAnd(
new sfValidatorSchemaReCaptcha('challenge', 'response', $options = array()),
new sfValidatorCallback(array('callback' => array($this, 'checkPassword')))

I am sure it will work for you. :)

fxsymfony comments:

Worked perfectly! thanks!


Arturo Linares answers:

Don't run the second validator if you already have errors in the first one. Use an if statement inside your postValidator class.

An example showing your post validator doClean() method:

protected function doClean($values)
$errorSchema = new sfValidatorErrorSchema($this);
if ($invalid_login)
$errorSchema->addError(new sfValidatorError($this, 'login'), 'login');

if (count($errorSchema) == 0 && $invalid_captcha)
$errorSchema->addError(new sfValidatorError($this, 'captcha'), 'captcha');

if (count($errorSchema) > 0)
throw new sfValidationErrorSchema($this, $errorSchema);

return $values;

fxsymfony comments:

But in my case both post validators are separate methods, so I wouldn't know how to test them as conditions like in your code. This is what I have in the form->configure():

$this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
new sfValidatorSchemaReCaptcha('challenge', 'response', $options = array()),
new sfValidatorCallback(array('callback' => array($this, 'checkPassword')))))

So I created my own "checkPassword" method, and the one for the captcha is provided in the plugin. I need somehow to execute them one at a time in a sequence.


Damian Martinelli answers:

Please try with:

$this->validatorSchema->setPostValidator(new sfValidatorAnd(new sfValidatorAnd(array(
new sfValidatorSchemaReCaptcha('challenge', 'response', $options = array()),
new sfValidatorCallback(array('callback' => array($this, 'checkPassword'))))))

fxsymfony comments:

Tried it but it doesnt change anything, I mean if my username/password are correct I only get an error for the captcha, if my username/password are not correct I get both error messages. This renders the captcha useless.

What I'm looking for is being able to run the captcha postvalidator first, so that the username/password are only checked when the text entered in the captcha is valid.


Nate Flink answers:

As I understand the problem, it relates to the fact that the capcha image validator call is in a separate form class from your username/password form. I haven't used the symfony capcha plugin before, but to my way of thinking, the solution to this issue would be to consolidate both form classes to a single class that handles all the desired validation and application logic.

This should be fairly easy to achieve by simply overriding the plugin's form class. Make a copy of the plugin's form class and save to yourproject/lib/form/whateverForm.class.php

Then copy the username / password submission form stuff to that one. From there it should be a trivial matter to tweak the validators to get them to behave the way you want.


Ivan Rey answers:

The halt_on_error option is the best way to do it as Jimish Gamit posted.