Laravel validation required_without_all - laravel

Call me stupid, but I can't get it :)
I want to set up validator rule, so it will pass only if one of the two fields is present (adgroup or all_adgroups).
Here is my controller:
$this->validate($request,
[
'new_target_cpa_value' => 'required|numeric',
'adgroups' => 'exists:google.ad_groups,id|required_without_all:all_agroups',
'all_agroups' => 'required_without_all:adgroups'
]
);
dd($request->all());
Here is dd:
"_token" => "aHjluUXPuZpEbglmVt4UePhriGvRWDOjk3OgfF88"
"new_target_cpa_value" => "123"
"adgroups" => array:1 [▶]
"all_agroups" => "1"

Try this:
$this->validate($request,
[
'new_target_cpa_value' => 'required|numeric',
'adgroups' => 'exists:google.ad_groups,id',
'all_agroups' => 'required_unless:adgroups,null'
]
);

Related

Validating Arrays not working in laraval 9

Validating Arrays not working in laraval 9.
Request as follows
array:2 [
0 => array:4 [
"nic" => "908110248V"
"employee_id" => "1"
"request_id" => "2"
"schedule_training_id" => "1"
]
1 => array:4 [
"nic" => "962930898v"
"employee_id" => "2"
"request_id" => "1"
"schedule_training_id" => "1"
]
]
validator code snipit as follows
$validator = Validator::make($request->input('data_attributes'), [
'data_attributes.*.nic' => 'required|max:9'
]);
$validator = Validator::make($request->input('data_attributes'), [
'*.nic' => 'required|max:9'
]);
You should check the matrix as a whole and then start working with its elements, this is an example of what you should do:
$validator = Validator::make($request->input('data_attributes'), [
"data_attributes" => "required|array|min:3",
"data_attributes.*" => "required|string|distinct|min:3",
]);

How to set required_if in laravel 7

I have two textboxes color_name[] and color_code[],
How to put required_if? If the color code is not empty, the color name is required.
'color_name' => 'required_if:color_code',
error
Validation rule required_if requires at least 2 parameters.
$validator = Validator::make($request->all(), [
'color_name' => 'required_with:color_code',
]);
if ($validator->fails()) {
return $validator->errors()->first();
}
Use this to solve the problem.
For array please re shape your array into this
array:2 [
0 => array:2 [
"color_name" => "red"
"color_code" => "#77"
]
1 => array:2 [
"color_name" => "blue"
"color_code" => "#88"
]
]
$validator = Validator::make($request->all(), [
'color'=>'array',
'color.*.color_name' => 'required_with:color.*.color_code',
]);

Create a collection given a number of times keeping the key

I'm trying to create a kind of dataset using laravel Collections, for this I'm using the "times" method:
function getValidData(int $amount): Collection
{
return Collection::times($amount, function (int $number): array {
$password = faker()->password(8, 12);
return [
"User #{$number}" => [
'name' => faker()->firstName(),
'email' => faker()->unique()->safeEmail(),
'password' => $password,
'password_confirmation' => $password
]
];
});
}
However, the result is not as I expected:
[
0 => [
'User #1' => [
'name' => 'ana',
'email' => 'ana#email.com',
'password' => '12345678',
'password_confirmation' => '12345678'
]
],
1 => [
'User #2' => [
'name' => 'leo',
'email' => 'leo#email.com',
'password' => '3231232132',
'password_confirmation' => '3231232132'
]
]
]
I was hoping it would be:
[
'User #1' => [
'name' => 'ana',
'email' => 'ana#email.com',
'password' => '12345678',
'password_confirmation' => '12345678'
],
'User #2' => [
'name' => 'leo',
'email' => 'leo#email.com',
'password' => '3231232132',
'password_confirmation' => '3231232132'
]
]
I can solve this using array_merge(...(Collection::times...)) but it seems a kinda off... Is there any way to solve this in a cleaner way using Collections?
If you would like to map the collection with new keys, you could do the following, using the mapWithKeys() function.
Example
$users = collect(range(1, $amount))
->mapWithKeys( function($index) {
$password = faker()->password(8, 12);
return [sprintf("User #%d", $index) => [
'name' => faker()->firstName(),
'email' => faker()->unique()->safeEmail(),
'password' => $password,
'password_confirmation' => $password,
]];
});
This will run from 1 to the specified $amount. Example output with 3 users:
Illuminate\Support\Collection {#2016
#items: array:3 [
"User #1" => array:4 [
"name" => "Garret"
"email" => "aurelio03#example.com"
"password" => "Vp=Et3!?w0"
"password_confirmation" => "Vp=Et3!?w0"
]
"User #2" => array:4 [
"name" => "Genoveva"
"email" => "hilda.bins#example.net"
"password" => "W?miL1Kts"
"password_confirmation" => "W?miL1Kts"
]
"User #3" => array:4 [
"name" => "Zella"
"email" => "mmurray#example.net"
"password" => "g8)"pYgjQ~"
"password_confirmation" => "g8)"pYgjQ~"
]
]
}
You could also chain the toArray() method on the collection if you prefer an Array over a Collection.

Proper formatting of a JSON and multiplepart Guzzle post request

I have two different Guzzle post requests that I am trying to merge (solely because they basically do a united job and should be performed together).
Initially I have my donation data:
'donation' => [
'web_id' => $donation->web_id,
'amount' => $donation->amount,
'type' => $donation->type,
'date' => $donation->date->format('Y-m-d'),
'collection_id' => NULL,
'status_id' => $donation->status_id,
],
And then I have my files that go with it, which are basically two different PDFs that are enabled or disabled for donors, sometimes they have both. I know the multipart would look something like below, but I'm not sure.
foreach ($uploadDocs as $doc) {
'multipart' => [
[
'name' => 'donation_id',
'contents' => $donation->web_id,
],
[
'name' => 'type_id',
'contents' => $doc->type_id',
],
[
'name' => 'file',
'contents' => fopen($doc->path, 'r'),
'headers' => ['Content-Type' => 'application/pdf'],
],
],
}
Since I've usually only handled one file at a time and I'm not sure how to merge the first block of code with the second for an appropriate Guzzle post request.
You can try this:
$donationData = [
'web_id' => $donation->web_id,
'amount' => $donation->amount,
'type' => $donation->type,
'date' => $donation->date->format('Y-m-d'),
'collection_id' => NULL,
'status_id' => $donation->status_id,
];
$multipart = [];
foreach ($uploadDocs as $doc) {
$multipart[] = [
[
'name' => 'donation_id',
'contents' => $donation->web_id,
],
[
'name' => 'type_id',
'contents' => $doc->type_id,
],
[
'name' => 'file',
'contents' => fopen($doc->path, 'r'),
'headers' => ['Content-Type' => 'application/pdf'],
],
];
}
Than perform your request:
$r = $client->request('POST', 'http://example.com', [
'body' => $donationData,
'multipart' => $multipart,
]);

Laravel 5.6 Validation Array Data

When validating a request data, we are getting the result filtered out by the rules. For example, the following request:
$this->post(route('test'), [
'foo' => 'bar',
'john' => 'doe'
]);
And in my controller, I have the following:
$data = request()->validate([
'foo' => 'required|string'
]);
Then if I perform a dd($data);, I would get the following:
array:1 [
"foo" => "bar"
]
So far so good. However, when working with arrays, for example, the following request:
$this->post(route('test'), [
'foo' => 'bar',
'names' => [
'en' => 'Product',
'fr' => 'Produit',
'john' => 'Doe'
]
]);
And then in my controller, I have the following:
$data = request()->validate([
'foo' => 'required|string',
'names' => 'array',
'names.en' => 'required|string',
'names.fr' => 'required|string'
]);
It would return the following $data:
array:2 [
"foo" => "bar"
"names" => array:3 [
"en" => "Product"
"fr" => "Produit"
"john" => "doe"
]
]
Now my questions are:
Why is 'john' => 'doe' in my names key when I don't have it in my validation rules?
Is there a way to remove unspecified array keys from the data?
Update
I've tested the suggestion of #JonasStaudenmeir, however the result is not what I expected.
Request:
$this->post(route('test'), [
'names' => [
'en' => 'Doe',
'fr' => 'John'
]
]);
Controller:
$rules = [
'names' => 'array',
'names.en' => 'string'
];
dd(request()->only(array_keys($rules));
Expected Output:
array:1 [
"names" => array:2 [
"en" => "Doe"
]
]
Actual Output:
array:1 [
"names" => array:2 [
"fr" => "John"
"en" => "Doe"
]
]
For cases with only nested rules ('names.en') but no parent rule ('names'),
this will be fixed in 5.7: https://github.com/laravel/framework/pull/23708
Until then you can use this workaround:
$data = request()->only(array_keys($rules));
If you do you have a parent rule, this would be much more complicated to achieve.
I would argue that receiving the whole 'names' array in the validated data can be seen as the expected behavior. The idea is that the validator returns the data for each rule. In your case it returns the data for the 'names' => 'array' rule, which is the whole 'names' array.

Resources