Zend 2条件验证器

时间:2017-01-26 08:28:14

标签: php validation zend-framework2 apigility

我正在努力执行验证问题,基于名为published的字段实体我必须应用验证规则:

  • 在设置为true
  • 时验证实体
  • 设置为false(草稿功能)
  • 时不执行任何操作

我设法在规范字段中添加了一个回调验证器来检查我的规则并且它有效 细:

Validator definition
    $emptyValidatorOnPublish = array(
        'name' => 'Callback',
        'options' => array(
            'messages' => array(
                \Zend\Validator\Callback::INVALID_VALUE => 'This field cannot be empty',
            ),
            'callback' => function($value, $context=array()) {
                if($context['published']){//Here I know the POST value
                    return !empty($value); //it must not be empty
                }
                return true;
            },
        ),
    );

用法:

 array(
    'name' => 'title',
    'description' => 'Title of the interview',
    'required' => true,
    'filters' => array(
        0 => array(
            'name' => 'Zend\\Filter\\StringTrim',
            'options' => array()
        ),
        1 => array(
            'name' => 'Zend\\Filter\\StripTags',
            'options' => array()
        )
    ),
    'validators' => array($emptyValidatorOnPublish),
    'error_message' => 'title is required',
    'allow_empty' => true,
    'continue_if_empty' => true
)

现在,我已经使用ObjectExists验证器验证了一些字段:

array(
    'name' => 'person',
    'description' => 'Person link',
    'required' => true,
    'filters' => array(),
    'validators' => array(
        0 => array(
            'name' => 'MyApp\\Validators\\ObjectExists',
            'options' => array(
                'fields' => 'ref',
                'message' => 'This person does not exist',
                'object_manager' => 'doctrine.entitymanager.orm_default',
                'object_repository' => 'MyApp\\Person'
            )
        )
    ),
    'allow_empty' => true,
    'continue_if_empty' => true
),

ObjectExists验证程序扩展DoctrineModule\Validator\ObjectExists

class ObjectExists extends BaseObjectExists
{

    /**
     * {@inheritDoc}
     */
    public function isValid($value)
    {
        if (! is_array($value)) {
            return parent::isValid($value);
        }

        $isValid = null;

        foreach ($value as $oneValue) {
            $isValid = false === $isValid ? $isValid : parent::isValid($oneValue);
        }

        return $isValid;
    }
}

问题:

  • 父类验证员不知道published的价值

  • 即使我更改实施以检查published值,我也会从数据库中获取值而不是实际的POST请求

是否有办法根据请求中的published值检查实体是否存在?

有没有办法在验证另一个字段时传递一个兄弟值(在我的情况下,在验证'published时传递person)?

2 个答案:

答案 0 :(得分:3)

您的输入过滤器有一个叫validation group的东西。当published字段的值为false时,您可以删除不希望从该验证程序组验证的输入,然后在输入过滤器为时,这些输入元素不会得到验证运行

您无需在验证程序类本身中解决此问题。将此逻辑移动到更高级别会更好(例如,通过在输入过滤器类的init方法中设置验证组)。我认为验证者类本身不应该处理这个责任。

//pass the input names you want to validate here when published is false
if($published === false){
    $inputFilter->setValidationGroup();
}

在这样的解决方案中,您只需要在输入过滤器类中注入此published字段,而不是在所有单独的验证器中注入。

答案 1 :(得分:0)

我找到了一个解决方案:

  1. 为您在其中注入请求参数的验证器创建工厂:
  2. class ObjectExistsIfPublishedFactory implements FactoryInterface,MutableCreationOptionsInterface 
    {
        /**
         * @var array
         */
        protected $options = array();
    
      public function setCreationOptions(array $options)
      {
          $this->options = $options;
      }
    
      public function createService(ServiceLocatorInterface $serviceLocator)
      {
          $services = $serviceLocator->getServiceLocator();
          $application = $services->get('Application');
          $mvcEvent  = $application->getMvcEvent();
          $dataContainer = $mvcEvent->getParam('ZFContentNegotiationParameterData', false);
          $data = $dataContainer->getBodyParams(); //Get request parameters
          $this->options['isPublished'] = $data['published']?true:false; //Add to the options of the validator
          $objectManager = $serviceLocator->getServiceLocator()->get($this->options['object_manager']);
    
          $this->options['object_repository'] = $objectManager->getRepository($this->options['object_repository']);
          return new ObjectExistsIfPublished($this->options);
      }
    }
    
    1. 在validationg:
    2. 时使用注入的请求变量
      use DoctrineModule\Validator\ObjectExists as BaseObjectExists;
      class ObjectExistsIfPublished extends BaseObjectExists
      {
      
          /**
           * {@inheritDoc}
           */
          public function isValid($value)
          {
              $isValid = true;
              if($this->getOption('isPublished')){
                  if (! is_array($value)) {
                      return parent::isValid($value);
                  }
                  $isValid = null;
                  foreach ($value as $oneValue) {
                      $isValid = false === $isValid ? $isValid : parent::isValid($oneValue);
                  }
              }
              return $isValid;
          }
      }