Zend框架2个自定义验证表单(Zend Framework 2 Custom Validators

2019-07-04 00:36发布

我试图让该检查的密码字段的复杂性,用户登记表。 我写了一个自定义验证根据做这个文件 。 此文件居住在用户的\ src \用户\验证我的“用户”模块。

<?php

namespace User\Validator;

use Zend\Validator\AbstractValidator;

class PasswordStrength extends AbstractValidator {

const LENGTH = 'length';
const UPPER  = 'upper';
const LOWER  = 'lower';
const DIGIT  = 'digit';

protected $messageTemplates = array(
    self::LENGTH => "'%value%' must be at least 6 characters long",
    self::UPPER => "'%value% must contain at least one uppercase letter",
    self::LOWER => "'%value% must contain at least one lowercase letter",
    self::DIGIT => "'%value% must contain at least one digit letter"
);

public function isValid($value) {
    ... validation code ...
}
}

我的问题出现在试图在我的用户登记表使用此验证。 我试图在Module.php配置它添加验证到的ServiceManager。

public function getServiceConfig() {
    return array(
        'invokables' => array(
            'PasswordStrengthValidator' => 'User\Validator\PasswordStrength'
        ),
    );
}

然后我把它添加到user.php的输入滤波器。

public function getInputFilter() {
    if (!$this->inputFilter) {
        $inputFilter = new InputFilter();
        $factory     = new InputFactory();

        $inputFilter->add($factory->createInput(array(
            'name'     => 'username',
            'required' => true,
            'validators' => array(
                array(
                    'name'    => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min'      => 1,
                        'max'      => 100,
                    ),
                ),
            ),
        )));

        $inputFilter->add($factory->createInput(array(
            'name'     => 'password',
            'required' => true,
            'validators' => array(
                array(
                    'name'    => 'PasswordStrengthValidator',
                ),
            ),
        )));

        $this->inputFilter = $inputFilter;
    }

    return $this->inputFilter;
}

然而,当我访问的形式和点击提交按钮,我得到一个ServiceNotFoundException的。

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for PasswordStrengthValidator

有没有与我的ServiceManager配置有问题? 我甚至不知道这是摆在首位,以使用自定义验证程序的适当方式。 我发现很多使用ZF1的例子,但我发现从来没有超越验证程序的书面延伸,以解决其与整合形式等任何意见,将不胜感激的文档和ZF2例子。

Answer 1:

您正试图在你的例子使用“短名称”验证加载只有当你注册一个简短的名称/别名与验证插件管理器(作品Zend\Validator\ValidatorPluginManager )第一。

一种可以替代的(和我的方式做到这一点)是创建表单过滤器对象时,注入必要的自定义验证器的实例。 这是ZfcUser做它的方式:

// Service factory definition from Module::getServiceConfig
'zfcuser_register_form' => function ($sm) {
     $options = $sm->get('zfcuser_module_options');
     $form = new Form\Register(null, $options);
     $form->setInputFilter(new Form\RegisterFilter(
         new Validator\NoRecordExists(array(
             'mapper' => $sm->get('zfcuser_user_mapper'),
             'key'    => 'email'
         )),
         new Validator\NoRecordExists(array(
            'mapper' => $sm->get('zfcuser_user_mapper'),
            'key'    => 'username'
         )),
         $options
     ));
     return $form;
},

来源: https://github.com/ZF-Commons/ZfcUser/blob/master/Module.php#L100

这里,两个ZfcUser\Validator\NoRecordExists验证器实例(一个用于电子邮件,一个用于用户名)被注入到输入滤波器对象的登记表(的构造ZfcUser\Form\RegisterFilter )。

然后,里面ZfcUser\Form\RegisterFilter类,校验器被添加到元素定义:

$this->add(array(
    'name'       => 'email',
    'required'   => true,
    'validators' => array(
        array(
            'name' => 'EmailAddress'
        ),
        // Constructor argument containing instance of the validator
        $emailValidator
    ),
));

来源: https://github.com/ZF-Commons/ZfcUser/blob/master/src/ZfcUser/Form/RegisterFilter.php#L37

我相信,另一种选择是使用完全合格的类名作为验证名称(即:“用户\验证\密码强度”,而不仅仅是“PasswordStrengthValidator”),虽然我从来没有尝试这个自己。



Answer 2:

你可以试试这个解决办法... registrer在Module.php但功能getValidatorConfig或下键module.config.php“验证器”你的验证。

public function getValidatorConfig() {
  return array(
    'invokables' => array(
        'PasswordStrengthValidator' => 'User\Validator\PasswordStrength'
    ),
  );
}

然后在你的user.php的,试试这个:(但你必须访问的服务定位器,你可以从UserFactory等注入的话)

$validatorManager = $this->getServiceLocator()->get('ValidatorManager');
// here you can test $validatorManager->get('PasswordStrengthValidator');

$validatorChain = new ValidatorChain();
$validatorChain->setPluginManager($validatorManager);

$inputFilter = new InputFilter();   
$inputFilter->getFactory()->setDefaultValidatorChain($validatorChain);

这对我的作品。

马丁



Answer 3:

删除您可调用的配置。

并修改您的验证设置:

  $inputFilter->add($factory->createInput(array(
            'name'     => 'password',
            'required' => true,
            'validators' => array(
                array(
                    'name'    => 'User\Validator\PasswordStrength',
                ),
            ),
        )));

为我工作。



Answer 4:

Rufinus解决方案的工作般的魅力。 步骤我跟着使用自定义的验证中(在我的案件的URL验证来检查网站确实存在):

1)在module.config.php

'validators' => array(
     'invokables' => array(
         'UrlValidator' => 'Application\Validators\UrlValidator'
     ),
 )

2)在路径的应用/ SRC /应用/验证器/ UrlValidator.php

namespace Application\Validators; 
use Zend\Validator\AbstractValidator;                     
class UrlValidator extends AbstractValidator{
    const NOTURL = 'NOTURL';

    protected $messageTemplates = array(
        self::NOTURL => 'Value should be a valid URL',
    );

    public function __construct(array $options = array()){
        parent::__construct($options);
    }

    public function isValid($value){
        $this->setValue($value);       
        if (!$this->validateurl($value)) {
            $this->error(self::NOTURL);
            return false;
        } 
        return true;
    }
    private function validateurl($url) {
        $ch = curl_init(); // initialize curl handle
        curl_setopt($ch, CURLOPT_URL, $url); // set url to post to
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        $result = curl_exec($ch);

        $info = curl_getinfo($ch);
        $code = $info['http_code'];
        curl_close($ch);

        if ($code == substr($code, 0, 1) || substr($code, 0, 1) == '4' || substr($code, 0, 1) == '5') {
            return false;
        } else {
            return true;
        }
   }
}

3)在形式

  $inputFilter->add($factory->createInput(array(
                    'name' => 'url',                       
                    'validators' => array(
                        array(
                            'name' => 'NotEmpty',
                            'options' => array(
                                'messages' => array(
                                    'isEmpty' => 'URL is required'
                                )
                            )
                        ),
                        array(
                            'name'=>'Application\Validators\UrlValidator'
                        )
                    )
        )));

额外的)如果你想在应用程序(即一个控制器动作内),您可以从ValidatorManager插件检索任何地方使用它:

$urlValidator = $this->getServiceLocator()->get('ValidatorManager')->get('UrlValidator');


Answer 5:

是的,正如孔蒂或表述为工厂的情况下,你需要注入一个业务经理,或学说实体管理器在下面的例子中也可以是可调用的。 这种方式是非常优雅的解决方案:

 'validators' => array(
        'invokables' => array(
            //'emailExist' => 'Application\MyValidation\EmailExistValidator',
        ),
        'factories' => array(
            'emailExist' => function ($vm) {
                $serviceLocator = $vm->getServiceLocator();
                $emailExistValidator = new \Application\MyValidation\EmailExistValidator();
                $doctrineEntityManager = $serviceLocator->get('Doctrine\ORM\EntityManager');
                $emailExistValidator->setObjectManager($doctrineEntityManager);
                return $emailExistValidator;
            },
        ),
    ),


文章来源: Zend Framework 2 Custom Validators for Forms