如果值存在于另一个字段数组中,则 Laravel 验证规则

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43147584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:41:57  来源:igfitidea点击:

Laravel Validation Rules If Value Exists in Another Field Array

phplaravellaravel-5laravel-5.4laravel-validation

提问by GRowing

I am working in Laravel 5.4 and I have a slightly specific validation rules need but I think this should be easily doable without having to extend the class. Just not sure how to make this work..

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

What I would like to do is to make the 'music_instrument'form field mandatory if programarray contains 'Music'.

我想这样做是为了使'music_instrument'表单字段强制性的,如果program数组包含'Music'

I found this thread How to set require if value is chosen in another multiple choice field in validation of laravel?but it is not a solution (because it never got resolved in the first place) and the reason it doesn't work is because the submitted array indexes aren't constant (not selected check boxes aren't considered in indexing the submission result...)

我发现这个线程如何设置要求如果在验证 laravel 的另一个多选字段中选择了值?但这不是一个解决方案(因为它首先从未得到解决)并且它不起作用的原因是因为提交的数组索引不是恒定的(在索引提交结果时不考虑未选中的复选框。 ..)

My case looks like this:

我的情况是这样的:

<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>

If I select some of the options from the list of check boxes I can potentially have this result in my $requestvalues

如果我从复选框列表中选择一些选项,我可能会在我的$request值中得到这个结果

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

[music_instrument] => 'Guitar'

Looking at validation rules here: https://laravel.com/docs/5.4/validation#available-validation-rulesI think something like his should work but i am literally getting nothing:

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

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

I was hoping this would work too but no luck:

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

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

Thoughts? Suggestions?

想法?建议?

Thank you!

谢谢!

回答by Marcin Nabia?ek

Haven't tried that, but in general array fields you usually write like this: program.*, so maybe something like this will work:

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

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

If it won't work, obviously you can do it also in the other way for example like this:

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

$rules = ['program' => 'required'];

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

$validator = Validator::make($request->all(), $rules);

回答by Martin Joiner

You could create a new custom rule called required_if_array_containslike this...

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

In app/Providers/CustomValidatorProvider.php add a new private function:

在 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;
        });
}

And don't forget to check there is a usestatement at the top of CustomValidatorProvider.php for our use of Validator as an argument in our new method:

并且不要忘记检查useCustomValidatorProvider.php 顶部的声明,用于我们在新方法中使用 Validator 作为参数:

...

use Illuminate\Validation\Validator;

Then in the boot() method of CustomValidatorProvider.php call your new private method:

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

public function boot()
{
    ...

    $this->required_if_array_contains();
}

Then teach Laravel to write the validation message in a human-friendly way by adding a new item to the array in resources/lang/en/validation.php:

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

return [
    ...

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

Now you can write validation rules like this:

现在您可以编写如下验证规则:

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

In the above example, animalsis a group of checkboxes and animals-otheris a text input that is only required if the other-mamalor other-reptilevalue has been checked.

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

This would also work for a select input with multiple selection enabled or any input that results in an array of values in one of the inputs in the request.

这也适用于启用了多项选择的选择输入或导致请求中的一个输入中的值数组的任何输入。

回答by brent_aof

The approach I took for a similar problem was to make a private function inside my Controller class and use a ternary expression to add the required field if it came back true.

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

I have roughly 20 fields that have a checkbox to enable the input fields in this case, so it may be overkill in comparison, but as your needs grow, it could prove helpful.

在这种情况下,我有大约 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;
}

Using this function, you can apply the same logic if you have other fields for your other programs as well.

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

Then in the store function:

然后在 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
}