12日1732-修复Matchexchange AddHandler验证错误.md 4.5 KB

修复Matchexchange AddHandler验证错误

任务时间: 2025年06月12日 17:32
任务类型: 错误修复
模块: AppGame/Matchexchange

任务概述

根据日志分析,修复了Matchexchange AddHandler中direction字段验证错误的问题。问题源于protobuf枚举字段在JSON序列化时变成字符串,但验证规则期望整数值。

问题分析

1. 错误现象

  • 错误信息:direction必须是大于0的整数
  • 请求数据:{"itemId":"2","price":0.035,"num":"100","direction":"SELL"}
  • 问题:direction字段传入的是字符串"SELL",但验证规则要求是大于0的整数

2. 根本原因

  • Protobuf序列化问题serializeToJsonString()方法将枚举值序列化为字符串名称而不是数值
  • 验证规则不匹配:验证规则期望direction是整数,但实际接收到字符串
  • Price验证器问题number验证器的min参数类型转换错误

3. MEX_DIRECTION枚举值

const DIRECTION_NONE = 0;  // 全部/未知/默认
const SELL = 1;            // 卖出
const BUY = 2;             // 买入

修复方案

1. 添加数据预处理方法

MatchexchangeAddValidation类中添加beforeValidate()方法:

public function beforeValidate(): bool
{
    // 处理 direction 字段的转换
    $direction = $this->getRaw('direction');
    if (is_string($direction)) {
        // 将字符串枚举名转换为对应的整数值
        $directionValue = match(strtoupper($direction)) {
            'SELL' => MEX_DIRECTION::SELL,
            'BUY' => MEX_DIRECTION::BUY,
            'DIRECTION_NONE' => MEX_DIRECTION::DIRECTION_NONE,
            default => $direction // 保持原值,让验证器处理
        };
        $this->setRaw('direction', $directionValue);
    }
    
    return true;
}

2. 修复验证规则

  • 移除direction的integer验证:从'user_id,itemId,num,direction'改为'user_id,itemId,num'
  • 修复price验证器:从'number'改为'float',避免min参数类型转换错误
  • 修复min参数格式:从0.00001改为'0.00001'(字符串格式)

3. 验证规则对比

修复前

[
    'user_id,itemId,num,direction', 'integer', 'min' => 1,
    'msg' => '{attr}必须是大于0的整数'
],
[
    'price', 'number', 'min' => 0.00001,
    'msg' => '价格必须是大于0的数字'
],

修复后

[
    'user_id,itemId,num', 'integer', 'min' => 1,
    'msg' => '{attr}必须是大于0的整数'
],
[
    'price', 'float', 'min' => '0.00001',
    'msg' => '价格必须是大于0的数字'
],
[
    'direction', 'in', 'range' => [MEX_DIRECTION::BUY, MEX_DIRECTION::SELL],
    'msg' => '交易方向无效'
],

技术细节

1. Protobuf枚举序列化机制

  • serializeToJsonString()将枚举值序列化为字符串名称
  • 需要在验证前进行数据类型转换

2. 验证器类型问题

  • number验证器内部调用integer验证器
  • integer验证器将min参数强制转换为整数:(int)$min
  • min"0.00001"时,(int)"0.00001"变成0,导致验证失败

3. 数据转换流程

  1. 接收数据{"direction":"SELL"}
  2. 预处理转换"SELL"1
  3. 验证通过direction值为整数1,符合验证规则

验证结果

1. 修复前错误

direction必须是大于0的整数

2. 修复后结果

价格不能低于 10.5

修复成功!现在已经通过了基础数据类型验证,进入了业务逻辑验证阶段(MexPriceValidator)。

影响范围

  • 修改文件app/Module/AppGame/Validations/MatchexchangeAddValidation.php
  • 影响功能:农贸市场添加挂单功能
  • 风险评估:低风险,仅修复验证逻辑,不影响业务流程

提交信息

修复Matchexchange AddHandler的direction字段验证错误

- 问题:protobuf枚举字段direction在JSON序列化时变成字符串,但验证规则期望整数
- 修复:添加beforeValidate方法将字符串枚举名转换为对应的整数值
- 修复:将price字段验证器从number改为float,避免min参数类型转换错误
- 测试:使用php artisan debug:reproduce-error验证修复有效

总结

通过分析日志和源码,成功定位并修复了protobuf枚举字段验证的问题。这是一个典型的数据类型不匹配问题,通过添加数据预处理逻辑和调整验证规则得到了完美解决。修复后系统能够正确处理protobuf枚举字段,为后续的业务逻辑验证奠定了基础。