【问题标题】:ZF3 - Callback validator attaches error message to wrong inputZF3 - 回调验证器将错误消息附加到错误的输入
【发布时间】:2019-07-12 15:33:03
【问题描述】:

我有一个表单,其中应根据选择字段中的选项要求单选按钮字段。如果选择了单选按钮选项“是”,那么还有一个文本字段也应该是必需的。 我对这两个字段都使用了回调验证器来检查这种依赖关系,但问题是错误消息被附加到错误的字段。例如,如果我从 select 中选择一个选项并未选中单选按钮,则验证器可以工作,但错误消息显示在 select 输入中,而不是单选按钮中。

根据“rkeet”在这篇文章中的回答,我为此字段编写了两个验证器:

https://github.com/zendframework/zend-inputfilter/issues/146

$inputFilter->add([
            'name' => 'regimenPreferencia',
            'required' => true,
            'validators' => [
                [
                    'name' => NotEmpty::class,
                    'options' => [
                        'message' => [
                            NotEmpty::IS_EMPTY => 'Ingrese el régimen de preferencia para este artículo'
                        ]
                    ],
                ],
                [
                    'name' => Callback::class,
                    'options' => [
                        'callback' => function($value, $context) {

                            var_dump($value, $context);
                            if($value === 'agricultura_familiar' && empty($context['esCompraCentralizada'])) {
                                $validatorChain = $this->getInputFilter()->getInputs()['esCompraCentralizada']->getValidatorChain();
                                $validatorChain->attach(new NotEmpty(['type' => NotEmpty::NULL]));
                                $this->getInputFilter()->getInputs()['esCompraCentralizada']->setValidatorChain($validatorChain);

                                return false;
                            }

                            return true;
                        },
                        'messages' => [
                            Callback::INVALID_VALUE => 'Indique si esta compra es centralizada'
                        ]
                    ],
                ]
            ],
            'allow_empty' => false,
            'continue_if_empty' => false,
        ]);

        $inputFilter->add([
            'name' => 'esCompraCentralizada',
            'required' => false,
            'allow_empty' => true,
            'validators' => [
                [
                    'name' => Callback::class,
                    'options' => [
                        'callback' => function($value, $context) {

                            if(strlen($value) > 0 && empty($context['porcAdjudicacionReservaMercado'])) {
                                $validatorChain = $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->getValidatorChain();
                                $validatorChain->attach(new NotEmpty(['type' => NotEmpty::NULL]));
                                $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->setValidatorChain($validatorChain);

                                return false;
                            }

                            return true;
                        },
                        'messages' => [
                            'callbackValue' => 'Ingrese el porcentaje de adjudicación de reserva de mercado'
                        ]
                    ],
                ]
            ],

            'continue_if_empty' => true
        ]);

        $inputFilter->add([
            'name' => 'porcAdjudicacionReservaMercado',
            'allow_empty' => true,
            'filters' => [
                ['name' => ToInt::class]
            ],
            'validators' => [

            ],
        ]);

【问题讨论】:

  • 很高兴被引用,我第一次想到。看esCompraCentralizada,你不是在更新不正确的ValidatorChain吗?如果设置了porcAdju*,则应该需要esCompra*。因此,您应该$this->getInputFilter()->getInputs('esCompra*')->getValidatorChain() 并照常进行。与您的其他输入回调相同。在您引用的 Github 上的示例中,NotEmpty 附加到 另一个 输入。所以,2个选项:
  • 1 - 使用您当前的大部分代码,按照之前的评论执行并更新 当前 输入的验证器链。 2 - 按照 Github 示例执行操作,并根据“this one's”值更新 other 输入。
  • (在引用示例中,伪代码:如果设置了 latitude,则设置经度 && 如果设置了 longitude,则设置纬度)
  • 嗨,rkeet,非常感谢您的回答。实际上,字段约束应该是这样的:如果设置了regimenPreferencia,并且值为agricultura_familiar,则应该需要esCompraCentralizada;如果设置了esCompraCentralizada,并且选择了“是”选项,则应该需要porcAdjudicacionReservaMercado。我会测试你的方法,然后用结果回复你。再次感谢。
  • 怎么样?坚持只使用esCompra*regi*,您可以: 1 - 通过上下文检查esCompra* 上的回调,如果设置了regi*,如果是,则在它自己的链上添加一个NotEmpty 验证器。 2 - regi* 上的回调检查自身是否已设置,如果是,则在 esCompra* 链上添加 NotEmpty 验证器。 - 这同样适用于第二种情况,附加条件是它必须是“设置 && true”而不是仅仅设置。

标签: php zend-framework zend-framework3


【解决方案1】:

好的,我让它按预期工作。 我向 esCompraCentralizada 添加了一个回调验证器,以检查它是否为空,并将其余验证器添加到 porcAdjudicacionReservaMercado 字段中。

这就是验证器最终的样子:

$inputFilter->add([
        'name' => 'esCompraCentralizada',
        'required' => false,
        'allow_empty' => true,
        'validators' => [
            [
                'name' => Callback::class,
                'brake_chain_on_failure' => true,
                'options' => [
                    'callback' => function($value, $context) {
                        if(!isset($context['esCompraCentralizada']) && $context['regimenPreferencia'] === 'agricultura_familiar') {
                            $validatorChain = $this->getInputFilter()->getInputs()['esCompraCentralizada']->getValidatorChain();
                            $validatorChain->attach(new NotEmpty(['type' => NotEmpty::NULL]));
                            $this->getInputFilter()->getInputs()['esCompraCentralizada']->setValidatorChain($validatorChain);

                            return false;
                        }

                        return true;
                    },
                    'messages' => [
                        Callback::INVALID_VALUE => 'Indique si esta compra es centralizada'
                    ]
                ],
            ]
        ]
    ]);

    $inputFilter->add([
        'name' => 'porcAdjudicacionReservaMercado',
        'required' => false,
        'allow_empty' => true,
        'filters' => [
            ['name' => ToInt::class]
        ],
        'validators' => [
            [
                'name' => Callback::class,
                'break_chain_on_failure' => true,
                'options' => [
                    'callback' => function($value, $context) {
                        if($context['porcAdjudicacionReservaMercado'] === '' && $context['esCompraCentralizada'] === '1' && $context['regimenPreferencia'] === 'agricultura_familiar') {
                            $validatorChain = $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->getValidatorChain();
                            $validatorChain->attach(new NotEmpty(['type' => NotEmpty::NULL]));
                            $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->setValidatorChain($validatorChain);

                            return false;
                        }

                        return true;
                    },
                    'messages' => [
                        Callback::INVALID_VALUE => 'Ingrese el porcentaje de adjudicación de reserva de mercado'
                    ]
                ],
            ],
            [
                'name' => Callback::class,
                'break_chain_on_failure' => true,
                'options' => [
                    'callback' => function($value, $context) {
                        if (!is_numeric($context['porcAdjudicacionReservaMercado']) && $context['regimenPreferencia'] === 'agricultura_familiar' && $context['esCompraCentralizada'] === '1') {
                            $validatorChain = $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->getValidatorChain();
                            $validatorChain->attach(new LessThan());
                            $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->setValidatorChain($validatorChain);

                            return false;
                        }

                        return true;
                    },
                    'message' => [
                        Callback::INVALID_VALUE => 'El porcentaje de adjudicación de reserva de mercado debe ser un valor numérico'
                    ]
                ],
            ],
            [
                'name' => Callback::class,
                'break_chain_on_failure' => true,
                'options' => [
                    'callback' => function($value, $context) {
                        if ($value > 100 && $context['regimenPreferencia'] === 'agricultura_familiar' && $context['esCompraCentralizada'] === '1') {
                            $validatorChain = $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->getValidatorChain();
                            $validatorChain->attach(new LessThan());
                            $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->setValidatorChain($validatorChain);

                            return false;
                        }

                        return true;
                    },
                    'message' => [
                        Callback::INVALID_VALUE => 'El porcentaje de adjudicación de reserva de mercado debe ser menor o igual a 100'
                    ]
                ],
            ],
            [
                'name' => Callback::class,
                'break_chain_on_failure' => true,
                'options' => [
                    'callback' => function($value, $context) {
                        if ($value < 30 && $context['regimenPreferencia'] === 'agricultura_familiar' && $context['esCompraCentralizada'] === '1') {
                            $validatorChain = $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->getValidatorChain();
                            $validatorChain->attach(new GreaterThan());
                            $this->getInputFilter()->getInputs()['porcAdjudicacionReservaMercado']->setValidatorChain($validatorChain);

                            return false;
                        }

                        return true;
                    },
                    'message' => [
                        Callback::INVALID_VALUE => 'El porcentaje de precio de materiales nacionales debe ser mayor o igual a 30'
                    ]
                ],
            ],
        ],
    ]);

我在第二个字段中添加了四个验证器来检查:

  • 空字段
  • 字段值不是数字
  • 字段值小于 30(功能要求)
  • 字段值大于100(功能需求)

如果 'regimen_preferencia' 是 'agricultura_familiar' 并且 'esCompraCentralizada' 是真的,所有这些都适用。

非常感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多