Php 在Zend Framework 2中合并输入过滤器
我有很多字段集,我想为每个字段集创建一个输入过滤器类。这样的想法是,对于我的每个表单,我可以创建一个由其他输入过滤器组成的输入过滤器类。例如,当通过注册表创建帐户时,我希望使用我为我的Php 在Zend Framework 2中合并输入过滤器,php,zend-framework2,Php,Zend Framework2,我有很多字段集,我想为每个字段集创建一个输入过滤器类。这样的想法是,对于我的每个表单,我可以创建一个由其他输入过滤器组成的输入过滤器类。例如,当通过注册表创建帐户时,我希望使用我为我的帐户实体提供的基本帐户输入筛选器,并在新的输入筛选器类中使用它,该类可以修改输入或添加其他输入。类似下面的例子 class Register extends InputFilter { public function __construct(ObjectRepository $accountReposito
帐户
实体提供的基本帐户
输入筛选器,并在新的输入筛选器类中使用它,该类可以修改输入或添加其他输入。类似下面的例子
class Register extends InputFilter
{
public function __construct(ObjectRepository $accountRepository, Account $accountFilter)
{
/***** Add inputs from input filters *****/
$this->inputs = $accountFilter->getInputs();
/***** Add additional validation rules *****/
// Username
$usernameAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('username'),
));
$username = $this->get('username');
$username->getValidatorChain()
->attach($usernameAvailability, true);
// E-mail
$emailAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('email'),
));
$email = $this->get('email');
$email->getValidatorChain()
->attach($emailAvailability, true);
}
}
我将输入筛选器传递给构造函数,我想将此筛选器的输入添加到我的寄存器筛选器并修改输入
我遇到的问题是,只有我的一些输入似乎符合预期,而我似乎无法找出原因。当我提交表格时,只有部分输入按预期进行验证:
有趣的是,在填写数据库中已经存在的电子邮件时,电子邮件输入的行为与预期不符。结果应该是已经存在的验证错误,但不会发生这种情况。如果我调试并查看我的表单,我会发现以下内容:
表单的过滤器有正确的输入和正确的验证器,如上图所示,username
输入似乎正确验证。但由于某些原因,这并没有在我的表格中直观地反映出来
下面是我的代码
字段集
class Profile extends Fieldset
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('profile');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new ProfileEntity());
// Elements go here
$this->add(new AccountFieldset($objectManager));
}
}
class Account extends Fieldset
{
public function __construct()
{
parent::__construct('account');
$username = new Element\Text('username');
$username->setLabel('Username');
$password = new Element\Password('password');
$password->setLabel('Password');
$repeatPassword = new Element\Password('repeatPassword');
$repeatPassword->setLabel('Repeat password');
$email = new Element\Email('email');
$email->setLabel('E-mail address');
$birthdate = new Element\DateSelect('birthdate');
$birthdate->setLabel('Birth date');
$gender = new Element\Select('gender');
$gender->setLabel('Gender')
->setEmptyOption('Please choose')
->setValueOptions(array(
1 => 'Male',
2 => 'Female',
));
$this->add($username);
$this->add($password);
$this->add($repeatPassword);
$this->add($email);
$this->add($birthdate);
$this->add($gender);
$this->add(new CityFieldset());
}
}
表格
class Register extends Form
{
public function __construct()
{
parent::__construct('register');
// Terms and Conditions
$terms = new Element\Checkbox('terms');
$terms->setLabel('I accept the Terms and Conditions');
$terms->setCheckedValue('yes');
$terms->setUncheckedValue('');
$terms->setAttribute('id', $terms->getName());
// Submit button
$submit = new Element\Submit('btnRegister');
$submit->setValue('Register');
$profileFieldset = new ProfileFieldset($objectManager);
$profileFieldset->setUseAsBaseFieldset(true);
// Add elements to form
$this->add($terms);
$this->add($profileFieldset);
$this->add($submit);
}
}
查看
$form->prepare();
echo $this->form()->openTag($form);
$profile = $form->get('profile');
$account = $profile->get('account');
echo $this->formRow($account->get('username'));
echo $this->formRow($account->get('password'));
echo $this->formRow($account->get('repeatPassword'));
echo $this->formRow($account->get('email'));
echo $this->formRow($account->get('birthdate'));
echo $this->formRow($account->get('gender'));
$city = $account->get('city');
echo $this->formRow($city->get('postalCode'));
echo $this->formRow($form->get('terms'));
echo $this->formSubmit($form->get('btnRegister'));
echo $this->form()->closeTag();
控制器
$form = new Form\Register();
$profile = new Profile();
if ($this->request->isPost()) {
$form->bind($profile);
$form->setData($this->request->getPost());
$form->setInputFilter($this->serviceLocator->get('Profile\Form\Filter\Register'));
if ($form->isValid()) {
// Do stuff
}
}
return new ViewModel(array('form' => $form));
// This input filter aggregates the "fieldset input filters" and adds additional validation rules
class Register extends InputFilter
{
public function __construct(ObjectRepository $accountRepository, InputFilter $profileFilter)
{
/***** ADD ADDITIONAL VALIDATION RULES *****/
// Username
$usernameAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('username'),
));
$emailInput = $profileFilter->get('account')->get('username');
$emailInput->getValidatorChain()->attach($usernameAvailability, true);
// E-mail
$emailAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('email'),
));
$emailInput = $profileFilter->get('account')->get('email');
$emailInput->getValidatorChain()->attach($emailAvailability, true);
/***** ADD FIELDSET INPUT FILTERS *****/
$this->add($profileFilter, 'profile');
}
}
class Profile extends InputFilter
{
public function __construct(InputFilter $accountFilter)
{
$this->add($accountFilter, 'account');
// Add generic validation rules (inputs) for the profile fieldset here
}
}
我是不是误解了什么?在仍然有多个输入过滤器类的情况下,有没有更好的方法来实现这一点?我真的更喜欢这样保持代码的可维护性,而不是复制不同表单的验证规则。很抱歉发了这么长的帖子,很难解释这个问题 好吧,看来我已经明白了。显然,我的第一个方法是完全错误的。我找到了一种方法,为我的每个字段集创建一个输入过滤器类,然后对我的表单重用这些输入过滤器,同时为某些表单元素(从我的字段集)添加额外的验证规则。这样,我可以在每个字段集的标准输入过滤器类中定义我的通用验证规则,并针对不同的上下文(即表单)修改它们。下面是代码。课程与问题有点不同,因为这稍微简化了一点
主输入过滤器
$form = new Form\Register();
$profile = new Profile();
if ($this->request->isPost()) {
$form->bind($profile);
$form->setData($this->request->getPost());
$form->setInputFilter($this->serviceLocator->get('Profile\Form\Filter\Register'));
if ($form->isValid()) {
// Do stuff
}
}
return new ViewModel(array('form' => $form));
// This input filter aggregates the "fieldset input filters" and adds additional validation rules
class Register extends InputFilter
{
public function __construct(ObjectRepository $accountRepository, InputFilter $profileFilter)
{
/***** ADD ADDITIONAL VALIDATION RULES *****/
// Username
$usernameAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('username'),
));
$emailInput = $profileFilter->get('account')->get('username');
$emailInput->getValidatorChain()->attach($usernameAvailability, true);
// E-mail
$emailAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('email'),
));
$emailInput = $profileFilter->get('account')->get('email');
$emailInput->getValidatorChain()->attach($emailAvailability, true);
/***** ADD FIELDSET INPUT FILTERS *****/
$this->add($profileFilter, 'profile');
}
}
class Profile extends InputFilter
{
public function __construct(InputFilter $accountFilter)
{
$this->add($accountFilter, 'account');
// Add generic validation rules (inputs) for the profile fieldset here
}
}
配置文件输入过滤器
$form = new Form\Register();
$profile = new Profile();
if ($this->request->isPost()) {
$form->bind($profile);
$form->setData($this->request->getPost());
$form->setInputFilter($this->serviceLocator->get('Profile\Form\Filter\Register'));
if ($form->isValid()) {
// Do stuff
}
}
return new ViewModel(array('form' => $form));
// This input filter aggregates the "fieldset input filters" and adds additional validation rules
class Register extends InputFilter
{
public function __construct(ObjectRepository $accountRepository, InputFilter $profileFilter)
{
/***** ADD ADDITIONAL VALIDATION RULES *****/
// Username
$usernameAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('username'),
));
$emailInput = $profileFilter->get('account')->get('username');
$emailInput->getValidatorChain()->attach($usernameAvailability, true);
// E-mail
$emailAvailability = new NoObjectExists(array(
'object_repository' => $accountRepository,
'fields' => array('email'),
));
$emailInput = $profileFilter->get('account')->get('email');
$emailInput->getValidatorChain()->attach($emailAvailability, true);
/***** ADD FIELDSET INPUT FILTERS *****/
$this->add($profileFilter, 'profile');
}
}
class Profile extends InputFilter
{
public function __construct(InputFilter $accountFilter)
{
$this->add($accountFilter, 'account');
// Add generic validation rules (inputs) for the profile fieldset here
}
}
上面代码中提到的Account
输入过滤器是一个完全正常的输入过滤器类,它扩展了Zend\InputFilter\InputFilter
,并添加了输入。没什么特别的
我的字段集保持不变,与问题中的字段集相同,窗体类和控制器也是如此。使用setInputFilter
方法将寄存器
输入过滤器添加到表单中,就是这样
通过这种方法,每个输入过滤器实例都被添加到一个字段集——这是我的第一种方法没有做到的。我希望这能帮助有类似问题的人 我有一个用户
实体,其中指定了一些验证器
但我想扩展验证程序列表,以便根据服务调用添加一个验证程序,以检查用户电子邮件是否尚未使用
问题是我需要在验证器中注入一个实体管理器来调用服务。我不能(或者更确切地说,我不知道如何也不想:-)将实体管理器注入实体
我还希望保留实体上的现有验证,因为它更靠近存储库,并且可能在我的控制器之外使用。因此,我无法将所有验证器移出此实体,移到新的自定义筛选器中
因此,我的新自定义过滤器将按原样重用实体的现有验证器
新的自定义过滤器称为UserFormFilter
,它在其控制器中接收现有的实体过滤器,在其上循环,并将每个传入的验证器添加到自身:
class UserFormFilter extends InputFilter
{
public function __construct(EntityManager $em, $identity, InputFilter $userDefaultInputFilter)
{
// Add the validators specified in the user entity
foreach ($userDefaultInputFilter->inputs as $inputFilter) {
$this->add($inputFilter);
}
$this->add(array(
'name' => 'email',
'required' => true,
'filters' => array(),
'validators' => array(
array('name' => 'EmailAddress'),
array(
'name' => 'Application\Validator\User',
'options' => array('manager' => $em, 'identity' => $identity)
)
),
));
}
}
现在,我可以在UserController中实例化自定义UserFormFilter:
$formFilter = new \Application\Form\UserFormFilter($em, $user->getInputFilter());
$form->setInputFilter($formFilter);
您可以在上面的代码中看到,自定义UserFormFilter
采用myUser
entitygetInputFilter
方法中指定的默认过滤器。作为旁注,它还传递实体管理器,使定制过滤器能够执行服务调用