cakephp无模式形式的条件验证器

时间:2015-09-25 05:11:34

标签: validation cakephp cakephp-3.0

我需要以无模型形式进行以下条件验证:

class NewForm extends Form
{
    if (address_type == 'Street')
        required: street_name, street_type
        not required: po_box
    elseif (address_type == 'PO')
        required: po_box
        not required: street_name, street_type
}

我尝试过以下验证器:

$validator
        ->requirePresence('street_name', true, 'street_name is a required field')
        ->notEmpty('street_name', 'street_name is a required field', function ($context) {
            return ($context['address_type'] == 'Street Address');
        })
        ->requirePresence('street_type', true, 'street_type is a required field')
        ->notEmpty('street_type', 'street_type is a required field', function ($context) {
            return ($context['address_type'] == 'Street Address');
        });

    $validator
        ->requirePresence('po_box', true, 'po_box is a required field')
        ->notEmpty('po_box', 'po_box is a required field', function ($context) {
            return ($context['address_type'] == 'PO');
        });

当我打电话给这样的验证时

$valid = $newform->validate($data);

它要求所有street_name,street_type和po_box都在输入数据中。

如何构造条件验证器来完成伪代码? 感谢

修改

我已经提出以下内容,这有效!但是,它不允许我从 - > errors()获取空/无效的字段 即,我需要能够知道,例如,街道名称'是空的,需要填写。

$validator
        ->add('address_type', 'missing fields', [
            'rule' => function ($value, $context) {
                if ($value == 'Street') {
                    if ((!array_key_exists('street_name', $context['data']) && empty($context['data']['street_name'])) ||
                        (!array_key_exists('street_type', $context['data']) && empty($context['data']['street_type']))) {
                        return false;
                    }
                } elseif ($value == 'PO') {
                    if ((!array_key_exists('po_box', $context['data']) && empty($context['data']['po_box'])) ||
                        (!array_key_exists('po_no', $context['data']) && empty($context['data']['po_no'])) ||
                        (!array_key_exists('po_exchange', $context['data']) && empty($context['data']['po_exchange']))) {
                        return false;
                    }
                }
            }
        ]);

1 个答案:

答案 0 :(得分:2)

如果Validator::requirePresence()支持条件评估的可调用内容,就像add()allowEmpty()noteEmpty()一样,这会很方便。

在添加类似内容之前,还有其他各种方法可以解决此问题,例如在address_type字段的自定义规则中修改验证程序,在覆盖Form::validate()方法中,甚至在控制器。

我可能会使用第一个变体,类似于此,根据所需的address_type值设置所需的字段:

protected function _buildValidator(Validator $validator)
{
    return $validator
        ->requirePresence('address_type')
        ->add('address_type', 'valid', [
            'rule' => function($value) {
                switch ($value) {
                    case 'Street Address':
                        $this->validator()
                            ->requirePresence('street_name')
                            ->requirePresence('street_type');
                        break;

                    case 'PO':
                        $this->validator()
                            ->requirePresence('po_box');
                        break;

                    default:
                        return false;
                }
                return true;
            }
        ])
        ->notEmpty('street_name')
        ->notEmpty('street_type')
        ->notEmpty('po_box')
        // ...
        ;
}

<强>更新

requirePresence()中对callables的支持为added for 3.1.1。有了这个功能,它可以有条件地要求像

这样的字段
$validator
    // ...
    ->requirePresence('street_name', function ($context) {
        return $context['data']['address_type'] === 'Street Address';
    })
    // ...
    ;

如果在很多字段的情况下干掉东西,可以使用动态可调用的参数,例如

$requiredFor = function ($value) {
    return function ($context) use ($value) {
        return $context['data']['address_type'] === $value;
    };
};

$validator
    // ...
    ->requirePresence('street_name', $requiredFor('Street Address'))
    ->requirePresence('street_type', $requiredFor('Street Address'))
    ->requirePresence('po_box', $requiredFor('PO'))
    // ...
    ;

另请参阅 Cookbook > Validation > Conditional Validation