I have an array in my request:
['progress_group'] = [0, 0];
['fields'] = [];
If all values in progress_group have the value '0', then the field: fields, should be required. How do I implement this?
I've tried:
$rules = [
'progress_group.*' => 'required',
//'fields' => 'present',
'fields.*' => 'required_if:progress_group.*,0'
];
So:
['progress_group'] = [0, 0];
means fields is required, but
['progress_group'] = [0, 1];
means it is not required to fill in..
required_if compares each element from one array with the one you are comparing with, so it will be progress_group[0] == fields[0] and so on for each item.
What you need is I guess a sum of all the values to be either 0 than it is required, and if the sum is bigger than 0 then it is not required.
So you can make a custom rule, or update your validation as such:
$total = array_sum(request()->input('progress_group'));
if($total == 0) {
$rules['fields.*'] = 'required';
}
I think you had the right idea to use requiredIf, but I think youmay have got the use and syntax wrong, I think this is correct, or will help you on the way to solving your problem:
Validator::make($request->all(), [
'progress_group.*' => 'required',
'fields' => 'present',
'fields.*' => Rule:requiredIf:(progress_group.*, 0),
]);
Related
Currently I have working foreach array where it collects all tasks and it contains weight for each task.
Here's my working code
foreach ($arr4 as $row4) {
$taskCode = strtoupper(str_random(12));
$insert_data5[] = array(
'projCode' => $projCode,
'taskCode' => $taskCode,
'taskWeight' => $row4['weight'],
'plan_days' => $row4['planned_days'],
'actual_days' => $row4['actual_days'],
'deleted' => 0,
'by_id' => auth()->user()->id,
'updated_by' => auth()->user()->name,
'created_at' => now(),
'updated_at' => now(),
);
}
dd($insert_data5);
OUTPUT
What I'm trying to do is to validate if the sum up of taskWeight of 5 Tasks doesn't reached 100% this will show an error message.
As of now my idea is to use validator but I have no idea how can I calculate the array fields of taskWeight
$validator = Validator::make(
$insert_data5,
[
......
]
);
if($validator->fails()){
return redirect()
->back()
->with(['errors'=>$validator->errors()->all()])
->with('modal',$modal);
}
Fixed my problem
I declare $ttlTaskWeight = 0; outside of foreach
Then as suggested do the sum up inside of the foreach
like this
$ttlTaskWeight += $row4['weight'];
and I did this to validate if it exceeds 100% or not
if($ttlTaskWeight != 100){
return redirect()
->back()
->with(['errors'=> [0=> 'Total Task Weight must be exact 100%']])
->with('modal',$modal);
}
and the output is this
I have an array with orders. Example:
$orders = [
'0' => [
'ordernumber' => 1,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
],
'1' => [
'ordernumber' => 2,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
],
'2' => [
'ordernumber' => 3,
'customer' => [
'phone' => '0987654321',
'mobile' => '0687654321'
],
],
'3' => [
'ordernumber' => 3,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
]
];
I want to sort these orders. As you can see there can be orders where the same customer (customer with same phone number, this can be either same phone number or same mobile number) has multiple orders. I want to put all the orders that have the same phone number (doesn't matter if the phone number matches or the mobile number) in an array $duplicateOrders and all the "single" orders (orders that dont match a phone number) in an array $singleOrders. At the end the orders array must be empty. But no order can be lost or be in both arrays.
I have tried to loop through the orders with a foreach loop where I put every order in the $singleOrders array and unset it from the $orders array. I than try to match that order with another foreach loop to all the remaining orders in $orders. If I get a match i put that order (this is done once) in the $duplicateOrders array and every match of it also (I unset every match also from the $orders array). If the orders array is empty I stop, otherwise the first foreach loops kicks in and takes the next order and the proces repeats. This is my code:
protected function splitDuplicateOrders()
{
$singleOrderKey = 0;
if ($this->orders) {
foreach ($this->orders as $key => $order) {
if (count($this->orders) == 0) {
break;
}
array_push($this->singleOrders, $order);
unset($this->orders[$key]);
$orderPushed = false;
foreach ($this->orders as $otherKey => $value) {
if ($order->customer->phone == $value->customer->phone || $order->customer->mobile == $value->customer->mobile) {
if (!$orderPushed) {
array_push($this->duplicateOrders, $order);
}
array_push($this->duplicateOrders, $value);
unset($this->orders[$otherKey]);
unset($this->singleOrders[$singleOrderKey]);
$orderPushed = true;
}
}
$singleOrderKey++;
}
}
}
I expected to have an $duplicateOrders array with all the duplicates and a $singleOrders array with all the singles. I tested this with an $orders array of a total of 4 orders where 2 of them were duplicates and 2 were singles. The function sorted it nicely (but only if the orders aren't right after each other, if they are it still sorts the duplicates right but leaves one also in the $singleOrders and than I have 5 orders). Than I tested it where there were 3 duplicates and 1 single order. The $duplicateOrders array was correct but in the $singleOrders the single order was placed but also one duplicate order from the $orders array. It somehow removed the 2 duplicates correct but left one duplicate in the $singleOrders array.
Can someone help me to debug this or provide a different approach? I have been trying to solve this for 2 days but no success.
You could make use of Laravel Collections, in this case I'm gonna use the partition() method. From the documentation:
partition()
The partition method may be combined with the list PHP function to
separate elements that pass a given truth test from those that do not:
$collection = collect([1, 2, 3, 4, 5, 6]);
list($underThree, $equalOrAboveThree) = $collection->partition(function ($i) {
return $i < 3;
});
$underThree->all();
// [1, 2]
$equalOrAboveThree->all();
// [3, 4, 5, 6]
So in your case:
$orders = /** query or API to get orders as array */;
list($repeated, $single) = collect($orders)
->partition(function ($order) use ($orders) {
return $orders->where('customer.phone', $order['customer']['phone'])->count() > 1
OR $orders->where('customer.mobile', $order['customer']['mobile'])->count() > 1;
});
// now you can use them:
$repeated->all();
$single->all();
Notice that this two newly created objects ($repeated and $single) are in fact also instances of the Collection class (as you can see where I used the all() method on each), so you can keep constraining/sorting/customizing them with the help of the Collection's methods.
In my laravel POST endpoint, Im expecting an "items" parameter in the following form:
$items => [
['item' => 'a', 'item_slot' => 1],
['item' => 'b', 'item_slot' => 2],
['item' => 'c', 'item_slot' => 3],
]
I want to validate that all the required item slots were provided.
I have an array of required slots $requiredItemSlots = [1, 2]
What validation rules should I use to make sure that item slots in $requiredItemSlots were present? Note, i don't want to limit the provided slots to the required ones, i just need to make sure that the required slots were filled.
For now I have something like:
'items.*.item' => 'required',
'items.*.item_slot' => 'required|distinct'
To ensure that no duplicate slots were passed in.
Originally I tried doing
'items.*.item_slot' => Rule::in($requiredItemSlots)
But that's not correct because not all the slots are necessarily required.
You'll need to make a custom rule, something like that:
'items' => [
'required',
'array',
function ($attribute, $value, $fail) {
$required = [1, 2];
// Cast to collection for easier checks
$items = collect($value);
foreach ($required as $r) {
if (! $items->firstWhere('item_slot', '=', $r)) {
$fail("$r has to be present in items.");
}
}
},
], // ..other validation rules
You may use a combination of distinct, in:1,2,3 and size:3 to validate the input:
'items' => 'required|array|size:3',
'items.*.item_slot' => [
'required',
'distinct',
Rule::in($requiredSlots),
]
With size:3 you force the array to have exactly 3 elements. With distinct you make sure there are no duplicates in the item_slot element field. And with Rule::in($requiredSlots) you ensure that there are no unknown item_slots given.
I'm building an Insert query using Faker and I wonder whether it is possible to use a value to-be-inserted in another value.
Here is an example, not accurate for my situation but explains well:
DB::table('debts')->insert([
'name' => $faker->company,
'debt' => $faker->randomFloat($nbMaxDecimals = 2, $min = 20000, $max = 10000000),
'debt_paid' => 'debt' / rand ( 2 , 8 ),
'notes' => $faker->paragraph($nbSentences = 3, $variableNbSentences = true),
]);
As you can see, in the row of debt_paid I want to access the value of 'debt' that was randomly defined a row above. This is because debt_paid needs to be logical and without the value of debt it might be non-sense.
I know that defining 'debt' as a variable before the insert would solve it, but I wonder whether there's a more elegant solution.
So do that outside the insert
$dbt = $faker->randomFloat($nbMaxDecimals = 2, $min = 20000, $max = 10000000);
DB::table('debts')->insert([
'name' => $faker->company,
'debt' => $dbt,
'debt_paid' => $dbt / rand ( 2 , 8 ),
'notes' => $faker->paragraph($nbSentences = 3, $variableNbSentences = true),
]);
I am inserting multiple rows at the same time, say 2 rows
$multiple_rows = [
['email' => 'taylor#example.com', 'votes' => 0],
['email' => 'dayle#example.com', 'votes' => 0]
];
DB::table('users')->insert($multiple_rows);
How can I get those inserted ids.
I am doing it, this way for now.
foreach($multiple_rows as $row){
DB::table('users')->insert($row);
$record_ids[] = DB::getPdo()->lastInsertId();
}
Any other good way to do it, without inserting single row each time.
You could do something like the following:
$latestUser = DB::table('users')->select('id')->orderBy('id', 'DESC')->first();
$multiple_rows = [
['email' => 'taylor#example.com', 'votes' => 0],
['email' => 'dayle#example.com', 'votes' => 0]
];
DB::table('users')->insert($multiple_rows);
$users = DB::table('users')->select('id')->where('id', '>', $latestUser->id)->get();
If you really need all the inserted ID's
$dataArray = [
['name' => 'ABC'],
['name' => 'DEF']
];
$ids = [];
foreach($dataArray as $data)
{
$ids[] = DB::table('posts')->insertGetId($data);
}
To get all id with a massive insertion I think the good way is to first get the last id in the table, make the massive insertion and get the last id. In theory they must follow, unless there has been an insertion from another connection. To avoid that the solution is a transaction.
Update
Also read the documentation