【问题标题】:Laravel Validation Rules If Value Exists in Another Field Array如果值存在于另一个字段数组中,Laravel 验证规则
【发布时间】:2017-08-26 03:11:26
【问题描述】:

我在 Laravel 5.4 中工作,我需要稍微具体的验证规则,但我认为这应该很容易实现,而无需扩展类。只是不知道如何使这项工作..

如果program 数组包含'Music',我想做的是强制'music_instrument' 表单字段。

我找到了这个线程How to set require if value is chosen in another multiple choice field in validation of laravel?,但这不是一个解决方案(因为它一开始就没有得到解决),它不起作用的原因是提交的数组索引不是恒定的(未选中复选框在索引提交结果时不考虑...)

我的情况是这样的:

<form action="" method="post">
    <fieldset>

        <input name="program[]" value="Anthropology" type="checkbox">Anthropology
        <input name="program[]" value="Biology"      type="checkbox">Biology
        <input name="program[]" value="Chemistry"    type="checkbox">Chemistry
        <input name="program[]" value="Music"        type="checkbox">Music
        <input name="program[]" value="Philosophy"   type="checkbox">Philosophy
        <input name="program[]" value="Zombies"      type="checkbox">Zombies

        <input name="music_instrument" type="text" value"">

        <button type="submit">Submit</button>

    </fieldset>
</form>

如果我从复选框列表中选择一些选项,我的 $request 值中可能会出现此结果

[program] => Array
    (
        [0] => Anthropology
        [1] => Biology
        [2] => Music
        [3] => Philosophy
    )

[music_instrument] => 'Guitar'

在这里查看验证规则:https://laravel.com/docs/5.4/validation#available-validation-rules 我认为像他这样的东西应该可以工作,但我实际上什么也没得到:

  $validator = Validator::make($request->all(),[
        'program'           => 'required',
        'music_instrument'  => 'required_if:program,in:Music'
  ]);

我希望这也能奏效,但没有运气:

'music_instrument'  => 'required_if:program,in_array:Music',

想法?有什么建议吗?

谢谢!

【问题讨论】:

    标签: php laravel laravel-5 laravel-5.4 laravel-validation


    【解决方案1】:

    我知道这篇文章较旧,但如果有人再次遇到此问题。

    $validator = Validator::make($request->all(),[
        'program' => 'required',
        'music_instrument'  => 'required_if:program,Music,other values'
    ]);
    

    【讨论】:

      【解决方案2】:

      这是我使用 Laravel 6 验证规则解决此类问题的一段代码

      我尝试使用上面的代码

      public function rules() 
      {
          return [
            "some_array_field.*" => ["required", "integer", "in:1,2,4,5"],
            "another_field" => ["nullable", "required_if:operacao.*,in:1"],
          ];
      }
      

      我需要当 some_array_field 的值为 1 时,必须验证 another_field,否则,可以为空。 使用上面的代码,即使使用 required_if:operacao.*,1

      也不起作用

      如果我将 another_field 的规则更改为 required_if:operacao.0,1 WORKS 但仅当要查找的值在索引 0 中时,当订单更改时,验证将失败。

      所以,我决定使用自定义闭包函数

      这是我的示例的最终代码。

      public function rules() 
      {
          return [
            "some_array_field.*" => ["required", "integer", "in:1,2,4,5"],
            "another_field" => [
                "nullable",
                Rule::requiredIf (
                    function () {
                        return in_array(1, (array)$this->request->get("some_array_field"));
                    }
                ),
              ]
          ];
      }
      

      希望也能解决你的烦恼!

      【讨论】:

        【解决方案3】:

        您可以像这样创建一个名为 required_if_array_contains 的新自定义规则...

        在 app/Providers/CustomValidatorProvider.php 添加一个新的私有函数:

        /**
         * A version of required_if that works for groups of checkboxes and multi-selects
         */
        private function required_if_array_contains(): void
        {
            $this->app['validator']->extend('required_if_array_contains',
                function ($attribute, $value, $parameters, Validator $validator){
        
                    // The first item in the array of parameters is the field that we take the value from
                    $valueField = array_shift($parameters);
        
                    $valueFieldValues = Input::get($valueField);
        
                    if (is_null($valueFieldValues)) {
                        return true;
                    }
        
                    foreach ($parameters as $parameter) {
                        if (in_array($parameter, $valueFieldValues) && strlen(trim($value)) == 0) {
                            // As soon as we find one of the parameters has been selected, we reject if field is empty
        
                            $validator->addReplacer('required_if_array_contains', function($message) use ($parameter) {
                                return str_replace(':value', $parameter, $message);
                            });
        
                            return false;
                        }
                    }
        
                    // If we've managed to get this far, none of the parameters were selected so it must be valid
                    return true;
                });
        }
        

        不要忘记检查 CustomValidatorProvider.php 顶部是否有 use 语句,以便我们在新方法中使用 Validator 作为参数:

        ...
        
        use Illuminate\Validation\Validator;
        

        然后在 CustomValidatorProvider.php 的 boot() 方法中调用你的新私有方法:

        public function boot()
        {
            ...
        
            $this->required_if_array_contains();
        }
        

        然后通过在 resources/lang/en/validation.php 中的数组中添加一个新项来教 Laravel 以人性化的方式编写验证消息:

        return [
            ...
        
            'required_if_array_contains' => ':attribute must be provided when &quot;:value&quot; is selected.',
        ]
        

        现在你可以像这样编写验证规则:

        public function rules()
        {
            return [
                "animals": "required",
                "animals-other": "required_if_array_contains:animals,other-mamal,other-reptile",
            ];
        }
        

        在上面的示例中,animals 是一组复选框,animals-other 是一个文本输入,仅在选中 other-mamalother-reptile 值时才需要。

        这也适用于启用了多项选择的选择输入,或者任何在请求中的一个输入中产生一组值的输入。

        【讨论】:

          【解决方案4】:

          我针对类似问题采取的方法是在我的 Controller 类中创建一个私有函数,并在返回 true 时使用三元表达式添加所需字段。

          在这种情况下,我有大约 20 个带有复选框以启用输入字段的字段,因此相比之下它可能有点过分,但随着您的需求增长,它可能会有所帮助。

          /**
           * Check if the parameterized value is in the submitted list of programs
           *  
           * @param Request $request
           * @param string $value
           */
          private function _checkProgram(Request $request, string $value)
          {
              if ($request->has('program')) {
                  return in_array($value, $request->input('program'));
              }
          
              return false;
          }
          

          使用此功能,如果您的其他程序也有其他字段,则可以应用相同的逻辑。

          然后在store函数中:

          public function store(Request $request)
          {
              $this->validate(request(), [
              // ... your other validation here
              'music_instrument'  => ''.($this->_checkProgram($request, 'music') ? 'required' : '').'',
              // or if you have some other validation like max value, just remember to add the |-delimiter:
              'music_instrument'  => 'max:64'.($this->_checkProgram($request, 'music') ? '|required' : '').'',
              ]);
          
              // rest of your store function
          }
          

          【讨论】:

          • 这是个好主意!谢谢
          【解决方案5】:

          没有尝试过,但在一般数组字段中,您通常会这样写:program.*,所以也许这样的东西会起作用:

            $validator = Validator::make($request->all(),[
                  'program'           => 'required',
                  'music_instrument'  => 'required_if:program.*,in:Music'
            ]);
          

          如果它不起作用,显然你也可以用其他方式来做,例如这样:

          $rules = ['program' => 'required'];
          
          if (in_array('Music', $request->input('program', []))) {
              $rules['music_instrument'] = 'required';
          }
          
          $validator = Validator::make($request->all(), $rules);
          

          【讨论】:

          • 我尝试了星号,但它被忽略了。我能够让它与 required_if:program.34,Music,, 一起使用,但为此我必须索引我的列表并跟踪 34,这显然不是一个好主意......我也会尝试这种方法。谢谢。我希望 laravel 的 in_array 能工作,但没有运气
          • 我会接受你的第二个解决方案,因为这就是我的方式:) 谢谢!为了争论,如果其他人想出一个开箱即用的工作配置,我仍然希望看到它......呵呵
          猜你喜欢
          • 2017-06-07
          • 2020-01-24
          • 1970-01-01
          • 1970-01-01
          • 2021-10-24
          • 2015-07-09
          • 1970-01-01
          • 2016-01-11
          • 2022-01-14
          相关资源
          最近更新 更多