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

Validation cakephp无模型形式的条件验证器,validation,cakephp,cakephp-3.0,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, st

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

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);
它要求输入数据中包含所有街道名称、街道类型和邮政信箱

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

编辑

我想出了以下方法,很管用!但是,它不允许我从->errors()获取空/无效的字段 例如,我需要知道,例如,“street_name”是空的,需要填写

$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;
                    }
                }
            }
        ]);

如果
Validator::requirePresence()
支持条件求值的可调用项,就像
add()
allowEmpty()
notempty()
do一样,这将非常方便

在添加类似的内容之前,还有其他各种方法来处理此问题,例如,修改
地址类型
字段的自定义规则中的验证器、重写的
表单::validate()
方法中的验证器,甚至在控制器中

我可能会使用第一个变量,类似这样的变量,它根据所需的
地址类型
值设置所需的字段:

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')
        // ...
        ;
}
更新

requirerepresence()
中可调用项的支持已被取消。使用该功能,可以有条件地要求字段,如

$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'))
    // ...
    ;

另请参见《yoyoma》,目前还没有,但在发布之前不会太久。如果你喜欢冒险,你可以尝试
dev master
,直到3.1.1发布。在
requirerepresence()
的可调用项可用之前,第一个解决方案运行良好,直到我需要将其中一个字段设置为null。也就是说,如果是“街道地址”,则该位置的
notEmpty
表示我无法将“邮箱”设置为空。如果我将
notEmpty
移动到
开关
区域,则它允许设置null,但是,一旦出现错误,
表单->错误()
不会给出未设置的特定字段。希望这是有意义的,如果你有任何建议,我真的很感激