how to get sum of dynamic values from array - php

I have a list of requested items that are pulled from the database. What I am looking to do is to get the hourly_rate for each item that is selected and add those values together. I am getting the values I need from the database, but now I am looking to add those values.
//Get total hours from other query
$hours = $row['total_hours'];
//Items requested by user
$requestedItems = "1,2,3";
$items = explode(',', $requestedItems);
//Query
$priceQuery = "SELECT hour_rate,
day_rate,
item_id,
rental_status,
hourly_rental
FROM
products
WHERE
rental_status != 1
AND
item_id = :var
";
$itemDisplay = array();
I loop through and get back the values, but now what I want is to add those returned values together...I tried turning them to integers and adding them together but could not seem to do it.
foreach($items as $var){
$itemDisplay = $userFile->priceSelection($conn, $var, $priceQuery);
foreach($itemDisplay as $key=>$v){
//Edits added
$itemVar += $v['hour_rate'];
if($hours >= 3){
if($v['hourly_rental'] == '1'){
$hours -= 2;
$itemVar += $v['day_rate'] * $hours;
}else{
$itemVar += $v['day_rate'];
}
}else{
if($v['hourly_rental'] == '1'){
$itemVar += $v['day_rate'];
}else{
// This is the line here that is affecting the value of both items.
//If $day_rate = $v['day_rate'] then the items with hourly_rentals == '1'
//have correct values. If I set $day_rate = 0; then the items with
//hourly_rentals != '1' have correct values
//but not both at the same time. Might need to figure out a better comparison.
$day_rate = $v['day_rate'];
print_r($day_rate);
}
}
}
}
$totalPrice = $itemVar + $day_rate + $delivery_cost;
The price selection function just grabs the values from database (code for clarity)
public function priceSelection($conn, $var, $priceQuery){
$stmt = $conn->prepare($priceQuery);
$stmt->bindParam(":var", $var);
$stmt->execute();
$result = $stmt->fetchAll();
if($stmt->rowCount() > 0){
foreach($result as $row){
$array[] = $row;
}
return $array;
}
return false;
}

Beside the option to Summarize the numbers within the SQL query you may do it in PHP as well.
Avoid resetting the value on each loop step and continuously add the value to $itemVar variable:
<?php
foreach($items as $var){
$itemDisplay = $userFile->priceSelection($conn, $var, $priceQuery);
foreach($itemDisplay as $key=>$v){
//$itemVar = ''; // do not null the sum value
//Items returned that I would like to be added together
$itemVar += $v['hour_rate'];
//$values = intval($itemVar);
}
}
print_r($itemVar); // print final value
EDIT after OP update
I see two issues in the updated OP code.
the data in the variable $day_rate is set directly and only within the nested foreach loop so this variable keeps the very last value that is set each time the else - else condition is met AND it is the only place where the variable is initiated. This could make some troubles in final calculation.
the $itemVar variable is incrementally calculating its total sum in each loop however the $day_rate is not and more over the problem mentioned in first point. You may need to make a sum of that value as well what you can achieve with this: $day_rate = $v['day_rate'];
potential problem might be the comparison of (xxx == '1') as the PHP dynamically works with the variable entity it will take and convert the value of xxx to most probable to an integer and then converts the string of '1' to the integer as well befor the comparison is made. As an example gues how is compared var_dump(true == '1'); true or false, huh?
Note it is going to be XY problem since the whole structure starts not making any sense to me.
Last EDIT
As general purpose tip for understanding what your code is doing I would recommend any kind of debugger where you can see live status of any variable while the script is processing. Debugging in PHP
Or very simple way of debugging that is simple printing the variable content so you can get at least some idea how to data are calculated.
And of course Always debug your scripts with enabled PHP Error Reporting!
// Counters for
$itemsCounter = 0;
$displayCounter = 0;
foreach($items as $var){
$itemDisplay = $userFile->priceSelection($conn, $var, $priceQuery);
foreach($itemDisplay as $key=>$v){
// Debug current variables rows and $v
echo "Row $itemsCounter::$displayCounter; key=$key;". print_r($v, true);
//Edits added
$itemVar += $v['hour_rate'];
if($hours >= 3){ // WHERE do you get the $hours? Sould it be $v['hour_rate']?
if($v['hourly_rental'] == '1'){
$hours -= 2;
$itemVar += $v['day_rate'] * $hours;
}else{
$itemVar += $v['day_rate'];
}
// Debug current variable $itemVar
echo "itemVar=$itemVar;"
}else{
if($v['hourly_rental'] == '1'){
$itemVar += $v['day_rate'];
}else{
$day_rate = $v['day_rate'];
print_r($day_rate);
}
// Debug current variable $itemVar and new $day_rate
echo "itemVar=$itemVar;day_rate=$day_rate;"
}
$displayCounter++; // iterrate the inner counter
}
// iterrate the counter
$itemsCounter++;
// reset the inner counter for next loop
$displayCounter = 0;
// Debug inserts new line
echo PHP_EOL;
}
$totalPrice = $itemVar + $day_rate + $delivery_cost;

Maybe you just get the amount, it will solve your problem?
$sumHourlyRental = "SELECT SUM(hourly_rental) FROM products WHERE rental_status != 1 AND item_id = :var";

So to answer my own question, I needed to actually do the calculations within the function itself. It works as intended now
//Code on schedule.php page
//Find how many requested items there are
$items = explode(',', $requestedItems);
$item_name = array();
foreach ($items as $var){
$item_name[] = $products->priceChange($conn, $var, $hours);
}
$prices = 0;
foreach($item_name as $price){
$prices += $price;
}
$prices += $delivery_cost;
echo '<button type="button" class="btn" style="color:green;font-weight:bold;">$'.$prices.'</button>';
Then in the function, I added up the values.
public function priceChange($conn, $var, $hours){
$query = "SELECT * FROM products WHERE item_id = :id";
$stmt = $conn->prepare($query);
$stmt->bindParam(":id", $var);
$stmt->execute();
$result = $stmt->fetchAll();
if($stmt->rowCount() > 0){
$total = 0;
foreach($result as $row){
$hour_rate = $row['hour_rate'];
$day_rate = $row['day_rate'];
if($hours == '2'){
$total += $hour_rate;
}else{
if($row['hourly_rental'] == '1'){
$hours -= 2;
$total += $hour_rate + $day_rate * $hours;
}
else{
$total = $hour_rate + $day_rate;
}
}
}
return $total;
}
return false;
}

Related

While-Else Condition PHP

I know that my question might be similar with
while else statement? PHP.
However, that solution doesn't seem to work with my case.
So, in my case is something like this.
I do the select query from database to get all records then get the result in array
I get the total and period from the array
Do the checking, when the $qtyOut > $total, it will loop the statements inside the {}.
This is the problem here, AFTER LOOP ENDS, it should do else statement (call another function).
public function trialOut($id, $qtyOut)
{
$a = $this->uri->segment(3);
$dataset = $this->m1->trial($a);
$i = 0;
$sisa;
$total = $dataset[$i]['total'];
$period = $dataset[$i]['periode'];
if($qtyOut > $total){
while ($qtyOut > $total) {
$qtyOut = $qtyOut - $total;
$this->m1->updateOut2($period, $id);
$i++;
$total = $dataset[$i]['total'];
$period = $dataset[$i]['periode'];
}
} else{ //when while loop ends, i want it to execute the code here
$sisa = $total - $qtyOut;
$this->m1->updateOut1($period, $sisa, $id);
}
}
And I still can't found the proper way to do this, should I use another loop method and how to do that?
If - else statement is working by this logic. if condition under if statement is true code insde {} if(condition) {//this code is executed} will execute. However if condition = false code under else will execute. Having that in mind your else statement WILL NOT execute when $qtyOut > $total .
If you want to execute it after if statement just remove else and brackets.
If you want to execute it after while ends try this
public function trialOut($id, $qtyOut)
{
$a = $this->uri->segment(3);
$dataset = $this->m1->trial($a);
$i = 0;
$sisa;
$total = $dataset[$i]['total'];
$period = $dataset[$i]['periode'];
if($qtyOut > $total){
while ($qtyOut > $total) {
$qtyOut = $qtyOut - $total;
$this->m1->updateOut2($period, $id);
$i++;
$total = $dataset[$i]['total'];
$period = $dataset[$i]['periode'];
}
$sisa = $total - $qtyOut;
$this->m1->updateOut1($period, $sisa, $id);
}
}
If else explanation
Take this example
x = 5;
if( x = 5 ){
echo 'x is 5';
}
if( x != 5){
echo 'x is not five'
}
is the same code as
x = 5;
if( x = 5 ){
echo 'x is 5';
}else{
echo 'x is not five'
}
In first case you are checking if x = 5 and then if x is not equal to 5.
In second case you are checking if x = 5 and if it isn't only then else will execute

PHP How do I loop through pages of this api?

So basically I am trying to get the sum of AveragePrice of every single page on this api. Right now it only gets first page the things i've tried have only gotten it to go on an endless loop crashing wamp. Heres my code for 1 page of working.
I am just really unsure how I can get it to loop through pages and get sum of every page.
<?php
function getRap($userId){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=1&itemsPerPage=14");
$results = file_get_contents($url);
$json = json_decode($results, true);
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
echo $rap;
}
$userId = 1;
getRap($userId);
?>
You may get better answers by looking into the API you are working with regarding how many pages to look for. You want to loop until you hit the max pages. There should be an value in the result of your request that tells you that you've asked for a page that doesn't exist (ie. no more results). If you can get a total number of results to search for then you could do a for loop with that as your limit.
//Change the function to accept the page number as a variable
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=14");
//work out how many pages it takes to include your total items
// ceil rounds a value up to next integer.
// ceil(20 / 14) = ceil(1.42..) == 2 ; It will return 2 and you will look for two pages
$limit = ceil($totalItems / $itemsPerPage);
// Then loop through calling the function passing the page number up to your limit.
for ($i = 0; $i < $limit; $i++) {
getRap($userId, $i);
}
If you cannot get the total number of items, you could loop while a fail state hasn't occured
// look for a fail state inside your getRap()
function getRap($userId, $i) {
if ($result = error) { //you will have to figure out what it returns on a fail
$tooMany = TRUE;
}
}
for ($i = 0; $tooMany !== TRUE ; $i++) {
getRap($userId, $i);
}
Edit: Reviewing my answer, looking for the fail state inside your function is poor form (and won't work because of the scope of the variable in this case). You could pass the variable back and forth, but I'll leave that part up to you.
To get the total, make sure that your function doesn't print the result (echo $rap) but returns it for further use.
Full example
<?php
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=25");
$results = file_get_contents($url);
$json = json_decode($results, true);
if ($json['msg'] == "Inventory retreived!") {
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
return $rap;
} else {
return FALSE;
}
}
$total = 0;
$userId = 1;
for ($i = 0; $i < 1000 /*arbitrary limit to prevent permanent loop*/ ; $i++) {
$result = getRap($userId, $i);
if ($result == FALSE) {
$pages = $i;
break;
} else {
$total += getRap($userId, $i);
}
}
echo "Total value of $total, across $pages pages";
?>

Determine and do stuff in foreach loop except the last iteration

I am looping a foreach and i need to make some logic like this:
if the iteration is not the last. Gather up the prices. when the iteration is the last. subtract from the total with the gathered up prices. except the last iteration price. I got the following code not. but it's not working.
$i = 0;
$credit = '';
$count = count($reslist);
foreach ($reslist as $single_reservation) {
//All of the transactions to be settled by course
//$credit = $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
if ($i > $count && $single_reservation != end($reslist)) {
$gather_sum_in_czk += $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
$credit = $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
}
//Last iteration need to subtract gathered up sum with total.
else {
$credit = $suminczk - $gather_sum_in_czk;
}
$i++;
}
EDIT: TRYING TO GATHER UP PRICES FOR ALL INTERACTIONS EXECPT LAST:
if ($i != $count - 1 || $i !== $count - 1) {
$gather_sum_in_czk += $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
$credit = $this->Reservations_model->find_res_price($single_reservation['value']) * $this->input->post('currency_value');
}
else {
$credit = $suminczk - $gather_sum_in_czk;
}
The SPL CachingIterator is always one element behind its inner iterator. It can therefore report whether it will produce a next element via ->hasNext().
For the example I'm choosing a generator to demonstrate that this approach doesn't rely on any additional data like e.g. count($array).
<?php
// see http://docs.php.net/CachingIterator
//$cacheit = new CachingIterator( new ArrayIterator( range(1,10) ) );
$cacheit = new CachingIterator( gen_data() );
$sum = 0;
foreach($cacheit as $v) {
if($cacheit->hasNext()) {
$sum+= $v;
}
else {
// ...and another operation for the last iteration
$sum-=$v;
}
}
echo $sum; // 1+2+3+4+5+6+7+8+9-10 = 35
// see http://docs.php.net/generators
function gen_data() {
foreach( range(1,10) as $v ) {
yield $v;
}
}
foreach-ing an array in PHP returns both the key (integer index if pure array) and value. To be able to use the value, use the following construct:
foreach ($array as $key => $value) {
...
}
then you can check whether $key >= count($array) - 1 (remember in a 0-based array, the last element is count($array) - 1.
Your original code almost works, just wrong in the if condition. Use $i >= $count - 1 instead of $i > $count.

Compute everything inside foreach loop

I have foreach which consist of the list of candidates. I'm trying to compute the percentage inside the foreach then output the result. I don't know the problem, I want the program to compute the first if statement(talent), after going to the next if statement(distance), then continue the computation. The echo will display the overall computation of percentage. Please help. Thanks in advance
$counter = 0;
$status = array();
foreach($candidate as $c){
$queryResult = mysql_query("SELECT * FROM candidates WHERE id = '$c'");
$row = mysql_fetch_assoc($queryResult);
if($talent == "good"){
$status[$counter] = + 0.10;
}else if($talent == "better"){
$status[$counter] = + 0.05;
}
if($distance == "1200m"){
$status[$counter] = + 0.10;
}else if($distance == "1400m"){
$status[$counter] = + 0.05;
}
echo $status[$counter] * 100 . "%<br>";
$counter ++;
}//foreach end
how about changing those =+ with +=, perhaps that is what you want ..? (e.g., $status[$counter] += 0.10;)
and try to initialize this before the foreach loop..
$array = array_fill(0,$number_of_candidates, 0);

Split total into 5 different numbers

Ok what i'm wanting to do is split a number ($row['count']) into 5, this is easy enough if you want equal numbers:
$sum = ($row['count'] / 5);
$fsum = floor($sum);
but I want each number to be different and still add up to total ie $row['count'] how can this be achieved?
Update:
If this helps its to be used to update 5 rows in a database:
$query = "SELECT * FROM foo";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
$sum = ($row['count'] / 5);
$fsum = floor($sum);
$id = $row['id'];
$update = "UPDATE foo SET foo1='$fsum', foo2='$fsum', foo3='$fsum', foo4='$fsum', foo5='$fsum' WHERE id='$id'";
mysql_query($update);
}// while
so ideally the $update query would be something like:
$update = "UPDATE foo SET foo1='$fsum1', foo2='$fsum2', foo3='$fsum3', foo4='$fsum4', foo5='$fsum5' WHERE id='$id'";
This is my take:
function randomize($sum, $parts) {
$part_no = count($parts);
$continnue_counter = 0;
while (count(array_unique($parts)) != $part_no) {
$changing = array_rand($parts, 2);
if (($parts[$changing[0]] - 1) == 0 || ($parts[$changing[1]] - 1) == 0) { // don't let them go under 1
++$continnue_counter;
// sometime one element get everything and others even out on 1
// just throw away everything you got so far and start over
if ($continnue_counter > 10) {
$parts = setup($sum, $part_no);
$continnue_counter = 0;
}
continue;
}
$continnue_counter = 0;
$signum = mt_rand(0, 100) % 2 ? 1 : -1;
$delta = $signum * mt_rand(1, min($parts[$changing[0]] - 1, $parts[$changing[1]] - 1)); // -1 to make sure they don't go under 0
$parts[$changing[0]] += $delta;
$parts[$changing[1]] -= $delta;
}
return $parts;
}
function setup($sum, $part_no) {
$parts = array_fill(0, $part_no, (int)($sum / $part_no));
// acount for the reminder of (int) cast
$reminder = $sum - array_sum($parts);
while ($reminder) {
$parts[array_rand($parts)] += 1;
--$reminder;
}
return $parts;
}
$part_no = 5;
$sum = 42;
$parts = randomize($sum, setup($sum, $part_no));
var_export($parts);
print array_sum($parts)
Update:
I've added a version that introduces a little more entropy.
Update2:
The more random one had a tendency to decrement everything to 1 except one part, added an explicit detection to deal with this. Still the algorithm behind it has unknown termination time.

Categories