Php NoRecordExists输入过滤器
我有一个字段集,用于“添加”和“编辑”表单 字段集实现Php NoRecordExists输入过滤器,php,zend-framework2,Php,Zend Framework2,我有一个字段集,用于“添加”和“编辑”表单 字段集实现InputFilterProviderInterface以提供其验证 在验证添加操作时,我需要检查数据库中不存在具有相同值的数据库记录,因此我使用NoRecordExists验证器 到目前为止一切都很好。但是,当我在编辑表单中使用相同的字段集时,验证将失败,因为显然已经有一条记录具有特定的值,它就是正在编辑的记录 因此,我转到NoRecordExists验证器的exclude选项,并用我正在编辑的记录的“id”(这是我的主键字段)排除该记录
InputFilterProviderInterface
以提供其验证
在验证添加操作时,我需要检查数据库中不存在具有相同值的数据库记录,因此我使用NoRecordExists
验证器
到目前为止一切都很好。但是,当我在编辑表单中使用相同的字段集时,验证将失败,因为显然已经有一条记录具有特定的值,它就是正在编辑的记录
因此,我转到NoRecordExists
验证器的exclude
选项,并用我正在编辑的记录的“id”(这是我的主键字段)排除该记录
所以我就快到了,我唯一不能解决的问题是如何在getInputFilterSpecification
中创建inputfilter时获取要排除的“id”值
这是我的字段集代码。如果有人能告诉我如何从getInputFilterSpecification
中访问表单(或绑定对象)的其他属性,我将不胜感激
也许我需要以不同的方式实现我的imputfilter来实现这一点?或者甚至实现一个自定义验证器?但对于一个看起来相当常规的用例来说,定制验证器无疑是过火了
非常感谢。
:wq
在InputFilter之外检查该条件会更简单 如果这样做,则可以对更新和插入使用相同的表单 您可以a)使用一个单独的操作来更新和插入(CRUD),或者b)如果您想让它们在条件下更新/插入,请执行以下操作
// form validates for update or insert now...
if($form->isValid()) {
if($mapper->exists($object)) {
$mapper->update($object);
}
else {
$mapper->save($object);
}
}
在这种情况下使用此验证器是错误的 发生的情况:验证器向数据库发送一个SELECT查询。如果它发现了什么,它将报告“无效” 如果它没有找到某个内容,它将报告“valid”,但如果第二个请求同时执行相同操作并返回“valid”,该怎么办。谁赢了?一个查询的失败是如何处理的,因为您显然想将输入写入数据库 这就是所谓的问题。只有尝试插入新记录并等待数据库抱怨非唯一索引冲突,才能将唯一记录写入数据库。这是写入操作的预期结果,可以处理
验证器不是无用的:您仍然可以使用它来检查数据库中是否有某种东西,例如,当用户正在填写用户名等时,在Ajax查询中。检查并从数据库中获取布尔值仅用于读取完全可以。但作为输入验证器,这是错误的。这是我的工作解决方案:
$inputFilter->add($factory->createInput(array(
'name' => 'role_name',
'required' => true,
'filters' => array(
array('name' => 'StripTags')
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 2,
'max' => 15
),
),
array(
'name' => 'Zend\Validator\Db\NoRecordExists',
'options' => array(
'table' => 'user_role',
'field' => 'code',
'adapter' => \Zend\Db\TableGateway\Feature\GlobalAdapterFeature::getStaticAdapter(),
'messages' => array(
\Zend\Validator\Db\NoRecordExists::ERROR_RECORD_FOUND => 'The specified name already exists in database'
),
),
),
),
)));
我已经找到了解决这个问题的办法。 基本上,默认的NoRecordExists验证器期望在配置参数中排除值和列。这可以在Ritesh提到的控制器中更改;我玩了一会儿,得到了这个解决方案 我使用的是isValid函数中提供的上下文数组变量。您不发送id值,而是发送表单字段的值以从中提取 在InputFilter中,您有以下内容
$this->add ( array (
'name' => 'user_email',
'required' => true,
'filters' => array (
array (
'name' => 'StringTrim',
),
array (
'name' => 'StripTags',
),
),
'validators' => array (
array (
'name' => 'EmailAddress',
'options' => array (
'domain' => true,
)
),
array (
'name' => 'Application\Validator\NoRecordExists',
'options' => array (
'table' => 'user',
'field' => 'user_email',
'adapter' => \Zend\Db\TableGateway\Feature\GlobalAdapterFeature::getStaticAdapter( ),
'exclude' => array(
'field' => 'user_id',
'formvalue' => 'user_id',
),
)
),
)
) );
表单中定义了一个隐藏元素user_id;在那里设置的值用于内部检查
<?php
namespace Application\Validator;
class NoRecordExists extends \Zend\Validator\Db\NoRecordExists {
public function isValid( $value, $context=array( ) ) {
$exclude = $this->getExclude( );
if( is_array( $exclude ) ){
if ( array_key_exists( 'formvalue', $exclude ) ) {
$formvalue = $exclude[ 'formvalue' ];
$exclude[ 'value' ] = $context[ $formvalue ];
$this->setExclude( $exclude );
}
}
return parent::isValid( $value );
}
}
在这里,我找到了添加操作和编辑操作的解决方案
控制器:
在addAction:
$postData = $this->request->getPost ();
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$form->setInputFilter(new FormFilter($dbAdapter));
$form->setData ($postData);
if (!$form->isValid ()) {
$viewModel->error = true;
return $viewModel;
}
$post = $request->getPost();
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$form->setInputFilter(new FormFilter($dbAdapter,$Id));
$form->setData ($post);
$Id = $post['id'];
if (!$form->isValid ()) {
$viewModel->error = true;
$viewModel->Id = $Id;
$viewModel->form = $form;
return $viewModel;
}
在编辑操作中:
$postData = $this->request->getPost ();
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$form->setInputFilter(new FormFilter($dbAdapter));
$form->setData ($postData);
if (!$form->isValid ()) {
$viewModel->error = true;
return $viewModel;
}
$post = $request->getPost();
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$form->setInputFilter(new FormFilter($dbAdapter,$Id));
$form->setData ($post);
$Id = $post['id'];
if (!$form->isValid ()) {
$viewModel->error = true;
$viewModel->Id = $Id;
$viewModel->form = $form;
return $viewModel;
}
在表单过滤器文件中:
class FormFilter extends InputFilter {
public function __construct ($dbAdapter, $id = '')
{
$this->dbAdapter = $dbAdapter;
$this->add(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8'
),
),
array(
'name' => 'Zend\Validator\Db\NoRecordExists',
'options' => array(
'table' => 'test',
'field' => 'name',
'adapter' => $this->dbAdapter,
'exclude' => array(
'field' => 'id',
'value' => $id,
),
'messages' => array(
\Zend\Validator\Db\NoRecordExists::ERROR_RECORD_FOUND => 'The specified name already exists in database'
),
),
),
),
));
}
}
表单发送后,您可以从控制器访问验证程序,然后根据需要修改验证程序;)谢谢Sam,我会在下面看看这个和Andrew的建议。Andrew,谢谢你的评论。我实际上是在使用条令来管理我的实体,所以CRUD插入/更新对我来说很重要,只需保持现有的或新的实体即可。我将在表单验证之外验证副本。此外,我将更新我的原始帖子,以包含我的“编辑”控制器操作。