Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate层级嵌套与预期不符 #26

Open
LonelySally opened this issue Jan 21, 2025 · 7 comments
Open

Validate层级嵌套与预期不符 #26

LonelySally opened this issue Jan 21, 2025 · 7 comments

Comments

@LonelySally
Copy link

所属功能组件

验证器(Validate)

ThinkPHP 版本

8.1.2

操作系统

Centos

错误信息

  1. 嵌套验证失败时题错误信息不符合预期
  2. 嵌套下数组值验证不生效
    真实业务代码测试
//注册是一个有序验证规则
if (!function_exists('mustArrayIsList')) {
    function mustArrayIsList($value, $rule, $data, $field, $title): bool|string
    {
        if (is_array($value) === false) {
            return $field . '非有序数组';
        }
        return array_is_list($value) ? true : $field . '非有序数组';
    }
}

Validate::maker(function ($validate) {
    if (function_exists('mustArrayIsList'))
        $validate->extend('list', 'mustArrayIsList');
});

//rule校验规则定义
[
            'department_uid' => '>=:0',
            'customer_uid' => 'require|>=:0',
            'customer_signature' => 'max:254',
            'original_price' => 'require|>=:0|integer',
            'transaction_price' => 'require|>=:0|integer',
            'reduce_price' => 'require|>=:0|integer',
            'cost_price' => 'require|>=:0|integer',
            'coupon_price' => 'require|>=:0|integer',
            'buy_qty' => 'require|>=:0|integer',
            'designee_switch' => 'require|in:0,1|integer',
            'free_switch' => 'require|in:0,1|integer',
            'prepaid_switch' => 'require|in:0,1|integer',
            'consume_switch' => 'require|in:0,1|integer',
            'speed_switch' => 'require|in:0,1|integer',
            'arrears_switch' => 'require|in:0,1|integer',
            'new_customer_switch' => 'require|in:0,1|integer',
            'inc_balance_price' => 'require|>=:0|integer',
            'inc_extra_price' => 'require|>=:0|integer',
            'inc_rewards_points' => 'require|>=:0|integer',
            'inc_arrears_price' => 'require|>=:0|integer',
            'dec_balance_price' => 'require|>=:0|integer',
            'dec_extra_price' => 'require|>=:0|integer',
            'dec_rewards_points' => 'require|>=:0|integer',
            'dec_arrears_price' => 'require|>=:0|integer',
            'shop_goods' => 'list',
            'manual' => 'list',
            'order_datetime' => 'require|date',
            'remind_notify_switch' => 'require|in:0,1|integer',
            'memo' => 'max:254',//备注
            'guests_qty' => 'require|>=:0|integer',
            'guests_man_qty' => 'require|>=:0|integer',
            'guests_woman_qty' => 'require|>=:0|integer',
            'pay_terms' => 'list',
            'pay_terms.*' => rules([
                'title' => 'require|max:254',
                'pay_uid' => 'require|>:0|integer',
                'side_switch' => 'require|in:0,1|integer',
                'inside_keyword' => 'require',
                'outside_keyword' => 'require',
                'pay_price' => 'require|>=:0|integer',
            ]),
            'shop_goods.*' => rules([
                'free_switch' => 'require|in:0,1|integer',
                'goods_uid' => 'require|>:0',
                'bundle_goods_uid' => 'require|>=:0',
                'original_price' => 'require|>=:0|integer',
                'transaction_price' => 'require|>=:0|integer',
                'reduce_price' => 'require|>=:0|integer',
                'cost_price' => 'require|>=:0|integer',
                'coupon_price' => 'require|>=:0|integer',
                'total_transaction_per' => 'require|>=:0|<=:100',
                'buy_qty' => 'require|integer',
                'guests_qty' => 'require|>=:0|integer',
                'guests_man_qty' => 'require|>=:0|integer',
                'guests_woman_qty' => 'require|>=:0|integer',
                'pay_terms' => 'list',
                'pay_terms.*' => rules([
                    'title' => 'require|max:254',
                    'pay_uid' => 'require|>:0|integer',
                    'side_switch' => 'require|in:0,1|integer',
                    'inside_keyword' => 'require',
                    'outside_keyword' => 'require',
                    'pay_price' => 'require|>=:0|integer',
                    'reduce_price' => 'require|>=:0|integer',
                ]),
                'coupon' => 'list',
                'coupon.*' => rules([
                    'expiry_forever_switch' => 'require|in:0,1|integer',
                    'expiry_effect_timestamp' => 'require|integer',
                    'expiry_expiration_timestamp' => 'require|integer',
                    'disposable_switch' => 'require|in:0,1|integer',
                    'balance_price' => 'require|>=:0',
                    'limit_type' => 'require|in:0,1,2|integer',
                    'limit_type_payload.*' => '>:0',
                    'limit_price_switch' => 'require|in:0,1|integer',
                    'limit_price' => 'require|>=:0',
                    'use_limit_price_switch' => 'require|in:0,1|integer',
                    'use_limit_price' => 'require|>=:0',
                ]),
                'measure' => 'list',
                'measure.*' => rules([
                    'expiry_forever_switch' => 'require|in:0,1|integer',
                    'expiry_timestamp' => 'require|>=:0|integer',
                    'infinite_qty_switch' => 'require|in:0,1|integer',
                    'aggregate_qty' => 'require|>=:0|integer',
                    'extra_qty' => 'require|>=:0|integer',
                    'extra_cost_price' => 'require|>=:0|integer',
                    'limit_type' => 'require|in:0,1,2,3|integer',
                    'limit_qty' => 'require|>=:0|integer',
                    'commission_calculate_type' => 'require|in:0,1|integer',
                    'employee_commission_type' => 'require|in:0,1|integer',
                    'employee_commission_value' => 'require|>=:0',
                    'employee_extra_commission_type' => 'require|in:0,1|integer',
                    'employee_extra_commission_value' => 'require|>=:0',
                    'split_switch' => 'require|in:0,1|integer',
                    'fit_merchant_uid' => 'require|list',
                    'fit_merchant_uid.*' => 'gt:0',
                ]),
                'consumable' => 'list',
                'consumable.*' => rules([
                    'consumable_goods_uid' => 'require|>=:0|integer',
                    'group_title' => 'require',
                    'transaction_price' => 'require|>=:0|integer',
                    'original_price' => 'require|>=:0|integer',
                ]),
                'commission' => 'list',
                'commission.*' => rules([
                    'employee_uid' => 'require|>:0',
                    'employee_position_uid' => 'require|>=:0',
                    'employee_group_uid' => 'require|>=:0',
                    'commission_price' => 'require|>=:0|integer',
                    'performance_price' => 'require|>=:0|integer',
                    'designee_switch' => 'require|in:0,1|integer',
                    'real_free_price' => 'require|>=:0|integer',
                    'real_cash_price' => 'require|>=:0|integer',
                    'real_account_price' => 'require|>=:0|integer',
                    'virtual_free_price' => 'require|>=:0|integer',
                    'virtual_cash_price' => 'require|>=:0|integer',
                    'virtual_account_price' => 'require|>=:0|integer',
                    'cost_free_price' => 'require|>=:0|integer',
                    'cost_cash_price' => 'require|>=:0|integer',
                    'cost_account_price' => 'require|>=:0|integer',
                    'guests_qty' => 'require|integer',
                    'guests_man_qty' => 'require|integer',
                    'guests_woman_qty' => 'require|integer',
                    'pay_terms' => 'list',
                    'pay_terms.*' => rules([
                        'title' => 'require|max:254',
                        'pay_uid' => 'require|>:0|integer',
                        'side_switch' => 'require|in:0,1|integer',
                        'inside_keyword' => 'require',
                        'outside_keyword' => 'require',
                        'commission_price' => 'require|>=:0|integer',
                        'performance_price' => 'require|>=:0|integer',
                    ]),
                ]),
            ]),
            'coupon_used.*' => rules([
                'order_shop_goods_coupon_uid' => 'require|>:0|integer',
                'used_price' => 'require|>:0|integer',
            ]),
            'measure_used.*' => rules([
                'order_shop_goods_measure_uid' => 'require|>:0',
                'used_aggregate_qty' => 'require|>=:0',
                'used_extra_qty' => 'require|>=:0',
                'inquiry_datetime' => 'require|date',
                'guests_qty' => 'require|>=:0|integer',
                'guests_man_qty' => 'require|>=:0|integer',
                'guests_woman_qty' => 'require|>=:0|integer',
                'commission' => 'list',
                'commission.*' => rules([
                    'employee_uid' => 'require|>:0',
                    'employee_position_uid' => 'require|>=:0',
                    'employee_group_uid' => 'require|>=:0',
                    'commission_price' => 'require|>=:0|integer',
                    'performance_price' => 'require|>=:0|integer',
                    'designee_switch' => 'require|in:0,1|integer',
                    'real_free_price' => 'require|>=:0|integer',
                    'real_cash_price' => 'require|>=:0|integer',
                    'real_account_price' => 'require|>=:0|integer',
                    'virtual_free_price' => 'require|>=:0|integer',
                    'virtual_cash_price' => 'require|>=:0|integer',
                    'virtual_account_price' => 'require|>=:0|integer',
                    'cost_free_price' => 'require|>=:0|integer',
                    'cost_cash_price' => 'require|>=:0|integer',
                    'cost_account_price' => 'require|>=:0|integer',
                    'guests_qty' => 'require|>=:0|integer',
                    'guests_man_qty' => 'require|>=:0|integer',
                    'guests_woman_qty' => 'require|>=:0|integer',
                ]),
            ]),
        ]
  • 请求数据1
    实际返回shop_goods.不能为空
    预期返回shop_goods.
    .measure.*.fit_merchant_uid不能为空
    发生该问题在Validate.php:761处
    throw new ValidateException($result, $name);
    $result是shop_goods.不能为空,$name是measure..fit_merchant_uid
{
    "designee_switch": 0,
    "department_uid": 2411206172000115,
    "customer_uid": 10241101401260001,
    "original_price": 300,
    "transaction_price": 250,
    "reduce_price": 50,
    "cost_price": 200,
    "coupon_price": 0,
    "buy_qty": 1,
    "free_switch": 0,
    "prepaid_switch": 0,
    "consume_switch": 1,
    "speed_switch": 1,
    "arrears_switch": 0,
    "new_customer_switch": 0,
    "inc_balance_price": 11,
    "inc_extra_price": 12,
    "inc_rewards_points": 13,
    "inc_arrears_price": 14,
    "dec_balance_price": 10,
    "dec_extra_price": 10,
    "dec_rewards_points": 10,
    "dec_arrears_price": 10,
    "shop_goods": [ 
        {
            "total_transaction_per": 98.55,
            "guests_qty": 1,
            "guests_man_qty": 0,
            "guests_woman_qty": 1,
            "free_switch": 1,
            "goods_uid": 2412063775700122,
            "buy_qty": 1,
            "original_price": 300,
            "reduce_price": 50,
            "transaction_price": 250,
            "cost_price": 200,
            "coupon_price": 0,
            "bundle_goods_uid": 0,
            "consumable": [ 
                {
                    "consumable_goods_uid": 2412063745700122,
                    "group_title": "杯型",
                    "original_price": 4,
                    "transaction_price": 4
                }
            ],
            "measure": [ //重点关注这块数据结构
                {
                    "expiry_forever_switch": 1,
                    "expiry_timestamp": 0,
                    "infinite_qty_switch": 0,
                    "aggregate_qty": 10,
                    "extra_qty": 2,
                    "extra_cost_price": 19900,
                    "limit_type": 1,
                    "limit_qty": 5,
                    "commission_calculate_type": 1,
                    "employee_commission_type": 1,
                    "employee_commission_value": 10,
                    "employee_extra_commission_type": 1,
                    "employee_extra_commission_value": "10.88",
                    "split_switch": 1
                },
                {
                    "expiry_forever_switch": 1,
                    "expiry_timestamp": 0,
                    "infinite_qty_switch": 0,
                    "aggregate_qty": 10,
                    "extra_qty": 2,
                    "extra_cost_price": 19900,
                    "limit_type": 1,
                    "limit_qty": 5,
                    "commission_calculate_type": 1,
                    "employee_commission_type": 1,
                    "employee_commission_value": 10,
                    "employee_extra_commission_type": 1,
                    "employee_extra_commission_value": 10,
                    "split_switch": 0,
                    "fit_merchant_uid": [
                        -12
                    ]
                }
            ],
            "coupon": [ 
                {
                    "expiry_forever_switch": 0,
                    "expiry_effect_timestamp": 1732255155,
                    "expiry_expiration_timestamp": 1832255155,
                    "disposable_switch": 0,
                    "balance_price": 100,
                    "limit_type": 2,
                    "limit_type_payload": [
                        2412034760300122
                    ],
                    "limit_price_switch": 1,
                    "limit_price": 1,
                    "use_limit_price_switch": 0,
                    "use_limit_price": 1
                }
            ],
            "commission": [ 
                {
                    "guests_qty": 1,
                    "guests_man_qty": 1,
                    "guests_woman_qty": 0,
                    "employee_uid": 2411275671100112,
                    "employee_position_uid": 0,
                    "employee_group_uid": 0,
                    "commission_price": 100,
                    "performance_price": 100,
                    "designee_switch": 0,
                    "real_free_price": 100,
                    "real_cash_price": 100,
                    "real_account_price": 100,
                    "virtual_free_price": 100,
                    "virtual_cash_price": 100,
                    "virtual_account_price": 100,
                    "cost_free_price": 100,
                    "cost_cash_price": 100,
                    "cost_account_price": 100,
                    "pay_terms": [
                        {
                            "title": "余额",
                            "pay_uid": 2411195113200189,
                            "side_switch": 0,
                            "inside_keyword": "balance_price",
                            "outside_keyword": "undefined",
                            "commission_price": 100,
                            "performance_price": 100
                        },
                        {
                            "title": "余额",
                            "pay_uid": 2411195113200189,
                            "side_switch": 0,
                            "inside_keyword": "balance_price",
                            "outside_keyword": "undefined",
                            "commission_price": 100,
                            "performance_price": 100
                        }
                    ]
                }
            ],
            "pay_terms": [ 
                {
                    "title": "现金",
                    "pay_uid": 2411195119500189,
                    "side_switch": 0,
                    "inside_keyword": "undefined",
                    "outside_keyword": "undefined",
                    "pay_price": 90,
                    "reduce_price": 10
                },
                {
                    "title": "现金",
                    "pay_uid": 2411195119500189,
                    "side_switch": 0,
                    "inside_keyword": "undefined",
                    "outside_keyword": "undefined",
                    "pay_price": 90,
                    "reduce_price": 10
                }
            ]
        }
    ],
    "order_datetime": "2024-11-22 13:59:15",
    "remind_notify_switch": 1,
    "memo": "备注",
    "guests_qty": 2,
    "guests_man_qty": 1,
    "guests_woman_qty": 1,
    "manual": [ 
        123,
        456
    ],
    "pay_terms": [ 
        {
            "title": "现金",
            "pay_uid": 2411195119500189,
            "side_switch": 0,
            "inside_keyword": "undefined",
            "outside_keyword": "undefined",
            "pay_price": 10
        },
        {
            "title": "微信(扫码)",
            "pay_uid": 2411195143000189,
            "side_switch": 1,
            "inside_keyword": "undefined",
            "outside_keyword": "scan_wechat",
            "pay_price": 10
        }
    ],
    "measure_used": [ 
        {
            "order_shop_goods_measure_uid": 2412105047000002,
            "used_aggregate_qty": 1,
            "used_extra_qty": 1,
            "inquiry_datetime": "2024-12-22 10:00:00",
            "guests_qty": 1,
            "guests_man_qty": 0,
            "guests_woman_qty": 1,
            "commission": [ 
                {
                    "guests_qty": 1,
                    "guests_man_qty": 1,
                    "guests_woman_qty": 0,
                    "employee_uid": 2411275671100112,
                    "employee_position_uid": 0,
                    "employee_group_uid": 0,
                    "commission_price": 9,
                    "performance_price": 9,
                    "designee_switch": 0,
                    "real_free_price": 9,
                    "real_cash_price": 9,
                    "real_account_price": 9,
                    "virtual_free_price": 9,
                    "virtual_cash_price": 9,
                    "virtual_account_price": 9,
                    "cost_free_price": 9,
                    "cost_cash_price": 9,
                    "cost_account_price": 9
                }
            ]
        }
    ]
}
  • 请求数据2
    实际返回通过校验
    预期返回shop_goods..measure..fit_merchant_uid必须大于0
{
    "designee_switch": 0,
    "department_uid": 2411206172000115,
    "customer_uid": 10241101401260001,
    "original_price": 300,
    "transaction_price": 250,
    "reduce_price": 50,
    "cost_price": 200,
    "coupon_price": 0,
    "buy_qty": 1,
    "free_switch": 0,
    "prepaid_switch": 0,
    "consume_switch": 1,
    "speed_switch": 1,
    "arrears_switch": 0,
    "new_customer_switch": 0,
    "inc_balance_price": 11,
    "inc_extra_price": 12,
    "inc_rewards_points": 13,
    "inc_arrears_price": 14,
    "dec_balance_price": 10,
    "dec_extra_price": 10,
    "dec_rewards_points": 10,
    "dec_arrears_price": 10,
    "shop_goods": [ 
        {
            "total_transaction_per": 98.55,
            "guests_qty": 1,
            "guests_man_qty": 0,
            "guests_woman_qty": 1,
            "free_switch": 1,
            "goods_uid": 2412063775700122,
            "buy_qty": 1,
            "original_price": 300,
            "reduce_price": 50,
            "transaction_price": 250,
            "cost_price": 200,
            "coupon_price": 0,
            "bundle_goods_uid": 0,
            "consumable": [ 
                {
                    "consumable_goods_uid": 2412063745700122,
                    "group_title": "杯型",
                    "original_price": 4,
                    "transaction_price": 4
                }
            ],
            "measure": [ //重点关注这块数据结构
                {
                    "expiry_forever_switch": 1,
                    "expiry_timestamp": 0,
                    "infinite_qty_switch": 0,
                    "aggregate_qty": 10,
                    "extra_qty": 2,
                    "extra_cost_price": 19900,
                    "limit_type": 1,
                    "limit_qty": 5,
                    "commission_calculate_type": 1,
                    "employee_commission_type": 1,
                    "employee_commission_value": 10,
                    "employee_extra_commission_type": 1,
                    "employee_extra_commission_value": "10.88",
                    "split_switch": 1,
                    "fit_merchant_uid": [
                        -1
                    ]
                },
                {
                    "expiry_forever_switch": 1,
                    "expiry_timestamp": 0,
                    "infinite_qty_switch": 0,
                    "aggregate_qty": 10,
                    "extra_qty": 2,
                    "extra_cost_price": 19900,
                    "limit_type": 1,
                    "limit_qty": 5,
                    "commission_calculate_type": 1,
                    "employee_commission_type": 1,
                    "employee_commission_value": 10,
                    "employee_extra_commission_type": 1,
                    "employee_extra_commission_value": 10,
                    "split_switch": 0,
                    "fit_merchant_uid": [
                        -1
                    ]
                }
            ],
            "coupon": [ 
                {
                    "expiry_forever_switch": 0,
                    "expiry_effect_timestamp": 1732255155,
                    "expiry_expiration_timestamp": 1832255155,
                    "disposable_switch": 0,
                    "balance_price": 100,
                    "limit_type": 2,
                    "limit_type_payload": [
                        2412034760300122
                    ],
                    "limit_price_switch": 1,
                    "limit_price": 1,
                    "use_limit_price_switch": 0,
                    "use_limit_price": 1
                }
            ],
            "commission": [ 
                {
                    "guests_qty": 1,
                    "guests_man_qty": 1,
                    "guests_woman_qty": 0,
                    "employee_uid": 2411275671100112,
                    "employee_position_uid": 0,
                    "employee_group_uid": 0,
                    "commission_price": 100,
                    "performance_price": 100,
                    "designee_switch": 0,
                    "real_free_price": 100,
                    "real_cash_price": 100,
                    "real_account_price": 100,
                    "virtual_free_price": 100,
                    "virtual_cash_price": 100,
                    "virtual_account_price": 100,
                    "cost_free_price": 100,
                    "cost_cash_price": 100,
                    "cost_account_price": 100,
                    "pay_terms": [
                        {
                            "title": "余额",
                            "pay_uid": 2411195113200189,
                            "side_switch": 0,
                            "inside_keyword": "balance_price",
                            "outside_keyword": "undefined",
                            "commission_price": 100,
                            "performance_price": 100
                        },
                        {
                            "title": "余额",
                            "pay_uid": 2411195113200189,
                            "side_switch": 0,
                            "inside_keyword": "balance_price",
                            "outside_keyword": "undefined",
                            "commission_price": 100,
                            "performance_price": 100
                        }
                    ]
                }
            ],
            "pay_terms": [ 
                {
                    "title": "现金",
                    "pay_uid": 2411195119500189,
                    "side_switch": 0,
                    "inside_keyword": "undefined",
                    "outside_keyword": "undefined",
                    "pay_price": 90,
                    "reduce_price": 10
                },
                {
                    "title": "现金",
                    "pay_uid": 2411195119500189,
                    "side_switch": 0,
                    "inside_keyword": "undefined",
                    "outside_keyword": "undefined",
                    "pay_price": 90,
                    "reduce_price": 10
                }
            ]
        }
    ],
    "order_datetime": "2024-11-22 13:59:15",
    "remind_notify_switch": 1,
    "memo": "备注",
    "guests_qty": 2,
    "guests_man_qty": 1,
    "guests_woman_qty": 1,
    "manual": [ 
        123,
        456
    ],
    "pay_terms": [ 
        {
            "title": "现金",
            "pay_uid": 2411195119500189,
            "side_switch": 0,
            "inside_keyword": "undefined",
            "outside_keyword": "undefined",
            "pay_price": 10
        },
        {
            "title": "微信(扫码)",
            "pay_uid": 2411195143000189,
            "side_switch": 1,
            "inside_keyword": "undefined",
            "outside_keyword": "scan_wechat",
            "pay_price": 10
        }
    ],
    "measure_used": [ 
        {
            "order_shop_goods_measure_uid": 2412105047000002,
            "used_aggregate_qty": 1,
            "used_extra_qty": 1,
            "inquiry_datetime": "2024-12-22 10:00:00",
            "guests_qty": 1,
            "guests_man_qty": 0,
            "guests_woman_qty": 1,
            "commission": [ 
                {
                    "guests_qty": 1,
                    "guests_man_qty": 1,
                    "guests_woman_qty": 0,
                    "employee_uid": 2411275671100112,
                    "employee_position_uid": 0,
                    "employee_group_uid": 0,
                    "commission_price": 9,
                    "performance_price": 9,
                    "designee_switch": 0,
                    "real_free_price": 9,
                    "real_cash_price": 9,
                    "real_account_price": 9,
                    "virtual_free_price": 9,
                    "virtual_cash_price": 9,
                    "virtual_account_price": 9,
                    "cost_free_price": 9,
                    "cost_cash_price": 9,
                    "cost_account_price": 9
                }
            ]
        }
    ]
}

其它说明

关于层级校验的代码执行逻辑实际上可以使用原有的单层级校验+递归的形式完成,现在的拆分实现反而增加了更多的不确定性.
另外关于TestUnit,Validate已经是一个独立模块,但是单元测试数据未覆盖所有规则,层级单一(无层级嵌套测试).
可以做一个全规则+嵌套(3层甚至更多)的测试样例进行全覆盖测试避免频繁出现与预期相悖的校验结果.

@liu21st
Copy link
Member

liu21st commented Jan 22, 2025

问题出在 'fit_merchant_uid.*' => 'gt:0', 这个规则目前是不支持的 你可以在你的list验证规则里面附加判断处理一下

@LonelySally
Copy link
Author

LonelySally commented Jan 22, 2025

问题出在 'fit_merchant_uid.*' => 'gt:0', 这个规则目前是不支持的 你可以在你的list验证规则里面附加判断处理一下

当嵌套层级只有一层的时候是生效的.另外,回滚到8.x-dev 12ce496时校验正常提示fit_merchant_uid.*需要大于0.
另外这个pr实际是提在topthink/framework,看到issue引导才来这边又重新贴了一次.
gt:0的主要问题是多层级嵌套时没被执行.
总结下,从8.x-dev 12ce496升级到8.1.2出现校验不符合预期问题,然后回退校验符合预期,期间并没有变更任何业务代码.

@liu21st
Copy link
Member

liu21st commented Jan 22, 2025

测试了下 确实目前不支持超过2级的带*的多维数组验证场景

@liu21st
Copy link
Member

liu21st commented Jan 22, 2025

提交了一个改进版本 可以测试下

@LonelySally
Copy link
Author

测试了下 确实目前不支持超过2级的带*的多维数组验证场景

.*后缀判断之后需要在对规则做is_array/is_string判断,如果rule是sting类型则不需要再调用checkItem.
错误提示报错是8.x-dev 12ce496丢失了父级key信息,8.1.2是丢失了子级信息.
丢失父级key信息影响较小,至少能知道确切的哪个字段校验不通过.
丢失子级信息直接两眼一黑,所有的错误提示都是父级key.错误,根本无法定位到具体的哪个字段校验失败,只能肉眼一点点排查.

@LonelySally
Copy link
Author

提交了一个改进版本 可以测试下

拉去master后测试正常验证,但是提示依然不对.

<?php

namespace app\test;

use PHPUnit\Framework\TestCase;
use think\App;
use think\exception\ValidateException;
use think\facade\Validate;

class Test extends TestCase
{
    private App $app;

    public function setUp(): void
    {
        $this->app = (new App());
        $this->app->initialize();
        $this->app->debug(true);

    }

    public function testValidate()
    {
        Validate::maker(function ($validate) {
            $validate->extend('list', function ($value, $rule, $data, $field, $title): bool|string {
                if (is_array($value) === false) {
                    return $field . '非有序数组';
                }
                return array_is_list($value) ? true : $field . '非有序数组';
            });
        });

        $rule = [
            'shop_goods' => 'require|list',
            'shop_goods.*' => rules([
                'free_switch' => 'require|in:0,1|integer',
                'measure' => 'list',
                'measure.*' => rules([
                    'split_switch' => 'require|in:0,1|integer',
                    'fit_merchant_uid' => 'require|list',
                    'fit_merchant_uid.*' => '>:0',
                ]),
            ]),
        ];

        $data = [
            "shop_goods" => [
                [
                    "free_switch" => 1,//如果将该值修改为3 提示是shop_goods.*必须在 0,1 范围内而非shop_goods.free_switch必须在 0,1
                    "measure" => [
                        [
                            "split_switch" => 1,
                            "fit_merchant_uid" => [
                                -12
                            ]
                        ]
                    ]
                ]
            ]
        ];
        try {
            validate($rule)->check($data);
        } catch (ValidateException $e) {
//预期为 shop_goods.*.measure.*.fit_merchant_uid.*必须大于 0 , 运行后为shop_goods.*必须大于 0
            dump($e->getMessage());
        }
    }
}

@LonelySally
Copy link
Author

LonelySally commented Jan 22, 2025

关于提示需要修改此处Validate.php为可使提示符合预期

 throw new ValidateException(str_replace(substr($result, 0, strspn($result, $name)),$name,$result), $name);

最好详尽测试下 我只做了3层嵌套的测试 @liu21st PR

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants