Validation ZF2和x2B;复合密钥上的重复表单验证
我有一个在两个字段(gid,bid)上有主键的表单。我需要添加验证来阻止数据库中的重复条目 我已就此与ZF2解决方案进行了核对。虽然这种处理复合键的方法看起来不是理想的方法,但我仍然在尝试,因为它看起来只是一种内置方式。现在需要我提供第二个字段的值(排除中的值选项),这也是一个问题。因为我正在尝试Validation ZF2和x2B;复合密钥上的重复表单验证,validation,zend-framework2,db2,duplicates,zend-form2,Validation,Zend Framework2,Db2,Duplicates,Zend Form2,我有一个在两个字段(gid,bid)上有主键的表单。我需要添加验证来阻止数据库中的重复条目 我已就此与ZF2解决方案进行了核对。虽然这种处理复合键的方法看起来不是理想的方法,但我仍然在尝试,因为它看起来只是一种内置方式。现在需要我提供第二个字段的值(排除中的值选项),这也是一个问题。因为我正在尝试 $inputFilter->add(array( 'name' => 'gid', 'required' => true, 'validator
$inputFilter->add(array(
'name' => 'gid',
'required' => true,
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
'isEmpty' => 'required'
),
),
),
array (
'name' => 'Zend\Validator\Db\NoRecordExists',
'options' => array (
'table' => 'gtable',
'field' => 'gid',
'adapter' => $this->dbAdapter,
'messages' => array(
\Zend\Validator\Db\NoRecordExists::ERROR_RECORD_FOUND => 'The specified key already exists in database'
),
'exclude' => array(
'field' => 'bid',
'value' => [?],
),
)
),
)
));
我如何得到这个值,因为表单是绝对独立的类/文件,而不是控制器,在控制器中我有提交的表单值。这个问题是否存在更好的体系结构解决方案,或者将提交的字段值传递给表单类是唯一的解决方案
注意:我不赞成为此任务构建验证插件,因为短时间是功能的限制。您可以向getInputFilter添加参数,如下所示:
getInputFilter($gid, $bid)
然后在控制器上,当设置过滤器时,传递2个参数,然后只需检查$form->isValid()
另一种选择:试试这个:
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'table' => 'gtable',
'field' => 'gid',
'adapter' => $this->dbAdapter,
),
),
你可以用你的方式做所有的工作。为了实现这一点,您可以在模块module.php中将表单定义为工厂 Module.php
use MyNamespace\MyForm;
//NOTE THAT THE SERVICE MANAGER IS INJECTED. YOUR FORM COULD RECEIVE IT THROUGH THE CONSTRUCTOR
public function getServiceConfig()
{
return array(
'factories' => array(
'my_form' => function( $sm ) {
$form = new MyForm( $sm );
return $form;
},
),
);
}
use Zend\Form\Form;
class MyForm extends Form
{
public $serviceManager, $request, $postData;
public function __construct( $serviceManager ) {
parent::__construct( null );
$this->serviceManager = $serviceManager;
$this->request = $serviceManager->get( 'Application')->getMvcEvent()->getRequest();
$this->postData = get_object_vars( $this->request->getPost() );
}
}
当您想要使用表单时,只需在控制器中使用以下代码即可:
class MyController extends AbstractActionController
{
public function createAction() {
$form = $this->getServiceLocator()->get( 'my_form' ) );
(...)
}
}
以及您的MyForm.php
use MyNamespace\MyForm;
//NOTE THAT THE SERVICE MANAGER IS INJECTED. YOUR FORM COULD RECEIVE IT THROUGH THE CONSTRUCTOR
public function getServiceConfig()
{
return array(
'factories' => array(
'my_form' => function( $sm ) {
$form = new MyForm( $sm );
return $form;
},
),
);
}
use Zend\Form\Form;
class MyForm extends Form
{
public $serviceManager, $request, $postData;
public function __construct( $serviceManager ) {
parent::__construct( null );
$this->serviceManager = $serviceManager;
$this->request = $serviceManager->get( 'Application')->getMvcEvent()->getRequest();
$this->postData = get_object_vars( $this->request->getPost() );
}
}
通过这种方式,您可以在表单中使用服务管理器。还有公共的
postData
,您可以在这里找到构建NoRecordExists
过滤器所需的bid
值。我不确定您的用例。如果要添加数据库条目,则该表的主键在插入之前是未知的-如果有外键约束,则可以处理数据库中的异常
我不赞成为此任务构建验证插件
验证器也不是为了验证多个字段而设计的,因为它们以1-1的方式附加到表单元素。因此,您需要创建自己的
下面的示例未经测试,因此将其作为该方法的示例,而不是工作代码
关键位是isValid
方法
namespace MyModule\Validator\Db;
use Zend\Validator\Db\NoRecordExists;
class CompositeNoRecordExists extends NoRecordExists
{
protected $field2;
protected $field2Value;
public function __construct($options = null)
{
parent::__construct($options);
if (array_key_exists('field2', $options)) {
$this->setField2($options['field2']);
} else {
throw new \BadMethodCallException('Missing field2 option!');
}
}
protected function setField2Value(array $context)
{
if (! isset($context[$this->field2])) {
throw new \BadMethodCallException('Unable to find value for field 2');
}
$this->field2Value = $context[$this->field2];
}
public function isValid($value)
{
// The isValid() method is actually given a 2nd argument called $context
// Which is injected by the inputFilter, via the input and into the validator chain
// $context contains all of RAW form element values, keyed by thier element name.
// Unfortunately due to the ValidatorInterface you are unable to add this to the method
// signature. So you will need to be 'creative':
$args = func_get_args();
if (isset($args[1]) && is_array($args[1])) {
$this->setField2Value($args[1]);
} else {
throw new \BadMethodCallException('Missing validator context');
}
return parent::isValid($value);
}
public function getSelect()
{
$select = parent::getSelect();
$select->where->equalTo($this->field2, $this->field2Value);
return $select;
}
}
然后,您需要做的就是更新验证器配置,添加field2
字段名
array (
'name' => 'MyModule\Validator\Db\CompositeNoRecordExists',
'options' => array (
'table' => 'gtable',
'field' => 'gid',
'field2' => 'bid',
'adapter' => $this->dbAdapter,
'messages' => array(
\Zend\Validator\Db\NoRecordExists::ERROR_RECORD_FOUND => 'The specified key already exists in database'
),
)
),
我不知道是什么问题,但没有执行任何验证,数据库每次都会抛出重复错误。我检查了bjyprofile,发现执行了正确的查询,但没有出现验证错误。能否在控制器上发布设置过滤器的代码?
$postData=$request->getPost()$表单->设置输入过滤器($表单->获取输入过滤器($postData['bid'])代码>确定,因此尝试在方法上使用不同的名称,称之为getInputFilterCustom($bid,…);因为现在您正在覆盖表单上当前的getInputFilter,这总是会带来不需要的行为。但是所有其他验证都可以正常工作。我只是在教程中做了一个改动,我将inputfilter放在表单本身而不是模型中。实际上,@ins0的bid
值来自哪里?@ins0,这是我的问题。解决方案工作正常,验证工作正常。只有一个问题只有一个字段显示错误,但我认为这不容易修复。exclude
选项是一个混合变量。这意味着它可以是一个包含字段
和值
键的数组,也可以是一个类似gid=[?]和bid=[?]的字符串。
。您可以这样尝试,并将此exclude
设置添加到两个输入的验证器中。