web-dev-qa-db-ja.com

Laravel別のフィールド配列に値が存在する場合の検証ルール

私はLaravel= 5.4で作業しており、少し具体的な検証ルールが必要ですが、これはクラスを拡張することなく簡単に実行できるはずです。この作業を行う方法がわからないだけです。

program配列に'music_instrument'が含まれている場合、'Music'フォームフィールドを必須にすることをお勧めします。

私はこのスレッドを見つけました laravelの検証で別の複数選択フィールドで値が選択されている場合にrequireを設定する方法 しかし、それは解決策ではありません(最初から解決されなかったため)。機能しないのは、送信された配列インデックスが定数ではないためです(選択されていないチェックボックスは、送信結果のインデックス作成では考慮されません...)

私のケースは次のようになります:

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

考え?提案?

ありがとうございました!

7
GRowing

試したことはありませんが、一般的な配列フィールドでは通常、次のように記述します: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);
16

次のように、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;
        });
}

新しいメソッドの引数としてValidatorを使用するために、CustomValidatorProvider.phpの上部にuseステートメントがあることを確認することを忘れないでください。

...

use Illuminate\Validation\Validator;

次に、CustomValidatorProvider.phpのboot()メソッドで、新しいプライベートメソッドを呼び出します。

public function boot()
{
    ...

    $this->required_if_array_contains();
}

次に、Laravelを教えて、resources/lang/en/validation.phpの配列に新しい項目を追加することにより、人にわかりやすい方法で検証メッセージを書き込みます。

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-otherother-mamalまたはother-reptile値がチェックされている場合にのみ必要なテキスト入力です。

これは、複数選択が有効になっている選択入力、またはリクエストの入力の1つに値の配列が生成される入力でも機能します。

3
Martin Joiner

同様の問題に対して私が取ったアプローチは、コントローラークラス内にプライベート関数を作成し、3項式を使用して必要なフィールドが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;
}

この関数を使用すると、他のプログラムに他のフィールドもある場合、同じロジックを適用できます。

次に、ストア関数で:

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
}
2
brent_aof