Using validated method with array in Laravel - arrays

This is the rquest body:
{
"arr": [
{
"a": 3,
"b": 3
},
{
"a": 3,
"b": 3
}
]
}
and with this validations rules:
public function rules()
{
return [
// 'arr' => 'array',
'arr.*.a' => 'required'
];
}
The result of dd($request->validated()); is what I want, I don't need b to be included
"arr" => array:2 [
0 => array:1 [
"a" => 3
]
1 => array:1 [
"a" => 3
]
]
But when I want to validate the array itself like this:
public function rules()
{
return [
'arr' => 'array',
'arr.*.a' => 'required'
];
}
b will be added to the output
"arr" => array:2 [
0 => array:1 [
"a" => 3,
"b" => 3
]
1 => array:1 [
"a" => 3,
"b" => 3
]
]
How can I prevent adding b to the dd($request->validated()); while validating the array itself?

Related

convert array to array of object Laravel

my api receive single array of object from client side like following:
[
{
"datetime": "2022-07-19 12:04:03",
"receiptNumber" : "4010",
"isRefund": 0,
"amount" : 1025
},
]
and whem try to validate request at api side checked success and process to database success my issue happen when try to sent multi object inside array like following :
[
{
"datetime": "2022-07-19 12:04:03",
"receiptNumber" : "4010",
"isRefund": 0,
"amount" : 1025
},
{
"datetime": "2022-07-19 12:04:03",
"receiptNumber" : "4009",
"isRefund": 0,
"amount" : 1025
}
]
when i am try to validate first object inside array using foreach like following :
$array = $request->all();
foreach($array as $sdsa){
$this->validate($sdsa, [
'datetime' => 'required|date_format:Y-m-d H:i:s',
'amount' => 'required|numeric',
'isRefund' => 'required|integer|between:0,1',
'receiptNumber' => 'required|string',
]);
}
in this case api return error :
"message": "Argument 1 passed to App\\Http\\Controllers\\Controller::validate() must be an instance of Illuminate\\Http\\Request, array given,
so that i am asking how can convert this format:
array:4 [
"datetime" => "2022-07-19 12:04:03"
"receiptNumber" => "4010"
"isRefund" => 0
"amount" => 1025
]
to
{
array:4 [
"datetime" => "2022-07-19 12:04:03"
"receiptNumber" => "4010"
"isRefund" => 0
"amount" => 1025
]
}
You can use 'json_encode()'.
Example;
$myArray = array("datetime" => "2022-07-19 12:04:03", "receiptNumber" => "4010", "isRefund" => 0, "amount" => 1025);
Output;
[
"datetime" => "2022-07-19 12:04:03",
"receiptNumber" => "4010",
"isRefund" => 0,
"amount" => 1025,
]
Than if you use json_encode like this;
$myArray = json_encode($myArray);
Output;
{
[
"datetime" => "2022-07-19 12:04:03",
"receiptNumber" => "4010",
"isRefund" => 0,
"amount" => 1025,
]
}
You need to use
Validator::make($sdsa, [
'datetime' => 'required|date_format:Y-m-d H:i:s',
'amount' => 'required|numeric',
'isRefund' => 'required|integer|between:0,1',
'receiptNumber' => 'required|string',
])->validate()

Build a custom array in Laravel

I am looping the database to get a list of countries with continents.
array: [
0 => array: [
"country" => "BE"
"continent" => "EU"
1 => array: [
"country" => "BG"
"continent" => "EU"
]
...
]
From that result, I want to create an array that shows all the continents with the countries inside.
array:[
0 => array: [
"continent" => "EU"
"countries" => [
"country" => "BE"
"country" => "BG"
]
]
Suppose this is your array
$arr = [
[
"country" => "BE",
"continent" => "EU",
],
[
"country" => "BG",
"continent" => "EU",
]
];
Then this returns what you expected.
collect($arr)->groupBy('continent')->mapWithKeys(function ($group, $continent) {
return [
'continent' => $continent,
'countries' => $group->pluck('country')->toArray()
];
});
If you need just to group countries by continent, simple way to achieve this by mapToGroups() method for collections
$input = [
['country' => 'BE', 'continent' => 'EU'],
['country' => 'BG', 'continent' => 'EU'],
['country' => 'BU', 'continent' => 'AF'],
['country' => 'BY', 'continent' => 'EU'],
];
$grouped = collect($input)
->mapToGroups(fn ($country) => [$country['continent'] => $country['country']])
->toArray(); // if you need array at the end
This will be resulted in
You will need to some how group your results by the continent. One way to do that is to loop over the initial collection and build a new array keyed by the continent.
However, seeing that you are using Laravel just group the collection by the continent.
$countries = [
['country' => 'A', 'continent' => 'aa'],
['country' => 'B', 'continent' => 'bb'],
['country' => 'C', 'continent' => 'aa'],
['country' => 'D', 'continent' => 'aa'],
['country' => 'E', 'continent' => 'aa'],
['country' => 'F', 'continent' => 'bb'],
];
// Because my data is an array I just turn that into a collection.
// But an Eloquent query builder ->get would already return a collection.
$continents = collect($countries)->groupBy('continent');
foreach ($continents as $continent => $items) {
echo "Countries for " . $continent . "\n";
foreach ($items as $country) {
echo $country['country'] . "\n";
}
}
/**
Output:
Countries for aa
A
C
D
E
Countries for bb
B
F
**/

Laravel Multidimensional Array to Collection Object Values

I have an array that I'm wanting to recursively turn into a collection and to use the collection as object values.
I would like to use the collection object in similar ways that eloquent is used rather than using $contact['name'] and being able to use $collection->contacts->each vs foreach $collection->contacts .....)
$collection->contacts->each(function ($contact) {
// ability to use $contact->name (and not have to use $contact['name'])
});
Collection Macro:
Collection::macro('recursive', function () {
return $this->map(function ($value) {
if (is_array($value)) {
return (object)$value;
}
if (is_object($value)) {
return collect($value)->recursive();
}
return $value;
});
});
Example:
public function test_it_can_recursively_convert_array_to_collection()
{
$data = [
[
'name' => 'Michael Scott',
'emails' => [
'mscott#dundermifflin.com',
'michaelscarn#dundermifflin.com',
],
'contacts' => [
[
'name' => 'Dwight Schrute',
'emails' => [
'dschrute#dundermifflin.com',
],
],
[
'name' => 'Jim Halpert',
'emails' => [
'jhalpert#dundermifflin.com',
],
],
],
],
];
$collection = collect($data)->recursive();
$this->assertInstanceOf(Collection::class, $collection);
$collection->each(function ($item) {
$this->assertEquals('Michael Scott', $item->name);
$item->contacts->each(function ($contact) {
$this->assertNotNull($contact->name);
});
});
}
The original collection map works (e.g. $collection->each .... $item->name) but I can't seem to set convert the nested arrays to objects and get the object values.
Error: Call to a member function each() on array
Illuminate\Support\Collection^ {#632
#items: array:1 [
0 => {#13
+"name": "Michael Scott"
+"emails": array:2 [
0 => "mscott#dundermifflin.com"
1 => "michaelscarn#dundermifflin.com"
]
+"contacts": array:2 [
0 => array:2 [
"name" => "Dwight Schrute"
"emails" => array:1 [
0 => "dschrute#dundermifflin.com"
]
]
1 => array:2 [
"name" => "Jim Halpert"
"emails" => array:1 [
0 => "jhalpert#dundermifflin.com"
]
]
]
}
]
}

how to select elements in array from multiple elements in another array

I have an array A that looks like this:
A = [ { "id" => "1234", "name" => "audi", "isCool" => false },
{ "id" => "5678", "name" => "acura", "isCool" => false },
{ "id" => "9101112", "name" => "bentley", "isCool" => true },
{ "id" => "13141516", "name" => "rollsroyce", "isCool" => true },
{ "id" => "17181920", "name" => "toyota", "isCool" => true } ]
and I have an array B that looks like this:
B = ["1234", "13141516”]
I am trying to select only elements from array A that match array A's ids with Array Bs elements.
So the returned results I would like is:
C = [ { "id" => "1234", "name" => "audi", "isCool" => false },
{ "id" => "13141516", "name" => "rollsroyce", "isCool" => true } ]
Is there an easy way to go about this?
I have currently tried this but obviously not a good idea:
a.select {|x| x['id'] == B.first || B.last}
But obviously this is not dynamic, because what if I had 3 or 4 elements in array B.
A.select { |x| B.include?(x['id']) }

How do I access request arrays within arrays

I have the following request;
Collection {#278
#items: array:3 [
0 => array:2 [
0 => array:8 [
"id" => 631
"name" => "OIL, FILTER O.E.M."
"partno" => "235-00"
"oemnumber" => "16099 003"
"stock" => 0
"price" => "30"
"qty" => 1
"total" => 30
]
1 => array:8 [
"id" => 23
"name" => "SPEEDOMETER"
"partno" => "122-"
"oemnumber" => "25005 1013"
"stock" => 0
"price" => "276"
"qty" => 1
"total" => 276
]
]
1 => array:2 [
0 => array:2 [
"description" => "Oil change"
"hours" => "1"
]
1 => array:2 [
"description" => "Tune up"
"hours" => "2"
]
]
2 => array:15 [
"id" => 1
"custId" => 9046
"bikeId" => 5238
"trans" => "yes"
"transDetails" => "call cab"
"policies" => "Yes"
"locker" => "1"
"lockerContents" => "stuff"
"estimate" => "Yes"
"oldparts" => "Yes"
"status" => "Pending"
"created_by" => null
"created_at" => "2016-05-19 14:40:59"
"updated_by" => null
"updated_at" => "2016-06-08 09:06:58"
]
]
}
I am getting this through;
$collection = collect($request->all());
How should I go about accessing the attributes in these arrays? I have tried pluck with no joy. I suspect I could do a loop over them but with no array_expression for the arrays do I need to use the index?

Resources