How to update array based on values in another array - php

I get the error Undefined index: item_total on the line $totals['item_total'] += (float)$quantity; I want $totals array to contain the $mycart summarized quantity data by Product.
$mycart = array();
$mycart[0]['product'] = 'ProductA';
$mycart[0]['quantity'] = 10;
$mycart[1]['product'] = 'ProductA';
$mycart[1]['quantity'] = 4;
$mycart[2]['product'] = 'ProductB';
$mycart[2]['quantity'] = 8;
$mycart[3]['product'] = 'ProductB';
$mycart[3]['quantity'] = 8;
$totals = array();
foreach ($mycart as $row)
{
$product = $row['product'];
$quantity = $row['quantity'];
$totals['item_total'] += (float)$quantity;
}

In php you can create an array index by $totals['item_total'] = value;. And you cannot use an array index in an expression if it has not been "initialized". What do you see when you write this statement out $totals['item_total'] += (float)$quantity; "long hand"? It is just a shortcut for $totals['item_total'] = $totals['item_total'] + (float)$quantity;. In the right-hand expression $totals['item_total'] has not been initialized, thus program gives "Undefined index" message.

Your problem comes from using increment with an undefined variable
$totals['item_total'] += (float)$quantity;
The reason for this is that increment does a read (to get the current value) of the variable, before increment it. Which makes sense because we need to know it's current value before we can add 1 to it.
Now because that variable is not defined, you get an error message Undefined index: item_total". Which also makes sense because we cannot get the value of something (read it) that has not been defined, because it doesn't exist yet.
To further illustrate this, we can manually increment without the += like this:
$totals['item_total'] = $totals['item_total'] + 1;
We should agree this is the same as $totals['item_total'] += 1 as they give the same value, but here you can see how we must reference the previous value of that variable, which is the same thing that += must do. And in the same line of reason we cannot read it if it's not defined.
#Psudo for $var = $var + 1
write = read + 1
When simply assigning like this:
$totals['item_total'] = 0;
There is no reading (of an undefined value, as we know what 0 is) that takes place, so PHP is fine with that variable not existing and just creates it. Some languages are not that forgiving. What I mean here is some languagues you would need to first define $totals as an array, and then add stuff to it. In PHP $totals doesn't even need to exist to do $totals['item_total'] = 0;
So as others noted you need to define it with a value of 0 before hand, that way when the read is done it will know it's 0 and you wont see the error.
$totals['item_total'] = 0;
//or $totals = ['item_total' => 0];
foreach ($mycart as $row)
{
$product = $row['product'];
$quantity = $row['quantity'];
$totals['item_total'] += (float)$quantity;
}
echo $totals['item_total'];
Output
30
Sandbox
PHP is actually very forgiving about undefined variables, but in cases where it must first read that variable, it must be defined beforehand.
UPDATE
Based on this comment
I want it summed by product -- ProductA = 14 and ProductB = 16.
You can do it this way:
$mycart = array();
$mycart[0]['product'] = 'ProductA';
$mycart[0]['quantity'] = 10;
$mycart[1]['product'] = 'ProductA';
$mycart[1]['quantity'] = 4;
$mycart[2]['product'] = 'ProductB';
$mycart[2]['quantity'] = 8;
$mycart[3]['product'] = 'ProductB';
$mycart[3]['quantity'] = 8;
$totals = array();
foreach ($mycart as $row)
{
$key = $row['product'];
if(!isset($totals[$key])){
$totals[$key] = $row;
// $totals[$key] = $row['quantity']; //just [key=>quantity] no inner array
}else{
$totals[$key]['quantity'] += $row['quantity'];
// $totals[$key] += $row['quantity']; //just [key=>quantity] no inner array
}
}
print_r($totals);
Output
Array
(
[ProductA] => Array
(
[product] => ProductA
[quantity] => 14
)
[ProductB] => Array
(
[product] => ProductB
[quantity] => 16
)
)
/*
without the inner array
Array
(
[ProductA] => 14
[ProductB] => 16
)
*/
Sandbox
See my comments in the code on how to remove the inside array if you want just the Key and it's total quantity. If you do want the inner arrays but not the top level key (product), you can do this to remove those.
//after the loop
$totals = array_values($totals); //resets array keys to numbered keys
This will replace the ProductA and ProductB keys with 0 and 1.
Enjoy.

Simply add this line right before foreach:
$totals['item_total']=0;

Related

How do I move a group of items in a PHP array below the next group of items?

In an Array with normal numerical keys ( $file_array_for_editing ), I want to move a set of consecutive X number of values below the next set of X values.
Example: If a group of X values is 10, then in an Array of 50, I have 5 sets of 10 values. I want to move the 10 values in set 3 - below the 10 values in set 4.
So that : Set1(10 values) , Set2(10 values) , Set3(10 values) , Set4(10 values) , Set5(10 values)
Becomes: Set1(10 values) , Set2(10 values) , Set4(10 values) , Set3(10 values) Set5(10 values)
Since I don't know a better way, this is how I have done it now - by what I believe is switching the values:
$file_array_for_editing = [];
for($i=1; $i <= 50; $i++) {
$file_array_for_editing[] = $i;
}
$number_in_one_set = 10 ;
$set_number_to_move = 3 ;
$f = $file_array_for_editing ;
$s = ($set_number_to_move - 1) * $number_in_one_set ; // (3 - 1) * 10 = 20
list(
$f[$s+0],$f[$s+1],$f[$s+2],$f[$s+3],$f[$s+4],$f[$s+5],$f[$s+6],$f[$s+7],$f[$s+8],$f[$s+9],$f[$s+10],$f[$s+11],$f[$s+12],$f[$s+13],$f[$s+14],$f[$s+15],$f[$s+16],$f[$s+17],$f[$s+18],$f[$s+19]
) =
[$f[$s+10],$f[$s+11],$f[$s+12],$f[$s+13],$f[$s+14],$f[$s+15],$f[$s+16],$f[$s+17],$f[$s+18],$f[$s+19],$f[$s+0],$f[$s+1],$f[$s+2],$f[$s+3],$f[$s+4],$f[$s+5],$f[$s+6],$f[$s+7],$f[$s+8],$f[$s+9]];
$file_array_for_editing = $f ;
At the end, the numerical keys stay properly in order, from 0 to 49.
I need help finding a way to do this where I can vary the $number_in_one_set
If possible, I would appreciate help finding a solution where it is clearly apparent what is being done, so that after a year, when I look at the code again, it will be easy to understand. (as in, even now, I just vaguely understand why the list() above works)
Possibly following might help you on your way. You can change the 'sets' you'd like to switch using array $switch.
<?php
$arr = [];
for($i=1; $i <= 50; $i++) {
$arr[] = $i;
}
$set = 10; // each set has 10 items
$switch = [3, 4]; // switch element 3 vs. 4
$newArr = array_chunk($arr, $set); // chop array in chunks of size $set
// swap
$tmp = $newArr[$switch[0]]; // $temp=$newArr[3]
$newArr[$switch[0]] = $newArr[$switch[1]]; // $newArr[3]=newArr[4]
$newArr[$switch[1]] = $tmp; // $newArr[4]=$newArr[3]
$result = [];
array_walk_recursive($newArr, function($el) use (&$result) { $result[] = $el; }); // flatten array
EDIT
array_walk_recursive() applies the callback function (function($el)) to each element of nested array $newArr.
Each element of array $newArr, referenced by $el will be pushed into array $result, a flat indexed array.
Also, because the anonymous function (closure) writes to flat array $result which is defined in the parent scope, we need to employ the use language construct.
source manual: Closures may also inherit variables from the parent scope. Any such variables must be passed to the use language construct.
working demo
#jibsteroos - I really like the method you provided (which #CBroe also suggested) - reason being that it allows any two sets anywhere within the original array to be swapped.
After some thought, I find I prefer using the method below, even though it is a little long winded - reason being my use case is only to exchange a set with the one below it.
<?php
$arr = []; // Setting up a sample array
for($i=1; $i <= 50; $i++) {
$arr[] = $i;
}
$set_size = 10 ; // 10 items per set
$set = 3 ; // set to move down
$set_to_move = ($set - 1) * $set_size; // start position of this set in the array - 20
print_r($arr) ;
echo '<hr>';
$slice1 = array_slice($arr,0,$set_to_move);
print_r($slice1) ; // from the start of the array - to the start of the set to move
echo '<hr>';
$slice2 = array_slice($arr,$set_to_move,$set_size);
print_r($slice2) ; // the set to move
echo '<hr>';
$slice3 = array_slice($arr,$set_to_move + $set_size,$set_size);
print_r($slice3) ; // the set after the set to move
echo '<hr>';
$slice4 = array_slice($arr,$set_to_move + (2 * $set_size));
print_r($slice4) ; // the rest of the array
echo '<hr>';
$arr_edited = array_merge($slice1,$slice3,$slice2,$slice4,);
print_r($arr_edited) ; // All 4 arrays combined in the new order
echo '<hr>';

"Undefined variable: Profit $sum-$sub"

I am attempting to sum two arrays and subtract them from each other in PHP. Below is my attempt at it:
function total_price($totals)
{
$sum = 0;
$sub = 0;
foreach ($totals as $total)
{
$sum += $total['total_selling_price'];
$sub += $total['total_buying_price'];
$profit = $sum - $sub;
}
What I'm trying to do is sum up everything in the sales array and subtract it by everything in the costs array (represented by variable $sub) in order to generate profit. However, I'm unable to, and I get the following error:
UNDEFINED VARIABLE: PROFIT.
I've declared a profit variable within the foreach, so can someone tell me why my variable is considered undefined?
Assign $profit = 0 out of loop.
Also validate totals before iterating.
if(is_array($totals)){
foreach($totals as $total ){
// write your code here
}
}

How to add the values from a foreach loop php

I have and foreach loop that outputs the totals I want to add when i echo the $val_tex it outputs in one number like "4911165" but if I echo it with a break tag it gives me the right values. It looks like
49
1
1
1
65
My question is how to get the sum of all the values which should equal "117"
$val_tex = array();
foreach ( $get_seller as $keys ) {
$val_tex = $keys['total'];
}
You have to add them together in the foreach loop - there's a simple way to do that $total += $keys['total']; It's just a simpler way of saying $total = $total + $keys['total'];
There are also other ways - $total = array_sum(array(1,2,3,4)); // == 10 for example. To get the sum from a single column, you get an array that only contains the values from the specific column first:
// an array of the values from that column
$arrayTotall = array_column($keys, 'total');
$total = array_sum($arrayTotals);
Your for each needs another variable to add them:
foreach ( $get_seller as $keys ) {
$val_tex = $keys['total'];
$sum = += $val_tex
//or...
$val_tex += $keys['total'];
//depending on how you want to us val_tex
}
The .= adds the value to previous value instead of overwriting it.

php array insert and print

This is a part of my PHP program.
//for example: $rec_count = 30
$totalpages=(int)$rec_count/10;
$index=0;
$pageslink[$totalpages]='';
while($index <= $totalpages ){
$pageslink['index']=$index;
echo '<br>Index: '.$index.'<br>';
echo '<br>Page '.$pageslink['index'].' ';
$index++;
}
print_r($pageslink);
It comes out like this:
Index: 0
Page 0
Index: 1
Page 1
Index: 2
Page 2
Index: 3
Page 3 Array ( [3] => [index] => 3 )
Its supposed to be pageslink[0] = 1; pageslink[1 ]= 2; pageslink[3] = 3; But When I print_r() the pageslink array , only 3 as a value. I've been trying to find out why only 3 is inserted as value in array.
I am a beginner, so thank you in advance for your help. It will be much appreciated.
In the short version of this answer, arrays in PHP start counting from 0, not 1. So on the first loop it would be 0 and the second loop it would be 1 and so on.
You're using
$pageslink['index'] = $index;
Meaning you set the item with the named key 'index' in your array to the value of your variable $index, instead of using $index as your key.
In PHP (and many other languages) you can refer to an item in an array with its index number (0, 1, 2, etc.) or by a word (named key).
For example:
$myArray = ['John', 'London'];
echo $myArray[0]; // John
echo $myAray[1]; // London
or
$myArray = ['name' => 'John', 'city' => 'london'];
echo $myArray['name']; // John
echo $myArray['city']; // London
What you are doing now is setting the same item in your array (the item you're calling index) to a new value every loop, overwriting its old value. So after all the loops you'll only have the last value saved.
You want something like this:
$pageslink[$index] = $index + 1;
Which will translate to:
$pageslink[0] = 1; // first loop
$pageslink[1] = 2; // second loop
$pageslink[2] = 3; // third loop
By the way, a for loop would be cleaner in your example code:
$rec_count = 30
$totalpages=(int)$rec_count/10;
$pageslink = array(); // this is how to create an array, not with ''
for($i=0;i<$totalpages;$i++){
$pageslink[] = $i;
}
print_r($pageslink);
You over complicate the code here, try:
$totalpages=(int)$rec_count/10;
$index=0;
$pageslink = array();
while($index <= $totalpages ){
$pageslink[]=$index+1;
echo '<br>Index: '.$index.'<br>';
echo '<br>Page '.$pageslink[$index].' ';
$index++;
}
print_r($pageslink);
But this code is very weird. You just create array of n elements.
Could you explain what do you try to achieve here?

How to add variables that are passed on through the URL to an array?

<?php
$i = $_GET['i'];
echo $i;
$values = array();
while ($i > 0)
{
$expense = $_GET['expense_' + i];
$amount = $_GET['amount_' + i];
$values[$expense] = $amount;
i--;
print_r($values);
}
?>
i represents the number of sets of variables I have that have been passed through from the previous page. What I'm trying to do is add the expenses to the amounts and put them in an array as (lets just say for this example there were 3 expenses and 3 amounts) [expense_3 => amount_3, expense_2 => amount_2, expense_1 => amount_1]. The names of the variables are successfully passed through via the url as amount_1=50, amount_2=50, expense_1=food, expense2=gas, etc... as well as $i, I just dont know how to add those variables to an array each time.
Right now with this code I'm getting
4
Array ( [] => ) Array ( [] => ) Array ( [] => ) Array ( [] => )
I apologize if I'm not being clear enough, but I am pretty inexperienced with PHP.
The syntax error you're getting is because you're using i instead of $i - however - that can be resolved easily.
What you're looking to do is "simple" and can be accomplished with string-concatenation. It looks like you're attempting this with $_GET['expense'] + i, but not quite correct.
To properly build the parameter name, you'll want something like $_GET['expense_' . $i], here you can see to concatenate strings you use the . operator - not the + one.
I'm going to switch your logic to use a for loop instead of a while loop for my example:
$values = array();
for ($i = $_GET['i']; $i > 0; $i--) {
$expense = $_GET['expense_' . $i];
$amount = $_GET['amount_' . $i];
$values[$expense] = $amount;
}
print_r($values);
This is following your original logic, but it will effectively reverse the variables (counting from $i down to 1). If you want to count up, you can change your for loop to:
$numVariables = $_GET['i'];
for ($index = 1; $index <= $numVariables; $index++) {
$expense = $_GET['expense_' . $index];
...
Or just serialize the array and pass it to the next site, where you unserialize the array
would be much easier ;)

Categories