可以在元素级别实现动态验证吗?

时间:2016-06-02 03:34:58

标签: php zend-framework2 zend-form zend-validate zend-inputfilter

可以在元素级别实现动态验证吗?我使用this示例来实现依赖于另一个元素的值的一个元素的验证。但是为了这个目的,我需要为每个单独的表单实现这个,我使用这个元素(注释)进行验证。我有很多这样的形式。有没有办法做到以下几点:

使用某种“data-comment-for”属性将此过滤器/验证逻辑带到元素级别,并从父表单中检索它所依赖的元素的值。

这是我目前的代码(但我现在需要为每个表单提供它。它看起来并不优雅):

class CompetencyAdvanceHumanRightsAndJusticeFormFilter extends InputFilter
{
    public function isValid($context = null)
    {
        $figradeCommentName = 'applJusticeFIGrade'.'Comment';

        $forGrade = $this->get('applJusticeFIGrade');
        $gradeComment = $this->get($figradeCommentName);

        $applJusticeFIGradeRawValue = $forGrade->getRawValue('applJusticeFIGrade');

        if(is_numeric($applJusticeFIGradeRawValue)){
            $gradeValue = intval($applJusticeFIGradeRawValue);
        }else{
            $gradeValue = $applJusticeFIGradeRawValue;
        }

        if ($gradeValue != 'na' && $gradeValue > 0) {
            $gradeComment->setRequired(true);
            $validatorChain = new Validator\ValidatorChain();
            $validatorChain->attach(
                new Validator\NotEmpty(),
                true
            );
            $gradeComment->setValidatorChain($validatorChain);
        }

        return parent::isValid($context);
    }

    public function __construct(){
        $this->add(array(
            'name' => 'id',
            'required' => true,
            'filters' => array(
                array('name' => 'Int'),
            ),
        ));

        $this->add(array(
            'name' => 'studEvalId',
            'required' => true,
            'filters' => array(
                array('name' => 'Int'),
            ),
        ));
    }
}

修改

我在问题中添加了自定义元素的代码。我尝试将这种逻辑放在元素级别上有一些“遗留物”。

评论元素

class Comment extends Element implements InputProviderInterface
{

    /**
     * @var ValidatorInterface
     */
    protected $validator;

    // set its type
    protected $attributes = array(
        'type' => 'comment'
    );


    public function init()
    {

        if (null === $this->validator) {

            $validator = new StringLength();
            $validator->setMax(10);

            $validator->setMessage('The comment should not exceed 1000 letters!', StringLength::INVALID);

            $this->validator = $validator;
        }


    }


    /**
     * Get a validator if none has been set.
     *
     * @return ValidatorInterface
     */
    public function getValidator()
    {
        return $this->validator;
    }


    /**
     * @param ValidatorInterface $validator
     * @return $this
     */
    public function setValidator(ValidatorInterface $validator)
    {
        $this->validator = $validator;
        return $this;
    }


    /**
     * remove require and validator defaults because we have none
     *
     * @return array
     */
    public function getInputSpecification()
    {
//        return array(
//            'name' => $this->getName(),
//            'required' => false,
//            'validators' => array(
//                $this->getValidator(),
//            ),
//            'filters' => array(
//              new FIGradeCommentDynamicBufferFilter()
//            ),
//        );


        return array(
            'name' => $this->getName(),
            'required' => false,
            'filters' => array(
                array('name' => 'Zend\Filter\StringTrim'),
            ),
            'validators' => array(
                $this->getValidator(),
            ),

        );
    }

    // tell it where to find its view helper, so formRow and the like work correctly
    public function getViewHelperConfig()
    {
        return array('type' => '\OnlineFieldEvaluation\View\Helper\FormComment');
    }

}

1 个答案:

答案 0 :(得分:1)

您可以创建一个基本的抽象输入过滤器类和一个接口,并使所有表单过滤器扩展实现接口的基类,使用您希望在表单类中使用的方法来使事物正常工作。

使用方法建立界面:

interface GradeCommentFormFilterInterface()
{
    protected function getGradeInput();

    protected function getCommentInput();
}

然后将公共代码移动到基类:

abstract class BaseGradeCommentFormFilter extends InputFilter implements GradeCommentFormFilterInterface
{   
    protected function getGradeInput()
    {
        return $this->get(static::GRADE_NAME);
    }

    protected function getCommentInput()
    {
        return $this->get(static::GRADE_NAME . 'Comment');
    }

    public function isValid($context = null)
    {
        $gradeInput = $this->getGradeInput();
        $commentInput = $this->getCommentInput();
        $rawValue = $this->getRawValue($gradeInput);

        if(is_numeric($rawValue))
        {
            $gradeValue = intval($rawValue);
        }
        else
            $gradeValue = $rawValue;

        if ($gradeValue != 'na' && $gradeValue > 0) {
            $commentInput->setRequired(true);
            $validatorChain = new Validator\ValidatorChain();
            $validatorChain->attach(
                new Validator\NotEmpty(),
                true
            );
            $commentInput->setValidatorChain($validatorChain);
        }
        return parent::isValid($context);
    }
}

现在你可以像这样使用你的抽象类:

class CompetencyAdvanceHumanRightsAndJusticeFormFilter extends BaseGradeCommentFormFilter
{   
    const GRADE_NAME = 'applJusticeFIGrade';

    //... other code
}

我很快就尝试让它适用于你的情况,但是这没有经过测试,可能有很多方法可以优化它,但它可以让你知道你可以做些什么。