PHP & MySQL: While Loop - php

first, i am pretty new to PHP and MySQL, so i still code precedurally.
I am working on an application that takes transactions and pays out a due amount at a certain maturity date to users who have previously made a donation. i have a function knapSolveFast2 that solves the knapsack problem (where a set of transaction amounts in a database adds up to a due amount for a users who's maturity date is up). currently, my demo database looks like this:
if my current date (now) = 2017-04-03 11:36:03 = CAST(NOW() AS DATETIME), my application is meant to loop through the database, fetch users whose maturity_date is >= 1 month from tran_date (i.e. WHERE maturity_date <= CAST(NOW() AS DATETIME) ). Take each user found and pair them for payment in a while loop to other users tran_amt in the database whose tran_amt sums up to the maturity users found due_amount using the knapsack function knapSolveFast2.
Question:
after finding the user with maturity date due for payment (2 users) with the first while loop, i am trying to run an inner while loop to pair each user to other users whose tran_amt sums up to the fetched user's due amount. the problem here is, the inner while loop only runs for the first user found an not for thesecond user.
The code
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "test";
$connect = #mysqli_connect($servername, $username, $password, $dbname);
if (mysqli_connect_errno()) {
die("<pre><h1>Sorry, we are experiencing a little Downtime!</h1></pre>");
}
//include the match controller containing the knapSolveFast2 function
include('controller/match.php');
//UPDATE `pendingpair`SET `maturity_date`= DATE_ADD(`tran_date`, INTERVAL 1 MONTH)
//select user to be paid
$sql = "SELECT `user_id`, `due_payment` FROM `pendingpair` where `maturity_date` <= CAST(NOW() AS DATETIME) ORDER BY `id` ASC";
$queryRun = mysqli_query($connect, $sql);
$num_rows = mysqli_num_rows($queryRun);
if ($num_rows > 0) {
while ($row = mysqli_fetch_assoc($queryRun)) {
$user_id_due = $row['user_id'];
$user_amt_due = $row['due_payment'];
print_r($row);
/* Perform queries to select users to pay $user_id_due the sum of $user_amt_due; Where:
- user to be paid, $user_id_due, is not included in the pairing logic
- transacton payment to be chosen, ph_conf = 1, has been confirmed
- transaction has not yet been paired for payment, tran_paired_status = 0
- transactions have not been flaged for fake POP (proof of Payment), `ph_denied_fpop`= 0
*/
$fetchQuery = "SELECT `tran_inv`, `tran_amt`, `user_id` FROM `pendingpair`WHERE `tran_amt` <= {$user_amt_due} && `user_id` != {$user_id_due} && `ph_conf`=1 && `tran_paired_status` = 0 && `ph_denied_fpop`=0 ORDER BY `id`";
$m = array(); // Match Memo items array
$picked_trans = array();
$numcalls = 0; // number of calls made to get Match
$tran_inv = array();
$tran_amt = array();
$user_id = array();
//run query and throw users that fit the criteria into an array
if ($queryRun = mysqli_query($connect, $fetchQuery)) {
//check if data was pulled
if (mysqli_num_rows($queryRun) != NULL) {
//grab data from array and insert it into an array
while ($row = mysqli_fetch_assoc($queryRun)) {
//Populate Arrays to be used
$tran_amt[] = $row['tran_amt'];
$tran_inv[] = $row['tran_inv'];
$user_id[] = $row['user_id'];
}
}
}
## Solve
list ($m4,$pickedItems) = knapSolveFast2($tran_amt, $tran_amt, sizeof($tran_amt) -1, $user_amt_due, $m);
# Display Result
echo "<b><br><br>Invoice:</b><br>".join(", ",$tran_inv)."<br>";
echo "<b>Tran Amt:</b><br>".join(", ",$tran_amt)."<br>";
echo "<b>User_id:</b><br>".join(", ",$user_id)."<br>";
echo "<b>Max Value Found:</b><br>$m4 (in $numcalls calls)<br>";
}
}
?>
the result of the first while loop that finds user with the proper maturity date criteria is:
Array
(
[user_id] => 9
[due_payment] => 150
)
Array
(
[user_id] => 2
[due_payment] => 150
)
this means 2 users are due. but on trying to loop these users. the match for the second user is never found... only that of the first user is.
Array
(
[user_id] => 9
[due_payment] => 150
)
Invoice:
1102, 9022, 9113, 9029, 9116
Tran Amt:
100, 50, 100, 50, 50
User_id:
2, 5, 8, 5, 7
Max Value Found:
150 (in 19 calls)
Please help me figure out what i am missing. Thaaaaank you :)

Your problem is that you call the variables the same thing.
If you look at :
while ($row = mysqli_fetch_assoc($queryRun)) //External loop
Inside that loop you have another
while ($row = mysqli_fetch_assoc($queryRun)) //Internal loop
So the variables inside the external loop, you are using for the internal loop are essentially overwriting the External loops variables, and thus when it is time for the second run of your External loop, the code think it is done, since it is refering to the internal loops variable
To fix this, you must rename the variables you use for the internal loop

Note SECOND_ for both the queryRun and the row
Try this:
if ($SECOND_queryRun = mysqli_query($connect, $fetchQuery)) {
//check if data was pulled
if (mysqli_num_rows($SECOND_queryRun) != NULL) {
//grab data from array and insert it into an array
while ($SECOND_row = mysqli_fetch_assoc($SECOND_queryRun)) {
//Populate Arrays to be used
$tran_amt[] = $SECOND_row['tran_amt'];
$tran_inv[] = $SECOND_row['tran_inv'];
$user_id[] = $SECOND_row['user_id'];
}
}
}

Related

pHp Issue: "Waiting for localhost": Maybe infinite loop issue?

I am currently working on an elo based matchmaking system. Basically, I have a database where there are a bunch of users, each having their respective ratings.
Brief explanation of code, it chooses one user at random, and chooses another user if the second user is within +-100 difference-elo of the first user (so grandmasters don't play with bronze players). If there is no one within 100 elo, the difference-elo increments by 50 and checks again.
Problem: I created a test user that is 100 elo more than the other users to test the matchmaking system. The program works except for when the first selected player is my test user. The page never loads and it is stuck on "Waiting for localhost". I assumed this meant one of my while loops was going on infinitely, but after spending sometime editing them and trying to figure out why they might be going on infinitely, the error still persists.
<?php
include('mysql.php');
include('functions.php');
$result2 = executeQuery("SELECT * FROM images ORDER BY score DESC");
function executeQuery($query2){
$connect = mysqli_connect("localhost", "root", "password","database");
$result2 = mysqli_query($connect, $query2);
return $result2;
}
// Get random
$query="SELECT * FROM images ORDER BY RAND() LIMIT 0,1";
$result = #mysqli_query($connection, $query);
//Put random in images array
while($row = mysqli_fetch_object($result)) {
$images[] = (object) $row;
}
//Get elo of random
$elo1 = $images[0]->score;
--------------------------
//Point of Interest Below
--------------------------
//Sort database by DESC. Then go through entire database. If current row's elo is with +- difference (which right now is 100) of elo1's rating, ($elo1-100 < x < $elo1+100), then put into new array with all matchups.
//Get length of array, if length is 0 (meaning no match ups were found), increase difference by 50 and try again.
$potentialMatchup = [];
$diff = 100;
$arrayLength = count($potentialMatchup);
while ($arrayLength == 0){
$diff += 50;
while($row2 = mysqli_fetch_object($result2)){
if(($row2->score > $elo1-$diff) && ($row2->score < $elo1+$diff)){
$potentialMatchup[] = (object) $row2;
}
}
$arrayLength = count($potentialMatchup);
}
-------------------------------
//Get random index between 0 and length of array.
$randomNumber = rand(0, $arrayLength-1);
//Put match up into images array
$images[1] = (object) $potentialMatchup[$randomNumber];
//Get names of images
$nameLeft = $images[0]->filename;
$nameRight = $images[1]->filename;
//If same person, pick another random
while($nameLeft == $nameRight){
$randomNumber = rand(0, $arrayLength-1);
$images[1] = (object) $potentialMatchup[$randomNumber];
$nameRight = $images[1]->filename;
}
// Close the connection
mysqli_close($connection);
$leftName = str_replace("_", " ", $images[0]->filename);
$rightName = str_replace("_", " ", $images[1]->filename);
?>

How to get Fetch_array data

I am making Tournament mod. And I do not know how to correctly do some operations with fetched array.
What my code is doing, is that it takes data from Tournament table and add it to array. Then print it in HTML table, so all users can see the place where he has.
How can I correctly get the first, second, third array data for the first 3 winners and give them a price? And how can I deal with players who have the same amount of points?
Right now the query below seems to not work too, all statements are positiv and it should execute the function.
if($counter == 1) {
$GLOBALS['DATABASE']->query("UPDATE ".USERS." SET `atm` = `atm` + 20000 WHERE `id` = ".$recordRow['id_owner']." ;");
}
Sorry, my English is not good and I tried to search for the answers but didn't find anything, because i do not know for what PHP solution should i search.
My code:
$recordFetch = $GLOBALS['DATABASE']->query("SELECT *FROM `uni1_tournament` ORDER BY wons DESC;");
$counter = 0;
$RangeList = array();
while ($recordRow = $GLOBALS['DATABASE']->fetch_array($recordFetch)) {
$counter += 1;
$RangeList[] = array(
'id' => $recordRow['id_owner'],
'name' => $recordRow['name'],
'points' => $recordRow['wons']*5,
'counter' => $counter,
);
if($t_time > TIMESTAMP) {
if($counter == 1) {
$GLOBALS['DATABASE']->query("UPDATE ".USERS." SET `atm` = `atm` + 20000 WHERE `id` = ".$recordRow['id_owner']." ;");
}
elseif($counter == 2) {
//to do;
} elseif($counter == 3) {
//to do;
}
}
}
Make query like this "select * from uni1_tournament GROUP BY points ORDER BY
points desc limit 3";
If you're using regular mysql or mysqli (been a while since I have for either, moved to doctrine a while back), fetch_array needs to be ran on the results and not the GLOBALS['DATABASE'] variable (guessing this a global variable for the database connection).
Try changing
while ($recordRow = $GLOBALS['DATABASE']->fetch_array($recordFetch)) {
to
while ($recordRow = $recordFetch->fetch_array()) {
In order to use your original formatting, I believe fetch_array needed to be mysqli_fetch_array instead.
i.e
while ($recordRow = $GLOBALS['DATABASE']->mysqli_fetch_array($recordFetch)) {

PHP foreach loop running one extra time

I am having a bit of trouble with this for loop here and hope to get some help !
So I will recreate a simplified version of the loop here:
foreach($quote as $key => $item) {
if(isset($item['dbid'])){
$q_sql = new mysql_builder2('quote',3);
} else {
$q_sql = new mysql_builder2('quote',2);
}
$q_sql->addArgument('name', $name);
$q_sql->addArgument('curr', $curr);
foreach($term[$key] as $data) {
if(isset($data['term_id']) {
$t_sql = new mysql_builder2('details',3);
} else {
$t_sql = new mysql_builder2('details',2);
}
$t_sql->addArgument('date', $date);
$t_sql->addArgument('term', $termnum);
mysqli_query($dbc, $t_sql->build());
}
mysqli_query($dbc, $q_sql->build());
}
Okay, so I think I got it all right here.
EDIT: Before the loops I have the following :
$quote = $_POST['quotes'];
$term = $_POST['terms'];
Inside the HTML the name of these elements is structured like so:
quotes[1][name]
quotes[1][curr]
terms[1][1][date]
terms[1][1][termnum]
and then if there's a second:
quotes[2][name]
quotes[2][curr]
terms[2][1][date]
terms[2][1][termnum]
terms[2][2][date]
terms[2][2][termnum]
etc..
Explaination:
First, mysqli_builder2 is a premade function that creates SQL queries.. When the value is 3, it sets UPDATE, when it's 2 it does INSERT
Now, what will happen is a user will fill out a form and the data will go into two tables, Quote and Details. For each single entry into Quote, there can potentially be multiple in Details (note: I've left out a lot of fields in my example code to save space but there are links between the 2 tables).
My problem here is when I run this for a very simple UPDATE, the second foreach loops runs one extra time always, and it is always an INSERT with random values for each field.. I can't seem to figure why this is happening because it works 100% properly for the first foreach loop..
Example array output when submit:
Array
(
[0] => UPDATE quote SET job_id = 2, wo_id = 9952, quote_num = '1a', revenue = '100.00', cost = '100.00', currency = 1, term = 1 WHERE id = 5857;
)
Array
(
[0] => UPDATE details SET user_id = 532, job_id = 2, wo_id = 9952, quote_num = '1a', percent = 10, term = 1, active = 1, status = 0, date_picked = '2015-02-04', date_submitted = now() WHERE id = 588;
[1] => INSERT INTO details(user_id, job_id, wo_id, quote_num, percent, term, active, status, date_picked, date_submitted) VALUES(532, 2, 9952, '1a', 6, 6, 1, 0, '1969-12-31', now());
)
This INSERT should not be there at all (notice the date going in) ..
Anyways, I'm kind of stuck here and any help is appreciated. If you need any other info just ask :)
Thanks !
Are you sure you copy the code as is?
you have got syntax error:
if(isset($data['term_id']) {
should be:
if(isset($data['term_id'])) {

how to identify unsaved value from database using php mysql

I have to identify unsaved value from mysql table using php and mysql, for example i using table named as numtab and i have already stored some numbers 1, 3, 4, 7, 23, 12, 45 in numb column.
now i have generated one new number randomly(for example 23) and i have to check this number with already stored numbers,
if 23 is exist in the table mean i have to generate another one new number and have to check once again with stored values, this process have to continue till finding unsaved number.
if generated value is not exist in table mean can stop the process and can store this number in table.
here below the format i am currently using
$numb=23;
$qryb="select * from numtab where numb='$numb'";
$results=mysql_query($qryb)or die("ERROR!!");
if(mysql_num_rows($results) == 1)
{
$numb=rand(1,100);
mysql_query("insert query");
}
the problem is above the code is validation once only, its not verifying second time. i think if using for or while loop mean can solve this problem, but i dont know how to do looping, so help me to solve this problem.
You can use in clause like this :
$qryb="select * from numtab where numb in('$numb')";
$results=mysql_query($qryb)or die("ERROR!!");
$count = mysql_num_rows($results);
if ($count > 0) {
echo "number exist in db";
} else {
echo "number does not exist in db";
}
You could make a while() loop to check if the numbers exist in your database. You could also retrieve all numbers from the database, store them in an array and check if the generated number exists within that array.
The first option would be something like this:
do {
$numb=rand(1,100);
$qryb="select * from numtab where numb='$numb'";
$results = mysql_query($qryb) or die("ERROR!!");
} while(mysql_num_rows($results) >= 1)
mysql_query("insert query");
The second option would be something like this:
$query = mysql_query("SELECT DISTINCT(numb) as numb FROM numtab");
// set array
$array = array();
// look through query
while($row = mysql_fetch_assoc($query)){
// add each row returned into an array
$array[] = $row['numb'];
}
do
{
$numb = rand(1,100);
}
while(!in_array ( $numb , $array) ;
mysql_query("insert query");

MySQL queries optimization

So I've been working on an IRC game for one year now, written in PHP and using a PHP to IRC framework.
Recently, I've added the ability to archive scores (they're being reseted every couple hundreds of games) which forced me to update various admin functions.
I've just updated a function that allows me to merge two players (some users don't bother looking for their old password etc...) in order to merge archived scores too (in case a reset has occurred before I find the duplicated accounts).
The score-merging part (below) works has intended, but I'm wondering if I can optimize the process because I find it rather heavy (but can't think of something better) :
$from_stats = $this->db->query("SELECT `games`, `wins`, `points`, `date_archive` FROM ".$this->dbprefix."score WHERE `id`=".$id1." AND `channel`='".$gamechan."' GROUP BY `date_archive`"); // get scores for the original account
$to_stats = $this->db->query("SELECT `games`, `wins`, `points`, `date_archive` FROM ".$this->dbprefix."score WHERE `id`=".$id2." AND `channel`='".$gamechan."' GROUP BY `date_archive`"); // get scores for the duplicated account
$from_games = array();
$from_wins = array();
$from_points = array();
$from_date = array();
while (list($fromstats_games,$fromstats_wins,$fromstats_points,$fromstats_date) = $this->db->fetchRow($from_stats)) { // build score arrays for the original account
$from_games[count($from_games)] = $fromstats_games;
$from_wins[count($from_wins)] = $fromstats_wins;
$from_points[count($from_points)] = $fromstats_points;
$from_date[count($from_date)] = $fromstats_date;
}
$to_games = array();
$to_wins = array();
$to_points = array();
$to_date = array();
while (list($tostats_games,$tostats_wins,$tostats_points,$tostats_date) = $this->db->fetchRow($to_stats)) { // build score arrays for the duplicated account
$to_games[count($to_games)] = $tostats_games;
$to_wins[count($to_wins)] = $tostats_wins;
$to_points[count($to_points)] = $tostats_points;
$to_date[count($to_date)] = $tostats_date;
}
foreach ($from_date as $key1 => $id1_date) {
foreach ($to_date as $key2 => $id2_date) {
if ($id1_date == $id2_date) { // merge scores if dates match
$from_games[$key1] += $to_games[$key2];
$from_wins[$key1] += $to_wins[$key2];
$from_points[$key1] += $to_points[$key2];
$this->db->query("UPDATE ".$this->dbprefix."score SET `games`=".$from_games[$key1].", `wins`=".$from_wins[$key1].", `points`=".$from_points[$key1]." WHERE `id`=".$id1." AND `channel`='".$gamechan."' AND `date_archive`='".$id1_date."'");
break;
}
}
}
$this->db->query("DELETE FROM ".$this->dbprefix."score WHERE `id`=".$id2); // delete all entries for the duplicated account
Just one tip: after all use this query (if You have appropriate privilages)
$this->db->query("OPTIMIZE TABLE ".$this->dbprefix."score");
This should cause all indexes in this table to be recalculated. You'll notice the index file size has changed to 1kb (or few bytes)

Categories