While-Else Condition PHP - 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

Related

how to get sum of dynamic values from array

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;
}

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";
?>

Check if Variable is smaller than others, and which one its smaller than. PHP

I have been working on my scoring system and came accros this.
I have 4 vars.
$newscore
$score1
$score2
$score3
I want to see if new score is lower than the 3 others, and if so which ones. The scoring system requires you to have the lowest possible score.
I have the following code:
if($newscore > $score1){
if($newscore > $score2){
if($newscore < $score3){
//has to be score3 to replace.
}
}else{
...
}
}
But what I'm wondering is if I will have to continue on with all these if statements, or is there something a lot shorter and easier? I need to replace the the score that it is smaller than, but not the one its larger than. Score 1 2 and 3 are all the players stats. And if I do have to continue on with all the if statements, how would the code look (its baffling my logic)?
you should probably use an array
$scores = array(8, 15, 10); //previous scores
$new_score = 5;
$new_score_smallest = true;
foreach($scores as $score) {
if($score < $new_score) {
$new_score_smallest = false;
}
}
if($new_score_smallest) {
echo "Best score!";
}
else {
echo "Not the best score :(";
}
If you only want to remember the 3 best scores:
$scores = array(5, 6, 8);
$new_score = 7;
for($i = 0; $i < count($scores); $i++) {
if($new_score < $scores[$i]) {
$scores[$i] = $new_score;
break;
}
}
You could do something like the following:
EDIT: As you're using a database, you would execute the query similar to this:
SELECT scores FROM scores_table replacing the table name and column name with your corresponding data.
$scores = [$score1, $score2] // add as many as you like
$new_score = $scores[0]; // assign a baseline
foreach ($scores as $score) {
if ($score < $new_score) {
$new_score = $score;
}
}
Hope that helps.
You can use array_search and min
$newscore = 2;
$scores = array($score1, $score2, $score3);
if($newscore < min($scores)){
$scores[array_search(min($scores), $scores)] = $newscore;
}
array $score lowest score will be updated if $newscore is inferior
Put your scores in an array or anything iterable (like a query result, whether you use PDO or mysqli).
Let's say your scores are in $scores array (it will be the same if $score is a PDOStatement for example) and ordered (use ORDER ASC in your query):
$scores = [105, 201, 305];
$newscore = '186';
$hiscore = false;
$beaten = [];
foreach ($score as $k => $score) {
if ($newscore > $score) {
$hiscore = true;
$beaten[] = $score;
unset($scores[$k]);
}
}
if ($hiscore) {
echo 'New high score!'.PHP_EOL;
echo 'Better than '.implode(', ', $beaten).PHP_EOL;
echo 'But not better than '.implode(', ', $scores);
} else {
echo 'Try harder!';
}
<?php
$newscore = 78;
$score1 = 23;
$score2 = 201;
$score3 = 107;
$max = max([$score1, $score2, $score3]);
if ($max < $newscore) {
echo "New best score ! ({$newscore})";
} else {
echo "Not the best score !\nCurrent: {$newscore}\nBest: {$max}";
}

How to exclude MySQL query from my loop (limit unnecessary queries)

I'm asking MySQL for data, but it slows down the whole script. Yet I have no idea how to get this out of a loop. I tried converting it to PHP array but honestly after day of tries I failed.
<?php
$id = '1';
include_once 'include_once/connect.php';
for ($x = 1; $x <= 5; $x++) {
for ($y = 1; $y <= 5; $y++) {
$xy = $x."x".$y;
$pullMapInfo = "SELECT value FROM mapinfo WHERE id='".$id."' AND xy='".$xy."'";
$pullMapInfo2 = mysql_query($pullMapInfo) or die('error here');
if ($pullMapInfo3 = mysql_fetch_array($pullMapInfo2)) {
#some code
} else {
#some code
}
}
}
?>
How to get MySQL query $pullMapInfo2 out of loop to shorten loading it by asking once?
If you want to fire script on your localhost you can c&p whole thing :-)
I'm not sure what you have in your table, but considering you are basically looping through virtually everything in it, I'd say do a single query for the given Id and then sort out what you need from the larger dataset.
Especially if you are always pulling back essentially the complete dataset for each id, there's no reason to even bother with the IN query, just pull it all back into a single PHP array, and then iterate through that as needed.
Use a MySQL IN clause
<?php
$id = '1';
include_once 'include_once/connect.php';
// first we create an array with all xy
$array = array();
for ($x = 1; $x <= 5; $x++) {
for ($y = 1; $y <= 5; $y++) {
$xy = $x."x".$y;
$array[] = $xy;
}
}
$in = "'" . implode("', '", $array) . "'";
$pullMapInfo = "SELECT xy, value FROM mapinfo WHERE id='".$id."' AND xy IN ({$in})";
$pullMapInfo2 = mysql_query($pullMapInfo) or die('error here');
// we create an associative array xy => value
$result = array();
while (($pullMapInfo3 = mysql_fetch_assoc($pullMapInfo2)) !== false) {
$result[ $pullMapInfo3['xy'] ] = $pullMapInfo3['value'];
}
// we make a loop to display expected output
foreach ($array as $xy)
{
if (array_key_exists($xy, $result)) {
echo '<div class="castle_array" style="background-image: url(tiles/'.$result[$xy].'.BMP)" id="'.$xy.'">'. $result[$xy] .'</div>';
} else {
echo '<div class="castle_array" id="'.$xy.'"></div>';
}
echo '<div class="clear_both"></div>';
}
?>

PHP "Maximum execution time"

I'm trying to program my own Sine function implementation for fun but I keep getting :
Fatal error: Maximum execution time of 30 seconds exceeded
I have a small HTML form where you can enter the "x" value of Sin(x) your looking for and the number of "iterations" you want to calculate (precision of your value), the rest is PhP.
The maths are based of the "Series definition" of Sine on Wikipedia :
--> http://en.wikipedia.org/wiki/Sine#Series_definition
Here's my code :
<?php
function factorial($int) {
if($int<2)return 1;
for($f=2;$int-1>1;$f*=$int--);
return $f;
};
if(isset($_POST["x"]) && isset($_POST["iterations"])) {
$x = $_POST["x"];
$iterations = $_POST["iterations"];
}
else {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
if(isset($x) && is_numeric($x) && isset($iterations) && is_numeric($iterations)) {
$x = floatval($x);
$iterations = floatval($iterations);
for($i = 0; $i <= ($iterations-1); $i++) {
if($i%2 == 0) {
$operator = 1;
global $operator;
}
else {
$operator = -1;
global $operator;
}
}
for($k = 1; $k <= (($iterations-(1/2))*2); $k+2) {
$k = $k;
global $k;
}
function sinus($x, $iterations) {
if($x == 0 OR ($x%180) == 0) {
return 0;
}
else {
while($iterations != 0) {
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
$iterations = $iterations-1;
return $result;
}
}
}
$result = sinus($x, $iterations);
global $result;
}
else if(!isset($x) OR !isset($iterations)) {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
else if(isset($x) && !is_numeric($x)&& isset($iterations) && is_numeric($iterations)) {
$error = "Not a valid number.";
global $error;
}
?>
My mistake probably comes from an infinite loop at this line :
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
but I don't know how to solve the problem.
What I'm tring to do at this line is to calculate :
((pow($x, $k)) / (factorial($k)) + (((pow($x, $k))/(factorial($k)) * ($operator)
iterating :
+ (((pow($x, $k))/(factorial($k)) * $operator)
an "$iterations" amount of times with "$i"'s and "$k"'s values changing accordingly.
I'm really stuck here ! A bit of help would be needed. Thank you in advance !
Btw : The factorial function is not mine. I found it in a PhP.net comment and apparently it's the optimal factorial function.
Why are you computing the 'operator' and power 'k' out side the sinus function.
sin expansion looks like = x - x^2/2! + x^3/3! ....
something like this.
Also remember iteration is integer so apply intval on it and not floatval.
Also study in net how to use global. Anyway you do not need global because your 'operator' and power 'k' computation will be within sinus function.
Best of luck.
That factorial function is hardly optimal—for speed, though it is not bad. At least it does not recurse. It is simple and correct though. The major aspect of the timeout is that you are calling it a lot. One technique for improving its performance is to remember, in a local array, the values for factorial previously computed. Or just compute them all once.
There are many bits of your code which could endure improvement:
This statement:
while($iterations != 0)
What if $iterations is entered as 0.1? Or negative. That would cause an infinite loop. You can make the program more resistant to bad input with
while ($iterations > 0)
The formula for computing a sine uses the odd numbers: 1, 3, 5, 7; not every integer
There are easier ways to compute the alternating sign.
Excess complication of arithmetic expressions.
return $result is within the loop, terminating it early.
Here is a tested, working program which has adjustments for all these issues:
<?php
// precompute the factorial values
global $factorials;
$factorials = array();
foreach (range (0, 170) as $j)
if ($j < 2)
$factorials [$j] = 1;
else $factorials [$j] = $factorials [$j-1] * $j;
function sinus($x, $iterations)
{
global $factorials;
$sign = 1;
for ($j = 1, $result = 0; $j < $iterations * 2; $j += 2)
{
$result += pow($x, $j) / $factorials[$j] * $sign;
$sign = - $sign;
}
return $result;
}
// test program to prove functionality
$pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620;
$x_vals = array (0, $pi/4, $pi/2, $pi, $pi * 3/2, 2 * $pi);
foreach ($x_vals as $x)
{
$y = sinus ($x, 20);
echo "sinus($x) = $y\n";
}
?>
Output:
sinus(0) = 0
sinus(0.78539816339745) = 0.70710678118655
sinus(1.5707963267949) = 1
sinus(3.1415926535898) = 3.4586691443274E-16
sinus(4.7123889803847) = -1
sinus(6.2831853071796) = 8.9457384260403E-15
By the way, this executes very quickly: 32 milliseconds for this output.

Categories