15

I have a form with a series of numbers in an array:

<input type="number" name="items[{{ $sku }}]" min="0" />
<input type="number" name="items[{{ $sku }}]" min="0" />
<input type="number" name="items[{{ $sku }}]" min="0" />

I would like to validate that there is at least one of those input fields that has a value.

I tried the following in my OrderCreateRequest, yet the test is passing:

return [
    'items' => 'required|array|min:1'
];

Am I missing something?

LinkChef
  • 196
  • 2
  • 12
Miguel Stevens
  • 8,631
  • 18
  • 66
  • 125

9 Answers9

17

I think you need a custom validation rule like the following because min is not for the elements of the array.

Validator::extend('check_array', function ($attribute, $value, $parameters, $validator) {
     return count(array_filter($value, function($var) use ($parameters) { return ( $var && $var >= $parameters[0]); }));
});

You can create ValidatorServiceProvider and you can add these lines to boot method of ValidatorServiceProvider. Then you need to add Provider to your providers array in config/app.php.

App\Providers\ValidatorServiceProvider::class,

Or you just add them top of the action of your controller.

At the end you can use it like this in your validation rules.

'items' => 'check_array:1',

Note: if I understand you correctly it works.

Hakan SONMEZ
  • 2,176
  • 2
  • 21
  • 32
  • Great solution! Thank you. – Miguel Stevens Aug 21 '17 at 17:34
  • 1
    dont forget to add `'check_array' => 'at least one item is required',` to `langs/*/validation.php` – ctf0 May 01 '19 at 19:13
  • for some reason this now always return `0` check http://sandbox.onlinephpfunctions.com/code/7781961e4dd2aee88a4e873d52c8f2a4c994932b – ctf0 Jul 18 '19 at 14:36
  • Your code has some logical errors. so you should try like this http://sandbox.onlinephpfunctions.com/code/d0447c13a3a166373dd0ff18b300f7bb5b7272b8 – Hakan SONMEZ Jul 18 '19 at 15:35
  • The string value of a date 01/08/2021 fails the validator (php 7.4.8) since the parameter is a string and the slash breaks the behavior, I would use `!empty($var)` instead – Broshi Jul 26 '21 at 08:06
11

In addition ot Hakan SONMEZ's answer, to check if at least one array element is set, the Rule object can be used. For example create rule class and name it ArrayAtLeastOneRequired().

To create new rule class run console command:

php artisan make:rule ArrayAtLeastOneRequired

Then in created class edit method passes():

public function passes($attribute, $value)
    {
        foreach ($value as $arrayElement) {
            if (null !== $arrayElement) {
                return true;
            }
        }

        return false;
    }

Use this rule to check if at least one element of array is not null:

Validator::make($request->all(), [
  'array' => [new ArrayAtLeastOneRequired()],
 ]);
Jakhongir
  • 586
  • 8
  • 11
  • 1
    Great answer! Please note the validation rule should be applied to the array `'array'` and not to the array element `'array.*'` otherwise the foreach loop won't be able to iterate . – LobsterBaz Apr 24 '21 at 01:13
  • This is precisely what I was looking for. Thank you! – JasonJensenDev Feb 16 '23 at 20:35
5

If you are using this in your controller file then I guess it should be

$this->validate($request, [
    'items' => 'required|min:1'
]);

or this one

$validator = Validator::make($request->all(), [
    "items.*" => 'required|min:1',
]);

you can refer How to validate array in Laravel? to this as well.

linktoahref
  • 7,812
  • 3
  • 29
  • 51
Umer
  • 142
  • 9
  • 1
    second example with `items.*` will check that all values in items array should have at-least 1 character in it, but here we have to validate to minimum 1 element should be there in array so, first example is right but second one is wrong because it will check values. – Haritsinh Gohil Jul 25 '19 at 07:17
  • First example is wrong as well because it would pass an array with a single null value. This answer doesn't address the question and shouldn't be upvoted. – LobsterBaz Apr 24 '21 at 00:47
  • Not correct . i tried it – mercury Apr 04 '22 at 23:44
4

The accepted answer is ok, and it is working fine, but if you don't want to create function and other stuff then the another workaround which i have used is

that you can directly state the element of array as items.0 and make that input required, it will not care about other inputs but it will make first input required, it is not usable in all the cases but in my case it is useful.

in your OrderCreateRequest:

public function rules()
{
   return [
       "items.0" => "required",
   ];
}

And if your items are not dynamic and not in very large amount then you can use required_without_all as below:

public function rules()
{
   return [
       "items.0" => "required_without_all:items.1,items.2",
       "items.1" => "required_without_all:items.0,items.2",
       "items.2" => "required_without_all:items.0,items.1",
   ];
}
Haritsinh Gohil
  • 5,818
  • 48
  • 50
-1

"size" rule is used to match exact no. of items in array (if incoming parameter is an array) and same goes for "min" rule i.e it count minimum no. of elements in an array (if incoming parameter is an array)

$this->validate($request, ['my_array' => 'size:6']); // array must have 6 items

$this->validate($request, ['my_array' => 'min:1']); // there must be 1 item in array

https://laravel.com/docs/8.x/validation#rule-size

Naveed Ali
  • 361
  • 3
  • 12
-2

You can set your rules for array and foreach elements.

public function rulez(Request $req) {
        $v = Validator::make($req->all(), [
            'items'   => 'required|array|min:1',
            'items.*' => 'required|integer|between:0,10'

        ]);

        if ($v->fails())
            return $v->errors()->all();
}

First rule say that items must be an array with 1 element at least. Second rule say that each elements of items must be an integer between 0 and 10.

If the rules seem not to work, try to dump your $req->all().

dump($req->all());
Gragio
  • 17
  • 2
  • 3
-2
'items'   => 'required|array', // validate that field must be from array type and at least has one value
'items.*' => 'integer' // validate that every element in that array must be from integer type

and you can add any other validation rules for those elements like: 'items.*' => 'integer|min:0|max:100'

Omar
  • 203
  • 3
  • 5
  • the `min` attribute has nothing to do with the count items, instead it checks the value itself – behz4d Feb 20 '19 at 08:39
  • @behz4d and that what i meant to check the elements. `*` here it means apply the rules on every element in this array. not checking the count – Omar Feb 21 '19 at 13:55
-2
$valid = Validator($request->all(), [
    'type' => 'required|string|in:city,region,country',
]);

if ($valid->fails()) return response()->json($valid->errors(), 400);
Buddy
  • 10,874
  • 5
  • 41
  • 58
-3
$this->validate($request,[
'item'=>'required|min:1'

]);
Kuldeep Mishra
  • 3,846
  • 1
  • 21
  • 26