Laravel: Sum of foreach - php

I have this foreach loop:
my $items looks like this:
array:2 [▼
0 => array:3 [▼
"variant_id" => "393c6c70-8cb7-11e8-815a-f9c70a1fbe8e"
"name" => "Medicine 1"
"quantity" => "1"
]
1 => array:3 [▼
"variant_id" => "8a80d340-e0c1-11e8-86a4-3b06d2b50e37"
"name" => "Medicine 2"
"quantity" => "1"
]
]
Now, in my foreach, I compare the variant_id to my database and get the points from that database and multiply it by the quantity of the Medicines.
points for Medicine 1 is = 50
points for Medicine 2 is = 20
so it should be 50(medicine 1 points) multiplied by 1 (quantity of medicine 1) and
20 x 1 (medicine 2) and then the sum of both which should be equal to 70. But when I dd($sum) what I get is 50 which is only for medicine 1.
$sum = 0;
foreach ($items as $variants) {
$id = $variants['variant_id'];
$quantity = $variants['quantity'];
$find = Activity::where('variant_id', $id)->first();
$act_points = $find->points * $quantity;
$sum += $act_points;
dd($sum);
}
What am I missing here?

You can see dd() as a Dump and Die. This will dump the asked data and kills the script. Because this is executed, the script gets terminated before it can finish the loop
You need to use the dd() after the foreach-loop
$sum = 0;
foreach ($items as $variants) {
$id = $variants['variant_id'];
$quantity = $variants['quantity'];
$find = Activity::where('variant_id', $id)->first();
$act_points = $find->points * $quantity;
$sum += $act_points;
}
dd($sum);
If you do not want to halt the execution of your script, use the dump function instead.
https://laravel.com/docs/5.7/helpers#method-dd

I figure out you are doing Debug dump (dd) inside foreach loop so it will just stop after the first iteration.
You should do dd outside of foreach loop.

To rationalize and avoid multiple DB calls yu can do the next
$input = [
[
"variant_id" => "393c6c70-8cb7-11e8-815a-f9c70a1fbe8e",
"name" => "Medicine 1",
"quantity" => "1",
],
[
"variant_id" => "8a80d340-e0c1-11e8-86a4-3b06d2b50e37",
"name" => "Medicine 2",
"quantity" => "1",
],
];
$sum = Activity::whereIn('variant_id', array_column($input, 'variant_id'))->get()->sum(function ($s) use ($input) {
foreach ($input as $k => $v) {
if ($s->variant_id == $v['variant_id']) {
return $s->points * $v['quantity'];
}
}
});
This will work if in $input array there is no repeating elements by variant_id.
In other words if each $input[n]['variant_id'] value is unique.

Related

Is there a better way of adding values of the same array index in laravel using foreach that is memory efficient?

Here is my code to achieve:
The values of $categoryRatings are the following arrays:
$categoryRatings = array:2 [
2 => array:2 [
1 => 50.0
2 => 35.0
]
3 => array:2 [
1 => 55.0
2 => 45.0
]
]
$indexes = [];
foreach ($categoryRatings as $categoryRating) {
foreach ($categoryRating as $key => $value) {
foreach ($categories as $category) {
if ($category->id == $key) {
$indexes[$category->id] = isset($indexes[$category->id]) ? ($indexes[$category->id] + $value) : $value;
}
}
}
}
$overAllCategoryRating = [];
foreach ($categories as $category) {
$overAllCategoryRating[$category->id] = $indexes[$category->id]/sizeof($categoryRatings);
}
And the output of $overallCategoryRating is equal to:
array:2 [
1 => 52.5
2 => 40.0
]
The $categories here is a collection where I used the id as key so that I can assign the results to its key for use in my front end.
Is there some ways to optimized this code for memory efficient since when large data is computed it won't get results fast because of many foreach loop.
You can use
$first = collect($categoryRatings)->avg(1) // Result: 52.5
$second = collect($categoryRatings)->avg(2) // Result: 40.0

How do I update new collection values?

I need a way to update a collection that I am getting from the html form.
I have an array of
Product ids:
array:3 [
0 => "1"
1 => "2"
2 => "3"
]
Product quantity:
array:3 [
0 => "15"
1 => "5"
2 => "7"
]
Product Price:
array:3 [
0 => "12.00"
1 => "2.50"
2 => "4.00"
]
I am storing/saving the values to the database with something like this:
$product_ids = $request->get('product_ids');
$product_prices = $request->get('product_prices');
$product_quantities = $request->get('product_quantities');
$product_descriptions = $request->get('product_descriptions');
for ($i = 0; $i < sizeof($product_ids); $i++) {
$item = new Order_item;
$item->order_id = $order->id;
$item->product_id = $product_ids[$i];
$item->unit_price = $product_prices[$i];
$item->description = $product_descriptions[$i];
$item->quantity = $product_quantities[$i];
$item->save();
}
You can find the record based on id and then save the changed data:
$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();
From https://laravel.com/docs/7.x/eloquent#updates
If you're using order_id as the key, then use a where() statement with first():
$order = App\Order_item::where('order_id', 1)->first();
I fixed the issue with something like this:
$product_ids = $request->get('product_ids');
$product_prices = $request->get('product_prices');
$product_quantities = $request->get('product_quantities');
$product_descriptions = $request->get('product_descriptions');
Fetched the values using $request->get.
And updated the values using a for loop.
for ($i = 0; $i < sizeof($product_ids); $i++) {
Order_item::where('order_id', $id)
->where('product_id', $i + 1)->update(
[ 'quantity' => $product_quantities[$i],
'unit_price' => $product_prices[$i],
'description' => $product_descriptions[$i],
]);

Get data from multiple array in Controller

I have country list in array with multiple array, like:
public static function listCountries()
{
$this->country = array(
array(1, 'SAD', 'sad.png'),
array(2, 'Argentina', 'argentina.png'),
array(3, 'Australija', 'australija.png'),
array(4, 'Novi Zenland', 'noviz.png'),
array(5, 'Belgija', 'belg.png'),
array(6, 'Nizozemska', 'nizozemska.png')
);
}
But when i do foreach for array, i'm getting this:
//From DB
$item->country = "1,4";
$item->country = explode(",", $item->country);
for($i=0; $i < count($item->country); $i++) {
$index = $item->country[$i];
if( !empty($this->country[$index]) ) {
$item->country[$i] = $this->country[$index];
}
}
$item->country = implode(",", $item->country);
echo $item->country;
But i'm getting something like this:
array:2 [▼
0 => array:3 [▼
0 => 5
1 => "Belgija"
2 => "belg.png"
]
1 => array:3 [▼
0 => 2
1 => "Argentina"
2 => "argentina.png"
]
]
1 = SAD, 4 = Novi Zenland, not Belgija and Argentina
There is no good country, also no data what i want. How to fix this?
You can use this foreach loop to go through the other array and swap the string if the number matches:
$item->country = "1,4";
$item->country = explode(",", $item->country);
for($i=0; $i < count($item->country); $i++) {
$index = $item->country[$i];
foreach($this->country as $c) {
if($c[0] == $index) {
$item->country[$i] = $c[1]; // or $item->country[$i] = $c; if you want all three items
break;
}
}
}
$item->country = implode(",", $item->country);
echo $item->country;
// Should output: SAD,Novi Zenland
The indexes in arrays are 0-based, which means that:
$index = $item->country[$i];
Has to become
$index = $item->country[$i - 1];
To correlate with the country ids. Otherwise, it is always one off. This is assuming that the ids are always ordered from least to greatest, and all ids are a continuous range.

PHP Permutations with exception of similar sequence

My permutation/combinations of data
$combinations = [[]];
$data = [
['alteration1', 'alteration2', 'alteration3', 'alteration4' ... upto 5 each],
['alteration1', 'alteration5', 'alteration6', 'alteration7' ... upto 5 each],
['alteration8', 'alteration9', 'alteration10', 'alteration5' ... upto 5 each],
... upto 6 max
];
$length = count($data);
for ($count = 0; $count < $length; $count++) {
$tmp = [];
foreach ($combinations as $v1) {
foreach ($data[$count] as $v2)
$tmp[] = array_merge($v1, [$v2]);
}
$combinations = $tmp;
}
print_r($combinations);
The script would generate such sets
0 => array:3 [▼
0 => "alteration1"
1 => "alteration1"
2 => "alteration8"
]
1 => array:3 [▼
0 => "alteration1"
1 => "alteration1"
2 => "alteration9"
]
... the issue begins when I start getting the same sequences of data in my case array index 0 and 20 would be exactly the same despite any position.
20 => array:3 [▼
0 => "alteration8"
1 => "alteration1"
2 => "alteration1"
]
21 => array:3 [▼
0 => "alteration1"
1 => "alteration9"
2 => "alteration1"
]
$final = []; // remove duplicates
The basic idea is to keep $combinations array's unique (alteration1,alteration2,alteration3) is equal to (alteration3,alteration1,alteration2) therfore it should be skipped in the $final array. I haven't really found anything around SO and google. Thanks for the help. $data dimentions [ from 1 - 6 ], each array inside can be [ 1 - 6 ]. Following script might not be working as expected .
http://sandbox.onlinephpfunctions.com/code/3ad5084386c2185f7619aaac152b638873039ee8
We iterate over the data and find unique elements first for each set using array_unique.
We then natsort them to get a sorted form and serialize them using implode(). By doing this, we would get the same serialized code for sets ABC,CBA,BAC etc.
We then find duplicates using keys check inside a variable, say $set. If the serialized key is set, we exclude it from the results, else we include it in our final results.
Snippet:
<?php
$data = [
['alteration1', 'alteration4',],
['alteration2','alteration3'],
['alteration2','alteration3'],
[]
];
$combinations = [[]];
foreach($data as $index => $current_data){
$current_data = array_unique($current_data);
if(empty($current_data)) continue;
$temp_combinations = [];
foreach($current_data as $value){
foreach($combinations as $each_combination){
$temp_combinations[] = array_merge($each_combination,[$value]);
}
}
$combinations = $temp_combinations;
}
$set = [];
$unique_combinations = [];
foreach($combinations as $each_combination){
natsort($each_combination);
$serialized_form = implode(",",$each_combination);
if(isset($set[$serialized_form])) continue;
if(empty($each_combination)) continue;
$unique_combinations[] = $each_combination;
$set[$serialized_form] = true;
}
print_r($unique_combinations);
Demo: https://3v4l.org/Do6oH

How to save it in database

In my database i have column like id,product_id,company_name,service,qty,delivery_cost,delivery_date,order_status etc.
I view i used Jquery and Html and jquery dynamically add more input fields of product_id,service,delivery_cost,qty,delivery_date,order_status on clicking ADD more button.On submiting form i got this in controller on doing dd($allData);
My question is how can i save this data in database
array:8 [▼
"_token" => "gSddIeA11OBV60xU9YiDXn8fmsfkwxlQ85QmDdkQ"
"service" => array:3 [▼
0 => "cement"
1 => "iron"
2 => "steel"
]
"qty" => array:3 [▼
0 => "5"
1 => "44"
2 => "5"
]
"delivery_cost" => array:3 [▼
0 => "5465"
1 => "553"
2 => "554"
]
"delivery_date" => array:3 [▼
0 => "2016-12-16"
1 => "2016-12-08"
2 => "2016-12-17"
]
"order_status" => "Confirm"
"delivery_vehicle" => array:1 [▼
0 => "Self_elivery"
1 => "Self_elivery"
2 => "Self_elivery"
]
]
public function store(Request $request)
{
$allData= $request->all();
dd($allData);
$product = new Order;
}
i try this
public function store(Request $request)
{
$date = $request->get('delivery_date');
$cost = $request->get('delivery_cost');
$service = $request->get('service');//add quotes next to service
foreach($date as $deliveryDate)
{
foreach($cost as $proAmount){
$db = new Order;
$db->delivery_date = $deliveryDate;
$db->amount = $proAmount;
$db->save();
}
}
return"ok";
}
I tried this way but it store same data multiple times may be because of loop inside of loop.I need your help to store this data in database
Using for() should work for you:
$data = $request->all();
for ($i = 0; $i < count($data['delivery_date']); $i++) {
$db = new Order;
$db->delivery_date = $data['delivery_date'][$i];
$db->delivery_cost = $data['delivery_cost'][$i];
....
$db->save();
}
You can try this If you want to use foreach $key will give you the index.
$date = $request->get('delivery_date');
$cost = $request->get('delivery_cost');
$service = $request->get('service');
foreach($date as $key=>$deliveryDate)
{
$db = new Order;
$db->delivery_date = $deliveryDate;
$db->amount = $cost[$key];
$db->save();
}
return"ok";
Hope this help you. Ask if any query
Do bulk insert instead of running new sql query for every insert(if all the request params exist in single table).
$data = [];
foreach ($request->all() as $param => $val) {
if( is_array($val) ) // Ignore string params. i.e. _token, order_status
{
foreach ($val as $key => $value) {
$data[$index][$param] = $value;
$data[$index]['created_at'] = \Carbon\Carbon::now();
$data[$index]['updated_at'] = \Carbon\Carbon::now();
$index++;
}
$index = 0;
}
}
Model::insert($data);
Using foreach() should work for you very easy:
$inputdata = $request->all();
foreach ($inputdata as $key=>$val) {
$dbdata = new Order;
$dbdata ->delivery_date = $data['delivery_date'][$key];
$dbdata ->delivery_cost = $data['delivery_cost'][$key];
....
$dbdata ->save();
}

Categories