【问题标题】:What's the best way to validate numbers with comma as decimal separator?用逗号作为小数分隔符验证数字的最佳方法是什么?
【发布时间】:2013-07-11 19:40:35
【问题描述】:

在 Laravel 应用程序中,我有一个表单,我需要在该表单上使用逗号作为小数分隔符来验证数字。目前,它只适用于一个点,因为我的验证规则是:

$rules = [
    'amount' => 'numeric|min:0',
];

最好的方法是什么:

  • 保留规则并在验证前用点替换逗号?是否有 before_validation 观察者或类似的东西?
  • 建立自定义验证规则?例如 french_numeric ?

【问题讨论】:

    标签: php validation laravel


    【解决方案1】:

    如果其他人在从解决方案进行正则表达式检查后验证输入的数字大小时遇到​​问题,我会在此处发布我的解决方案。我需要它来处理 max 虽然与问题不同,但它可以很容易地适应 min

    我创建了一个新的规则对象,如下所述:https://laravel.com/docs/8.x/validation#using-rule-objects

    注入参数的思路来源于这个答案:https://stackoverflow.com/a/62384976/11854580

    toFloat 方法是用户对https://www.php.net/manual/en/function.floatval.php的贡献

    <?php
    
    namespace App\Rules;
    
    use App\Utils\NumberUtils;
    use Illuminate\Contracts\Validation\Rule;
    
    class NumericMaxForString implements Rule
    {
        private $maxValue;
    
        /**
         * Create a new rule instance.
         *
         * @return void
         */
        public function __construct($maxValue)
        {
            $this->maxValue = $maxValue;
        }
    
        /**
         * Determine if the validation rule passes.
         *
         * @param  string  $attribute
         * @param  mixed  $value
         * @return bool
         */
        public function passes($attribute, $value)
        {
            $numericValue = NumberUtils::toFloat($value);
            return $numericValue <= $this->maxValue;
        }
    
        /**
         * Get the validation error message.
         *
         * @return string
         */
        public function message()
        {
            return 'The :attribute may not be greater than ' . $this->maxValue . '.';
        }
    }
    

    【讨论】:

      【解决方案2】:

      在 The Alpha 的出色答案的基础上,这里有一个代码 sn-p 可配置浮动验证。

      将此 sn-p 添加到 AppServiceProvider 类中的 boot() 函数中(使用 Laravel 5.4 测试):

      Validator::extend('float', function ($attribute, $value, $parameters, $validator) {
          $thousandsSeparator = env('APP_NUMBER_THOUSANDS_SEPARATOR') == '.' ? '\\' . env('APP_NUMBER_THOUSANDS_SEPARATOR') : env('APP_NUMBER_THOUSANDS_SEPARATOR');
          $commaSeparator = env('APP_NUMBER_COMMA_SEPARATOR') == '.' ? '\\' . env('APP_NUMBER_COMMA_SEPARATOR') : env('APP_NUMBER_COMMA_SEPARATOR');
          $regex = '~^[0-9]{1,3}(' . $thousandsSeparator . '[0-9]{3})*' . $commaSeparator . '[0-9]+$~';
          $validate = preg_match($regex, $value);
      
          if ($validate === 1) {
              return true;
          }
      
          return false;
      });
      

      您的 .env 文件将包含这两行:

      APP_NUMBER_COMMA_SEPARATOR="."
      APP_NUMBER_THOUSANDS_SEPARATOR=","
      

      您的规则如下所示:

      $rules = [
          'amount' => 'float|min:0',
      ];
      

      注意:我只是正确地转义了.。如果您要使用在正则表达式语法中具有特殊含义的字符(如 * 或 +),您也必须转义它们。

      但由于像550*345,00 (550,345.00)57+44 (57.44) 这样的浮点数 没有意义,所以我忽略了这个问题。

      亲切的问候

      【讨论】:

      • 最小规则将评估您的解决方案中的字符数,还是我遗漏了什么?
      【解决方案3】:

      Laravel 在验证规则中支持 regex 模式,因此您可以使用给定的模式来匹配 12,365.00 之类的内容,并且建议在使用正则表达式作为规则时使用数组而不是管道

      $rules = array('amount' => array('match:/^[0-9]{1,3}(,[0-9]{3})*\.[0-9]+$/'));
      

      Check this link. 另外,如果您出于任何原因想要删除逗号,请使用check this answer

      【讨论】:

      • 这个怎么用?缺乏答案,因为它给了我Method [validateMatch] does not exist.
      • @StormSpirit:将match 替换为regex,它应该可以工作。
      • 更新:以下也将匹配负数:'regex:/^-?[0-9]{1,3}(,[0-9]{3})*\. [0-9]+$/' 即 10 和 -10 都将被验证。
      • 但是在使用正则表达式时不能正确使用 min 规则,因为它会采用字符数而不是数值。这对我来说是个问题。有谁知道解决办法吗?
      • 我创建了一个自定义规则作为数字大小验证的解决方案。请参阅下面的答案。
      猜你喜欢
      • 2011-05-18
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      相关资源
      最近更新 更多