Symfony 1.4 form, conditional throwing sfValidatorError in embedded form
-
11-10-2019 - |
سؤال
I have Page object:
Page:
actAs:
Timestampable: ~
I18n:
fields: [name,content,attachment,course_name, course_description ]
actAs:
Sluggable: { fields: [name], uniqueBy: [lang, name], canUpdate: true }
columns:
...
is_course: { type: boolean }
course_name: { type: string(255) }
course_description: { type: string(500) }
And PageForm with embedded i18n forms:
//PageForm.class.php
public function configure()
{
...
$this->embedI18n(array('pl','en'));
$this->widgetSchema->setLabel('en', 'Angielski');
$this->widgetSchema->setLabel('pl', 'Polski');
}
Fields course_name and course_description aren't required while is_course is set to false. But if is_course is enabled validation should throw error that course_name and course_description are required.
I have readed "Symfony Advanced Forms" guide and some other posts, but I don't know should I use sfValidatorCallback in PageForm or PostValidator in PageTranslationForm? I tried to use sfValidatorCallback in this way:
//PageForm.class.php
public function configure()
{
...
$this->validatorSchema->setPostValidator(
new sfValidatorCallback(array('callback' => array($this,'checkCourses')))
);
}
public function checkCourses($validator, $values)
{
if($values['is_course'])
{
if($values['pl']['course_name'] && !$values['pl']['course_description'])
{
$error = new sfValidatorError($validator,'Required filed');
throw new sfValidatorErrorSchema($validator, array( _what_name_ => $error));
}
}
return $values;
}
But i don't know how to throw error in $values['pl']['course_description'] because Symfony API says _what_name_ should be an array of errors..
I'm really confused what is what during process of validating forms in symfony.
//Edit
I have done some changes in PageTranslationForm and now it looks like this... //PageTranslationform.class.php
public function configure()
{
//......
$this->validatorSchema->setPostValidator(
new sfValidatorCallback(array('callback' => array($this,'checkCourses')))
);
//.....
}
public function checkCourses($validator, $values)
{
if($values['course_name'] && !$values['course_description'])
{
$error = new sfValidatorError($validator,'Required');
throw new sfValidatorErrorSchema($validator, array( 'course_description' => $error));
}
elseif(!$values['course_name'] && $values['course_description'])
{
$error = new sfValidatorError($validator,'Required');
throw new sfValidatorErrorSchema($validator, array( 'course_name' => $error));
}
return $values;
}
And it almost works but... this validator should be enabled only if in PageForm is_course is set to "true". How can I access field "is_course" from PageForm in checkCourses function in PageTranslationForm?
//SOLUTION
Thanks Jeremy, I used your idea and finally got this solution:
//PageForm.class.php
public function configure()
{
$this->embedI18n(array('pl','en'));
$this->widgetSchema->setLabel('en', 'Angielski');
$this->widgetSchema->setLabel('pl', 'Polski');
//.....
if($this->getObject()->getIsCourse())
{
foreach($this->getEmbeddedForms() as $key => $form)
{
$this->validatorSchema[$key]->setPostValidator(
new sfValidatorCallback(array('callback' => array($form,'checkCourses')))
);
}
}
}
//PageTranslationForm.class.php
//configure etc
public function checkCourses($validator, $values)
{
$errorSchema = new sfValidatorErrorSchema($validator);
if($values['course_name'] && !$values['course_description'])
{
$errorSchema->addError(new sfValidatorError($validator,'required'), 'course_description');
}
elseif(!$values['course_name'] && $values['course_description'])
{
$errorSchema->addError(new sfValidatorError($validator,'required'), 'course_name');
}
elseif(!$values['course_name'] && !$values['course_description'])
{
$errorSchema->addError(new sfValidatorError($validator,'required'), 'course_name');
$errorSchema->addError(new sfValidatorError($validator,'required'), 'course_description');
}
if (count($errorSchema))
{
throw new sfValidatorErrorSchema($validator, $errorSchema);
}
return $values;
}
Thanks for you advice, It works perfectly and I hope it would be helpful :)
المحلول
This should be a post validator because you are using multiple values.
When validating via a post validator, you can throw the error in two different ways:
Globally
When the error is thrown globally, it will show up as part of sfForm::renderGlobalErrors
. To throw globally, simply throw the error in the callback:
public function checkCourses($validator, $values)
{
if ($invalid)
{
throw new sfValidatorError($validator, 'Required.'); //global messages should be more specific than this
}
}
Locally
To have the error be rendered locally, throw a schema with an array, as you are doing. The keys of the array will determine the fields the errors are rendered on. This is probably want you want here.
public function checkCourses($validator, $values)
{
if ($invalid)
{
$error = new sfValidatorError($validator,'Required filed');
throw new sfValidatorErrorSchema($validator, array('course_description' => $error));
}
}