12

I have a POST endpoint on my Laravel 5.5 API, I used postman to test my route and here is the problem. I want to send an array of the same kind of object, like this:

[
  { 
   "name":"test",
   "tag":"TEST"
  },
  {
   "name":"test2",
   "tag":"TEST_2"
  }
]

But I can't manage to validate it properly.

in my controller, I have this:

$validator = Validator::make($requests->all(), [
 
   'name' => 'required|string',
   'tag' => 'required|string'
]);

if($validator->fails()) 
   //Warn user for errors 

I also tried with the simple

$this->validate($requests->all() .... )

I tried renaming the rules with '.name' and '*.name' but no success.

I tried replacing $request->all() with $request->input()but no success.

I also tried to loop over it but I get exceptions

foreach($request as $req){

  $validator = Validator::make($req ....) 

  //rest of the code
}

On the other hand, I can retrieve the data like this $datas = $request->all() and store them but there is no validation.

The only solution that seems to be working is naming my array:

{
 "data" : [
      { 
       "name":"test",
       "tag":"TEST"
      },
      {
       "name":"test2",
       "tag":"TEST_2"
      }
    ]
}

And then name the rules with 'data.*.name' but this obliges the API user to parse the array. Let suppose I have an array $array which I want to store, I need to do

$arrayParsed = ['data' => $array]

and call the API with $arrayParsed, which I think is a little redundant.

Is there a better way to handle the problem?

1
  • You need to send data with a key and then validate as you have done in last example. That's the correct way. Commented Sep 14, 2017 at 14:27

3 Answers 3

25

You can try to circumvent the issue by first doing:

$data = [ 'data' => $requests->all() ];

Then you can use the rule you suggested:

$validator = Validator::make($data, [
   'data.*.name' => 'required|string',
   'data.*.' => 'required|string'
]);

Not the most elegant solution but it solves your issue...

Sign up to request clarification or add additional context in comments.

3 Comments

I like this solution but I'm new to APIs, is it better to let the user place the 'data': array or should I do it myself as you suggested? What is the correct way to send an array of objects?
I've worked with APIs that require data to be sent in the request, and I've seen others that don't. It's really up to you how you implement the APIs. Developers will follow your documentation in any case if they want to use the APIs. But the easier to make it, the more likely they will use it.
Found this answer, looks like Lumen is looking for Request object not an array now in 5.6
7

I was able to do this in laravel 6 like the following via App\Http\Requests CustomRequestClass

public function rules()
{
    return [
        '*.name' => 'required',
        '*.tag' => 'required'
    ];
}

Comments

3

The approved answer works if your posting an array, however to take it a step further, I am needing to save multiple arrays. While that approach would work if I make two separate endpoints, what if I want to save everything inside one DB::transaction?

Viola:

POST:

{
"array1": [
    { "key1": "string", "key2": 1 },
    { "key1": "string", key2": 0 }
  ],
"array2": [
    { "key3": "string", "key4": 1 },
    { "key3": "string", "key4": 0 }
  ]
}

SERVER:

$this->validate($request, [
    'array1' => 'present|array',
    'array2' => 'present|array',
    'array1.*.key1' => 'required|string',
    'array1.*.key2' => 'required|integer',
    'array2.*.key3' => 'required|string',
    'array2.*.key4' => 'required|integer'
]);

DB::transaction(function() use($request) {
    foreach($request['array1'] as $x){
        ...do stuff here
    };
});

Note: 'present|array' accepts empty arrays whereas 'required|array' would reject them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.