有一个复杂的表单,有很多嵌套的字段集。一些字段需要根据另一个字段集中的字段(-s)进行验证。因此,我不能直接在Fieldset
的getInputFilterSpecification()
中定义所有验证规则,因为在那里我不能访问其他字段集(只能访问子字段集)。做到这一点的唯一方法是扩展Form
验证。对吧?如果有,如何做到这一点?
MyForm extends Form
{
public function isValid()
{
$isFormValid = parent::isValid();
$isFieldXyzValid = // my additional validation logic
if(! $isFieldXyzValid) {
$fieldXyz->setMessages(...);
}
return $isFormValid && $isFieldXyzValid;
}
}
呢?还是一个更干净的方法来解决这个问题?
我已经在之前的项目中开发了类似的东西。
为此,我使用了一个服务来获取我的表单并设置动态字段集,当然还有自定义验证规则。
在你的控制器中,获取你的表单(通过依赖注入formManager(是否填充))。
$form = $this->formManager->get('{your form}');
调用你的服务并给它你的表单。
在你的服务中,你可以做任何你想做的事情,比如:
- 得到你的东西(从数据库或其他),以确定哪些字段是强制性的
- Foreach on your form
- 添加或删除字段集
- 添加或删除validationGroup字段
- 添加或删除过滤器
- 添加或删除验证器
我在一个foreach中通过(sample)执行了这些操作,其中$stuff
是doctrine集合的一个元素
$nameFieldset = 'my_fieldset-'.$stuff->getId();
$globalValidator = new GlobalValidator();
$globalValidator->setGlobalValue($gloablValue);
$uoValidator = new UcValidator();
$uoValidator->setOptions(array(
'idToValidate' => $stuff->getId(),
'translator' => $this->translator
));
$globalValidator->setOptions(array(
'idToValidate' => $stuff->getId(),
'translator' => $this->translator
));
$name = 'qty-'.$stuff->getId();
$form = $this->setFilters($form, $name, $nameFieldset);
$globalValidator->setData($data);
$form = $this->setValidators($form, $name, $globalValidator, $uoValidator, $nameFieldset);
其中setFilters和setValidators是自定义方法,它们将过滤器和验证器添加到我的字段(也是自定义的)
/**
* @param myForm $form
* @param $name
* @param string $nameFieldset
* @return myForm
*/
public function setFilters($form, $name, $nameFieldset)
{
$form->getInputFilter()->get('items')->get($nameFieldset)
->get($name)
->getFilterChain()
->getFilters()
->insert(new StripTags())
->insert(new StringTrim());
return $form;
}
/**
* @param myForm $form
* @param $name
* @param $globalValidator
* @param $uoValidator
* @param $nameFieldset
* @return myForm
*/
public function setValidators($form, $name, $globalValidator, $uoValidator, $nameFieldset)
{
$optionsSpace = [
'translator' => $this->translator,
'type' => NotEmpty::SPACE
];
$optionsString = [
'translator' => $this->translator,
'type' => NotEmpty::STRING
];
$optionsDigits = [
'translator' => $this->translator,
];
$form->getInputFilter()->get('items')
->get($nameFieldset)
->get($name)
->setRequired(true)
->getValidatorChain()
->attach($uoValidator, true, 1)
->attach($globalValidator, true, 1)
// We authorize zéro but not space nor strings
->attach(new NotEmpty($optionsSpace), true, 2)
->attach(new NotEmpty($optionsString), true, 2)
->attach(new Digits($optionsDigits), true, 2);
return $form;
}