PHP: While loop only running once, should run many times - php

First time tackling a project where i'm needing to pull data from one table (lets say 200 records/results), and based on the results of a certain column within that result set, i need to query one of my 5 other tables (which table i need to query isnt defined until i've made the first query)
I'm currently under the impression there is no way for me to use a JOIN of some kind to do this as i cannot know which table i need to join before the first set of results have come back.
so the solution i came up with was as follows (example code for simplicity sake)
$FirstTableVals = array();
$sql = ("SELECT * FROM TABLE_A");
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
foreach($row as $key => $value)
{
$FirstTableVals[$key] = $value;
}
$valueToSwitch = $FirstTableVals["VAL_TO_SWITCH"];
//$SecondTable can be 1 of 5 different table names
$SecondTable = $FirstTableVals["SECOND_TABLE_TO_QUERY"];
switch ($valueToSwitch)
{
case"1":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_COLUMN = SOME_VALUE");
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
case"2":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_OTHER_COLUMN = SOME_OTHER_VALUE");
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
default:
break;
}
}
}
Now, the problem i'm running into is that once one of the "Second" sql queries is executed, after performing everything within the "Second" While loop, it will break out of the while loop its in and echo my values but stops there without breaking out of the switch statement and then running again, due to the "First" sql queries loop.
Essentially, this only seems to run for the first record inside of "TABLE_A" as opposed to looping again and executing the switch statement with "Second" sql queries for each record inside of "TABLE_A".
If any of this doesn't make any sense, please let me know and i'll do my best to elaborate on anything that may be confusing.
Really stumped with this one as it seems to me that should run as i've intended.

You are overridding the run variable, thats why it breaks the loop. Please change your code like this:
$FirstTableVals = array();
$sql = ("SELECT * FROM TABLE_A");
$run1 = $con->query($sql);
if($run1->num_rows > 0)
{
while($row = $run1->fetch_assoc())
{
foreach($row as $key => $value)
{
$FirstTableVals[$key] = $value;
}
$valueToSwitch = $FirstTableVals["VAL_TO_SWITCH"];
//$SecondTable can be 1 of 5 different table names
$SecondTable = $FirstTableVals["SECOND_TABLE_TO_QUERY"];
switch ($valueToSwitch)
{
case"1":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_COLUMN = SOME_VALUE");
$run2 = $con->query($sql);
if($run2->num_rows > 0)
{
while($row = $run2->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
case"2":
$sql = ("SELECT * FROM $SecondTable WHERE SOME_OTHER_COLUMN = SOME_OTHER_VALUE");
$run3 = $con->query($sql);
if($run3->num_rows > 0)
{
while($row = $run3->fetch_assoc())
{
//save some values from the second table
}
}
//echo the results of TABLE_A and second table
break;
default:
break;
}
}
}

Related

My for loop only allows one post to be displayed, over and over again

/* To sort the id and limit the post by 40 */
$sql = "SELECT * FROM requests";
$result = $conn->query($sql);
$sqlall= "SELECT * FROM requests ";
$resultall = $conn->query($sqlall);
$i = 0;
if ($result->num_rows > 0) {
// Output data of each row
$idarray= array();
while($row = $result->fetch_assoc()) {
echo "<br>";
// Create an array to store the
// id of the blogs
array_push($idarray,$row['id']);
}
}
else {
echo "0 results";
}
?>
<?php
for($x = 1; $x < 40; $x++) {
// This is the loop to display all the stored blog posts
if(isset($x)) {
$query = mysqli_query(
$conn,"SELECT * FROM `requests`");
$res = mysqli_fetch_array($query);
$email1 = $res['email1'];
$msg1= $res['msg1'];
$subject1 = $res['subject1'];
$name1 = $res['name1'];
$id = $res['id'];
the output is 40 cards reading data from the first row in my database. can anyone help?
I'm using xampp.
This code is to show the loop, but if anyone wants the full code is here
You are storing all the IDs in the array $idarray, but then you don't really use them properly. You loop over them, but you just run SELECT * FROM requests` 40 more times, and always extract the same first row. You never use the ID to change the query.
But it really makes no sense to run lots of separate queries anyway. If you just want the first 40 rows then use MySQL's LIMIT keyword. It usually works best when combined with ORDER BY as well. Something like this:
$sql = "SELECT * FROM requests ORDER BY id LIMIT 40";
$result = $conn->query($sql);
while ($res = $result->fetch_assoc()) {
$email1 = $res['email1'];
$msg1 = $res['msg1'];
$subject1 = $res['subject1'];
$name1 = $res['name1'];
$id = $res['id'];
//example output, just for demo:
echo $email1." ".$msg1." ".$subject1." ".$name1." ".$id;
}
Documentation: https://dev.mysql.com/doc/refman/8.0/en/limit-optimization.html

PHP-reaching more data at once

How can I make in PHP, that from my SQL baze are written all data, if value parent is not 0 from the same table, it find value from the line, which is the same idas parent.
I check this but I want data from one table.
Similar as below written, but in one query:
$query = "SELECT * FROM posts ORDER BY date DESC;";
$result = $mysqli->query($query);
while($rez = $result->fetch_assoc()) {
$query="SELECT * FROM ".$dbPrefix."posts WHERE
id=".$rez['parent']."";
$parents = $mysqli->query($query);
while($parent = $parents->fetch_assoc()) {
$parentName=$parent['name'];
}
}

PHP check if ID already is in use

I am currently busy with creating my own 6 player game based on PHP/MySQL. I want to check if the ID from players_online is already in use, if yes then it need to keep searching until it found one (till max 6) else it need to return 0;
$con is the connection to the database and you can find the settings on the .mysql_config.php
This is what I got:
function find_local_id()
{
include'./mysql_config.php';
$i=1;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
return 0;
} else {
return 6;
}
} else {
return 5;
}
} else {
return 4;
}
} else {
return 3;
}
} else {
return 2;
}
} else {
return 1;
}
Is there a way to have this smaller/compact? Because I think this is pretty big for just a small function. :)
I think this would work:
function find_local_id()
{
include'./mysql_config.php';
$result = mysqli_query($con, "SELECT `ID` FROM `players_online`");
while($row = mysqli_fetch_assoc($result)) {
$ids[] = $row['ID'];
}
if($available = array_diff(range(0, 6), $ids)) {
return min($available);
}
return 0;
}
If you have mysqli_fetch_all use that.
Get all of the IDs in the table
See which ones (1-6) are not in the results
If any are available return the lowest one
If not return 0
First of all, you could use a loop to do this (but you don't need one).
You're hitting the DB many times unnecessarily.
Create a function or query (like the one below) that accepts one integer id and returns the count of rows.
<?php
$db = new PDO('mysql:host=localhost;dbname=yourdb', 'user', 'pass');
$id = ''; //input, whether it be a param from a function, session superglobal, GET or POST.
$exists = $db->prepare('SELECT id FROM players_online WHERE id = ?');
$exists->execute(array($id));
echo $exists->rowCount(); // if greater than 1 or equal, it exists.
You'd be far better off doing something like
$sql = "SELECT * FROM players_online WHERE id BETWEEN {$i} AND {$i}+6";
$stmt = mysqli_query($con, $sql) or die(mysqli_error($con));
$in_use = mysqli_num_rows($stmt);
If all 6 IDs are in the database, then you'll get 6 rows in $in_use. If 5 show up, then you'll get 5 rows, etc...
You seem to have a really flawed design in that you are never going to scale for more than one game at at time with this approach, are going to need to delete rows from your table to make it work when generating a new game, and are going to have problems with race conditions in cases where concurrency is high. But assuming you have a means for managing inserting player record id's in order (1,2,3, etc.). Your query can simply be:
SELECT MAX(id) FROM players_online
This will tell you the current highest id in the table. You would simply insert the next player with the id value incremented by 1 above the current max value.

Im trying to loop through a recordset of class numbers to then query supplies from another recordset using mysql and php

I have these recordsets an I'm faking a $_POST in between the queries to use a values from the first query to get values from the second query, in this manner I get the first row of many, I've tried a foreach loop in-between the queries and fail...
How do I loop through the first recorset rows as many are returned?.... the code is:
$maxRows_rs_all_classes = 50;
$pageNum_rs_all_classes = 0;
if (isset($_GET['pageNum_rs_all_classes'])) {
$pageNum_rs_all_classes = $_GET['pageNum_rs_all_classes'];
}
$startRow_rs_all_classes = $pageNum_rs_all_classes * $maxRows_rs_all_classes;
mysql_select_db($database_conn_studiogear_mgr, $conn_studiogear_mgr);
$query_rs_all_classes = "SELECT sg_class_desc.class_image,
sg_class_desc.class_location,
sg_classes.class_name,
sg_class_desc.class_room,
sg_classes.class_cat1,
sg_classes.class_cat2,
sg_classes.class_cat3,
sg_classes.class_id
FROM sg_class_desc
INNER JOIN sg_classes
ON sg_class_desc.class_id = sg_classes.class_id";
$query_limit_rs_all_classes = sprintf("%s LIMIT %d, %d",
$query_rs_all_classes,
$startRow_rs_all_classes,
$maxRows_rs_all_classes);
$rs_all_classes = mysql_query($query_limit_rs_all_classes, $conn_studiogear_mgr)
or die (mysql_error());
$row_rs_all_classes = mysql_fetch_assoc($rs_all_classes);
if (isset($_GET['totalRows_rs_all_classes'])) {
$totalRows_rs_all_classes = $_GET['totalRows_rs_all_classes'];
} else {
$all_rs_all_classes = mysql_query($query_rs_all_classes, $conn_studiogear_mgr);
$totalRows_rs_all_classes = mysql_num_rows($all_rs_all_classes);
}
$totalPages_rs_all_classes = ceil($totalRows_rs_all_classes/$maxRows_rs_all_classes)-1;
$_POST['class_id'] = $row_rs_all_classes['class_id'];
//without the following loop I return the first row and the second query works for the first row
// start loop when I use this loop, "Array" is echoed out and next query does not run
$classes = $row_rs_all_classes['class_id']; // from recordset above
foreach ($classes as $value) {
$ArrayClasses[] = "".$value ."";
echo $ArrayClasses; //
}
// end loop
$colname_rs_gear = "-1";
if (isset($_POST['class_id'])) {
$colname_rs_gear = $_POST['class_id'];
}
mysql_select_db($database_conn_prestashop, $conn_prestashop);
$query_rs_gear = sprintf("SELECT ps_product_lang.name,
ps_product.id_product,
ps_product.price,
ps_product.reference,
ps_product_lang.description_short,
ps_product_lang.description,
ps_supplier.name,
sg_class_gear.class_gear_image,
sg_class_gear.class_gear_product_link
FROM ps_product
INNER JOIN ps_product_lang
ON ps_product.id_product = ps_product_lang.id_product
INNER JOIN ps_supplier
ON ps_product.id_supplier = ps_supplier.id_supplier
INNER JOIN sg_class_gear
ON sg_class_gear.class_gear_pid = ps_product.id_product
WHERE ps_product.id_product = sg_class_gear.class_gear_pid
AND sg_class_gear.class_id = %s",
GetSQLValueString($colname_rs_gear, "int"));
$rs_gear = mysql_query($query_rs_gear, $conn_prestashop) or die(mysql_error());
$row_rs_gear = mysql_fetch_assoc($rs_gear);
$totalRows_rs_gear = mysql_num_rows($rs_gear);
1) You are vulnerable to sql injection attacks
2) You are using an obsolete database library (mysql) and should switch to mysqli or PDO
3) mysql_fetch_*() functions return a SINGLE row of data from the result set. Since you're not calling mysql_fetch_in a loop for your initial query, you only ever get the first row of results. Your code should be
$result = mysql_query($first_query_sql);
while($row = mysql_fetch_assoc($result)) {
$result2 = mysql_query($inner_query_sql);
while($row2 = ...) {
}
}

search entire table except date fields using mysql and php

I have a large table and would like to search all of the fields in one go but some of the fields are dates so the search I have created falls over when it hits those fields.
Is there a way to exclude certain types of fields when using this type of search?
$table = 'accounts';
$condition = 'tracey';
$sql = "SHOW COLUMNS FROM accounts";
$result = mysqli_query($mysqli,$sql);
if (mysqli_num_rows($result) > 0)
{
$i=0;
while ($row = mysqli_fetch_array($result))
{
if($i==0)
{
$q="select * from ".$table." where ".$row[0]." LIKE %".$condition."%";
}
else
{
$q.=" or ".$row[0]."="." LIKE %".$condition."%";
}
$i++;
}
}
$sql = $q;
$result = mysqli_query($mysqli,$sql) or die(mysqli_error($mysqli));
$row = mysqli_fetch_array($result);
$answer = $row['phone_office'];
echo '<br><br>answer = '.$answer;
Or perhaps someone can suggest a better way of searching all of the fields in a table in one go?
To exclude certain types of fields You need to change the query SHOW COLUMNS FROM accounts with this one:
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE (table_name=".$table.")AND(NOT(DATA_TYPE IN ('field_type_1','field_type_2',...)));
Where field_type_i is the name of an excluded type (for example 'timestamp')

Categories