【问题标题】:Laravel: validate an integer field that needs to be greater than anotherLaravel:验证需要大于另一个的整数字段
【发布时间】:2015-11-09 07:01:46
【问题描述】:

我有两个字段是可选的,仅当两者都不存在时:

$rules = [
  'initial_page' => 'required_with:end_page|integer|min:1|digits_between: 1,5',
  'end_page' => 'required_with:initial_page|integer|min:2|digits_between:1,5'
]; 

现在,end_page 需要大于 initial_page。如何包含此过滤器?

【问题讨论】:

    标签: php laravel laravel-5


    【解决方案1】:

    没有内置验证可以让你比较像 Laravel 中的字段值,所以你需要实现一个自定义验证器,这将让您在需要时重用验证。幸运的是,Laravel 让编写自定义验证器真的很容易

    首先在你的AppServiceProvider中定义新的验证器:

    class AppServiceProvider extends ServiceProvider
    {
      public function boot()
      {
        Validator::extend('greater_than_field', function($attribute, $value, $parameters, $validator) {
          $min_field = $parameters[0];
          $data = $validator->getData();
          $min_value = $data[$min_field];
          return $value > $min_value;
        });   
    
        Validator::replacer('greater_than_field', function($message, $attribute, $rule, $parameters) {
          return str_replace(':field', $parameters[0], $message);
        });
      }
    }
    

    现在您可以在 $rules 中使用全新的验证规则:

    $rules = [
      'initial_page' => 'required_with:end_page|integer|min:1|digits_between: 1,5',
      'end_page' => 'required_with:initial_page|integer|greater_than_field:initial_page|digits_between:1,5'
    ]; 
    

    您可以在此处找到有关创建自定义验证器的更多信息:http://laravel.com/docs/5.1/validation#custom-validation-rules。它们很容易定义,然后可以在您验证数据的任何地方使用。

    【讨论】:

    • 谢谢,我按照你说的实现了,并尝试在Custom Validation Language Lines 中使用以下消息"greater_than_field" => "Field \":attribute\" must be greater than \":field\".", 编辑我的en/validation.php,但我不知道用什么替换:field
    • 我更新了答案 - 您需要定义替换器,它将用正确的值替换消息占位符。我没有测试过,我只是从文档laravel.com/docs/5.1/validation#custom-validation-rules 中获取的。让我知道它是否有效:)
    • 同时,我更改了我的表单,将数组语法用于字段名称,例如 category[id],而不仅仅是 id。当我尝试使用"category.secondnumber" => "greater_than_field:category.firstnumber" 时出现错误:Undefined index: category.firstnumber。将此语法与after 一起使用是可行的,所以我猜语法没问题,但验证器不完整。提前致谢。解决这个问题后我会实现replacer并报告。
    • @Sliq, @4ndro1d:它在 L5.2 中运行良好。我在App\Providers\CustomValidationServiceProvider.php 创建了自己的提供程序,并将其注册到config\app.php,如下所示:App\Providers\CustomValidationServiceProvider::class, 否则,我只是将他的答案复制并粘贴到boot() 函数中,它完美地工作。
    • 有人找出 :field 替换部件吗?上面的代码确实将 :field 替换为我的字段名称,但我想要“友好”的字段名称。即使替换字段名在validation.php的attributes数组中,仍然没有被使用。
    【解决方案2】:

    这个问题是在 2015 年提出的,所以大多数答案现在在 2019 年也已经过时了

    我想给出使用 laravel 团队提供的功能的答案,这些功能包含在它的新版本中,

    正如@Sarpadoruk 所说,从 laravel 5.6 开始,laravel 在验证中添加了一些功能,例如 gt,gte,ltlte 表示:

    • gt - 大于
    • gte - 大于等于
    • lt - 小于
    • lte - 小于等于

    所以使用gt,您可以检查您的 end_page 是否应该大于您的 initial_page 并且您的任务现在变得非常容易:

    $rules = [
      'initial_page' => 'required_with:end_page|integer|min:1|digits_between: 1,5',
      'end_page' => 'required_with:initial_page|integer|gt:initial_page|digits_between:1,5'
    ]; 
    

    【讨论】:

      【解决方案3】:

      对于 Laravel 5.4,它将是:

      $rules = ['end_page'=>'min:'.(int)$request->initial_page]
      

      【讨论】:

      • 正如@sobhan 建议的那样,$this 可能有效,但重要的是要提到它在很大程度上取决于上下文。例如,$this 在表单请求中可用作 Request 实例。对于控制器,您必须按照之前的答案和 cmets 中所述直接访问请求。
      • 像这样重新注入一部分不受信任的输入真的可以吗?这看起来像是对各种漏洞的潜在邀请......
      • @user1643723 没错。在请求之前添加(int) 可以使其安全。谢谢
      【解决方案4】:

      从 Laravel 5.6 开始,添加了 gtgteltlte 规则。

      【讨论】:

        【解决方案5】:

        我觉得你可以试试这样的,

        $init_page = Input::get('initial_page');
        
        $rules = [
            'initial_page' => 'required_with:end_page|integer|min:1|digits_between: 1,5',
            'end_page' => 'required_with:initial_page|integer|min:'. ($init_page+1) .'|digits_between:1,5'
        ]; 
        

        【讨论】:

        • 我的规则在我的模型类中,我不想在那里访问这个变量,但是谢谢:-)
        【解决方案6】:

        为什么不直接定义$min_number = $min + 1 编号并使用验证器min:$min_number,例如:

        $min = intval($data['min_number']) + 1;
        
        return ['max_number'  => 'required|numeric|min:'.$min];
        

        然后您可以返回自定义错误消息以向用户解释错误。

        【讨论】:

          【解决方案7】:

          使用 gt = grater than :value|field

          使用 gte = 大于等于 :value|field

          使用 lt = 小于 :value|field

          使用 lte = 小于等于 :value|field

          在你的情况下是

          gt:initial_page
          

          结果是

          $rules = array(
                'initial_page' => 'required_with:end_page|numeric|min:1|digits_between: 1,5',
                'end_page' => 'required_with:initial_page|numeric|gt:initial_page|min:2|digits_between:1,5'
                );
          

          【讨论】:

            【解决方案8】:

            如果你在 Laravel 5.2 上维护一个项目,那么以下应该为你向后移植当前的 gt 规则:

            class AppServiceProvider extends ServiceProvider
            {
              public function boot()
              {
                Validator::extend('gt', function($attribute, $value, $parameters, $validator) {
                  $min_field = $parameters[0];
                  $data = $validator->getData();
                  $min_value = $data[$min_field];
                  return $value > $min_value;
                });   
            
                Validator::replacer('gt', function($message, $attribute, $rule, $parameters) {
                  return sprintf('%s must be greater than %s', $attribute, $parameters[0]);
                });
              }
            }
            

            然后您可以按照当前文档使用它:

            $rules = [
              'end_page' => 'gt:initial_page'
            ]; 
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-06-17
              • 2017-06-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-08-18
              • 1970-01-01
              • 2017-05-24
              相关资源
              最近更新 更多