将输入筛选器添加到ZF2中的字段集


Adding input filter to fieldset in ZF2

我有一个表单Register,它有一个字段集Profile,它又有一个域集Account。字段集实现InputFilterProviderInterface,从而实现getInputFilterSpecification方法。这就是我添加的通用验证器和过滤器的地方,它们应该在使用字段集时使用。

现在,在我的注册表格中,我想验证具有给定用户名的帐户是否已经不存在。因此,我需要添加一个验证器来补充Account字段集上定义的验证器。这就是我遇到麻烦的地方。经过深入研究,我找到了一种将输入过滤器添加到字段集的方法。我想,通过这种方式,我可以向Account字段集添加一个额外的输入过滤器。

class Register extends Zend'InputFilter'InputFilter
{
    public function __construct()
    {
        $this->add(new RegisterProfileFilter(), 'profile');
    }
}

使用上面的代码,我可以向Profile字段集添加一个输入过滤器,在该输入过滤器中,我可以对account字段集执行同样的操作。然而,这种方法似乎有两个问题:

  1. 似乎我必须为层次结构中的每个字段集创建一个输入过滤器;在这种情况下,我必须为Profile字段集创建一个输入过滤器,这样我就可以向Account字段集添加输入过滤器——即使我不需要向Profile字段集添加任何验证器或任何东西。如果我尝试直接将筛选器添加到account字段集,则不会起作用
  2. 似乎向字段集添加一个输入过滤器对象会删除我在字段集的getInputFilterSpecification方法中定义的过滤器,而不是像我想要的那样将两者合并

有没有办法将在我的字段集上定义的输入过滤器规范与一个额外的规范(或Zend'InputFilter'InputFilter的实例)合并,这样我就不必将字段集规范复制到我的输入过滤器类中?这将是重复的代码,不太容易维护。或者我错过了什么导致我走错了轨道?

下面是我的代码,如果它在任何方面都有用的话。

// The code has been altered to be more self-explanatory and shorter
class RegisterForm extends 'Zend'Form'Form
{
    public function __construct()
    {
        parent::__construct('register');
        // Elements are added here
        $profileFieldset = new ProfileFieldset();
        $profileFieldset->setUseAsBaseFieldset(true);
        $this->add($profileFieldset);
    }
}

class ProfileFieldset extends 'Zend'Form'Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('profile');
        // Elements are added here
        $this->add(new AccountFieldset());
    }
    public function getInputFilterSpecification()
    {
        return array(
            /***** The below is apparently cleared when adding an input filter to this fieldset *****/
            'some_element1' => array(
                'required' => false,
            ),
            'some_element2' => array(
                'required' => false,
            ),
        );
    }
}

class AccountFieldset extends 'Zend'Form'Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('account');
        // Elements are added here
    }
    public function getInputFilterSpecification()
    {
        return array(
            /***** This is the element that I want to add an additional validator to in a specific context (form) *****/
            'username' => array(
                'required' => true,
                'validators' => array(
                    new Validator'StringLength(array(
                        'min' => 4,
                        'max' => 15,
                    )),
                    new I18nValidator'Alnum(false),
                ),
            ),
            // Other elements here
        );
    }
}

Zend'Form组件中没有很好地涵盖合并输入过滤器。必须有人真正重构整个东西。

无论如何,在您的情况下,我建议您在整个InputFilter创建完成后,通过重写Form中的getInputFilter方法来添加验证器

class RegisterForm extends 'Zend'Form'Form
{
    public function __construct()
    {
        // add stuff
    }
    public function getInputFilter()
    {
        $formInputFilter = parent::getInputFilter();
        $usernameInput = $formInputFilter->get('profile')->get('account')->get('username');
        $myValidator = new Validator'SomeValidator();
        $usernameInput->getValidatorChain()->addValidator($myValidator);
        return $formInputFilter;
    }
}    

作为旁注,我建议根据Form而不是根据Fieldset定义InputFilters,因为Fieldset中的元素在不同的上下文中通常具有不同的"验证要求"(=Form)。但也许这更多的是个人偏好。