Why does my while loop seems to always be false - php

I've been trying to make my php code to show entries from my mysql database. I wanted to make it automatic in a sense that i wouldn't need to print the tables manually instead they would be printed according to an alogrythm, but it doesn't work like intended.
I've tried different ways of setting up the table but none of them worked, the furthest I got was to print one entry from the table, and spitting errors after it.
$base = $_POST["base"];
$connection = mysqli_connect("localhost","login","pass") or die("Impossible to connect to the database!");
$db = mysqli_select_db($connection, "database")or die("Impossible to download the database!");
$sql = "SELECT * FROM $base";
$mysqli_result = mysqli_query($connection, $sql);
$sql2 = "SHOW COLUMNS FROM $base";
$set1 = mysqli_query($connection, $sql2);
$colu = array();
while($db = mysqli_fetch_row($set1)){
$colu[] = $db[0]; }
$columns=implode("<br/>",$colu);
echo "<TABLE BORDER=1>";
echo "<TR><TH>$colu[0]</TH><TH>$colu[1]</TH><TH>$colu[2]</TH><TH>$colu[3]</TH><TH>$colu[4]</TH><TH>$colu[5]</TH></TR>";
while ($row = mysqli_fetch_array($set1)) {
$colu[0] = $row["echo $colu[0]"];
$colu[1] = $row["echo $colu[1]"];
$colu[2] = $row["echo $colu[2]"];
$colu[3] = $row["echo $colu[3]"];
$colu[4] = $row["echo $colu[4]"];
$colu[5] = $row["echo $colu[5]"];
echo "<TR><TD>$colu[0]</TD><TD>$colu[1]</TD><TD>$colu[2]</TD><TD>$colu[3]</TD><TD>$colu[4]</TD><TD>$colu[5]</TD></TR>";}
echo "</TABLE>";
mysqli_free_result($mysqli_result);
mysqli_close($connection); ?>
the $_POST[$base]; part works, Im guessing the issue is in the while loop as it doesnt complete once, and I'm lost as to why it doesnt want to work.

I see some problems in you script. If you want to fetch columns as heading and the content for the table body you are using the wrong result sets.
// next line make it possible to do sql insertion, and what if $base has no input?
$base = $_POST["base"];
// the die will never be reached
$connection = mysqli_connect("localhost","login","pass") or die("Impossible to connect to the database!");
$db = mysqli_select_db($connection, "database")or die("Impossible to download the database!");
// where is this query for?
$sql = "SELECT * FROM $base";
// where is this result being used
$mysqli_result = mysqli_query($connection, $sql);
$sql2 = "SHOW COLUMNS FROM $base";
$set1 = mysqli_query($connection, $sql2);
$colu = [];
// what if the table order chages? Best to use mysqli_fetch_assoc
while($db = mysqli_fetch_row($set1)){
$colu[] = $db[0];
}
// where do you use $comumns?
$columns = implode("<br/>", $colu);
echo "<TABLE BORDER=1>";
echo "<TR><TH>$colu[0]</TH><TH>$colu[1]</TH><TH>$colu[2]</TH><TH>$colu[3]</TH><TH>$colu[4]</TH><TH>$colu[5]</TH></TR>";
// you already fetched all record from set1
while ($row = mysqli_fetch_array($set1)) {
$colu[0] = $row["echo $colu[0]"];
$colu[1] = $row["echo $colu[1]"];
$colu[2] = $row["echo $colu[2]"];
$colu[3] = $row["echo $colu[3]"];
$colu[4] = $row["echo $colu[4]"];
$colu[5] = $row["echo $colu[5]"];
echo "<TR><TD>$colu[0]</TD><TD>$colu[1]</TD><TD>$colu[2]</TD><TD>$colu[3]</TD><TD>$colu[4]</TD><TD>$colu[5]</TD></TR>";
}
echo "</TABLE>";
mysqli_free_result($mysqli_result);
mysqli_close($connection); ?>

This biggest issue you have right now is this:
$base = $_POST["base"]
$sql = "SELECT * FROM $base";
$sql2 = "SHOW COLUMNS FROM $base";
This is a huge SQL Injection vulnerability, even if they pass just an empty string to this it's all bad. For example that would result in a query error and depending on your settings on the server and for error reporting, you may expose quite a bit of info. Just one example is a stack trace could contain DB passwords etc.
Instead of directly using user input make a whitelist like this:
$tables = ['user', 'user_meta', 'states']; //etc
$base = !empty($_POST["base"]) && false !== ($index = array_search($_POST["base"], $tables)) ? $tables[$index] : false;
if(!$base) die('Unknown table '.$_POST["base"]);
This way you are only using data you know the value of.
Variable reuse
Other then that, your variable names are causing a bunch of "code confusion". This is what happens if you have to generic of a variable name. Some examples:
$db = mysqli_select_db(...)
while($db = mysqli_fetch_row($set1)){ //overwriting db
...
}
//....................
while ($row = mysqli_fetch_array($set1)) {
$colu[0] = $row["echo $colu[0]"]; //overwriting $colu
This last one is also wrong because the row key will be something like:
$colu[0] = $row["echo name"];
Or something with a column name. Because you are re-using this variable ("variable confusion" ) on the next loop it will be the value of $row["echo $colu[0]"]; which will get put back into that. So lets assume this is correct without the echo and will use Name as the value.
//loop 1
$colu[0] = 'name';
$row['name'] = 'Tom';
//result
$colu[0] = 'Tom'
//loop 2
$colu[0] = 'Tom';
$row['Tom'] doesn't exist.
//result
$colu[0] = null; //undefined index warning
Cursor Reuse
You are also reusing the DB cursor $set1 and looping over it 2 times. I'm not sure about MySqli, but PDO won't allow you to do that. This is probably why the second loop is failing. I believe the second one should be $mysqli_result. It's a bit confusing because you do both queries then loop though one then the other. Instead of doing a query, looping through it. Then doing the other, and looping though that.
Instead you can do something like this:
//you can even query the DB for the table names
$tables = ['user', 'user_meta', 'states']; //etc
$base = !empty($_POST["base"]) && false !== ($index = array_search($_POST["base"], $tables)) ? $tables[$index] : false;
if(!$base) die('Unknown table '.$_POST["base"]);
$connection = mysqli_connect("localhost","login","pass") or die("Impossible to connect to the database!");
$db = mysqli_select_db($connection, "database")or die("Impossible to download the database!");
//---------query for the columns
$sql = "SHOW COLUMNS FROM `$base`";
$mysqli_result = mysqli_query($connection, $sql);
$columns = [];
while($row = mysqli_fetch_row($mysqli_result)){
$columns[] = $row[0];
}
//---------query for the data
//use the column result in the select part of query, because the column names
//come from the DB they are safe to use.
$sql = "SELECT `".implode('`,`', $columns)."` FROM `$base`"; //reuse sql (no longer needed)
$mysqli_result = mysqli_query($connection, $sql); //reuse results (no longer needed)
//fetch all data as assoc array. because we tied it to the results
//of the first query, the column names. We no longer need to map it.
$data = mysqli_fetch_all($mysqli_result, MYSQLI_ASSOC);
///output table and headers
echo "<table>";
echo "<thead>";
echo "<tr>";
//we can just loop over the columns and put them in the table head
foreach($columns as $key ){
echo "<th>$key</th>";
}
echo "</tr>";
echo "</thead>";
echo "<tbody>";
//loop over each row of data
foreach($data as $row){
echo "<tr>";
//loop over each "correlated" column
foreach($columns as $key ){
echo "<td>{$row[$key]}</td>";
}
echo "</tr>";
}
echo "</tbody>";
echo "</table>";
BONUS For getting the table names from the DB:
$sql = 'SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` LIKE "'.$database.'"';
$mysqli_result = mysqli_query($connection, $sql);
$tables = mysqli_fetch_all($mysqli_result, MYSQLI_NUM);
Hope that makes sense.

Related

Use PHP loop to fetch tables data from the table which contain names of database tables

I have table named category which contain names of other tables in the same database. I want to fetch table names from category table and then fetch data from each table from db. So far I have this code below:
$db = new mysqli('localhost', 'root', '', 'db_cat');
if($db){
// $q = "SELECT TABLE";
// $echo = $db->query($q);
// echo $echo;
// $result = $db->query("SHOW TABLES");
$qCat="SELECT * FROM product_category";
$cat_query= $db->query($qCat) or die(mysql_error());
while ($fetch= $cat_query->fetch_object())
{
$cat_id=$fetch->id;
$category=$fetch->category;
$p_cat=str_replace(" ","_",strtolower($category).'_categories');
//if(strlen($category)>22){$fine_product_name= substr($service, 0,19).'...';}else{ $fine_product_name=$category;}
$result = $db->query("SHOW TABLES");
while($row = $result->fetch_array()){
$tables[] = $row[0];
}
}
The second query must be different.
$result = $db->query("SELECT * FROM $category");
while($row = $result->fetch_array()){
$tables[] = $row[0];
}
print_r($tables);
First of all your design to connect to a database is not that good, Please check the below code for a proper way of connecting to it.
<?php
$con=mysqli_connect("localhost","root","","db_cat");
//servername,username,password,dbname
if (mysqli_connect_errno())
{
echo "Failed to connect to MySql: ".mysqli_connect_error();
}
?>
Here is a sample code of getting data from a table ( where this table name is in another table).
$get_table_name ="SELECT TableName FROM table_name";
$get_name=mysqli_query($con,$get_table_name);
$count=0;
while($row_name=mysqli_fetch_array($get_name)){
$count++;
$tbName=$row_name['TableName'];
$_SESSION['table_name'][count]=$tbName;
}
This will show you how to fetch data from one table. You can use a For loop to get all the tables
$table=$_SESSION['table_name'][1];
$get_table ="SELECT * FROM $table";
.... // Normal way of fetching data
You can try to adjust your code according to this and improve it.
For further reference please refer http://php.net/manual/en/book.mysqli.php

Add Table or Array into Row Per User

First, I apologize for posting such an enormous block of code. It's probably not even pertinent to the question but just in case... The code maintains a simple ToDo list that I would like to incorporate into an existing PHP Website that stores a lot of information for each user. In other words, I would like to add this to the user's row of information in the mySQL DB.
I am new to PHP but have come a long way by coming up with ideas and figuring out how to make them work. Can you point me in the direction of adding a feature like this, that stores information by way of adding & deleting rows of information, into the list of fields assigned to a user?
Another way of putting it: I would like to give my users a way to maintain their own ToDo list.
<?php
$conn = mysql_connect('server, 'db', 'password') or die(mysql_error());
$db = mysql_select_db('db',$conn) or die(mysql_error());
// if an arrow link was clicked...
if ($_GET['dir'] && $_GET['id']) {
// make GET vars easier to handle
$dir = $_GET['dir'];
// cast as int and couple with switch for sql injection prevention for $id
$id = (int) $_GET['id'];
// decide what row we're swapping based on $dir
switch ($dir) {
// if we're going up, swap is 1 less than id
case 'up':
// make sure that there's a row above to swap
$swap = ($id > 1)? $id-- : 1;
break;
// if we're going down, swap is 1 more than id
case 'down':
// find out what the highest row is
$sql = "SELECT count(*) FROM info";
$result = mysql_query($sql, $conn) or die(mysql_error());
$r = mysql_fetch_row($result);
$max = $r[0];
// make sure that there's a row below to swap with
$swap = ($id < $max)? $id++ : $max;
break;
// default value (sql injection prevention for $dir)
default:
$swap = $id;
} // end switch $dir
// swap the rows. Basic idea is to make $id=$swap and $swap=$id
$sql = "UPDATE info SET usort = CASE usort WHEN $id THEN $swap WHEN $swap THEN $id END WHERE usort IN ($id, $swap)";
$result = mysql_query($sql, $conn) or die(mysql_error());
} // end if GET
// set a result order with a default (sql infection prevention for $sortby)
$sortby = ($_GET['sortby'] == 'name')? $_GET['sortby'] : 'usort';
// pull the info from the table
$sql = "SELECT usort, name FROM info ORDER BY $sortby";
$result = mysql_query($sql, $conn) or die(mysql_error());
// display table
echo "<table border = '1'>";
echo "<tr>";
// make column names links, passing sortby
echo "<td><a href='{$_SERVER['PHP_SELF']}?sortby=usort'>usort</a></td>";
echo "<td><a href='{$_SERVER['PHP_SELF']}?sortby=name'>name</a></td>";
echo "</tr>";
// delete from table
if ($_GET['del'] == 'true') {
// cast id as int for security
$id = (int) $_GET['id'];
// delete row from table
$sql = "DELETE FROM info WHERE usort = '$id'";
$result = mysql_query($sql, $conn) or die(mysql_error());
// select the info, ordering by usort
$sql = "SELECT usort, name FROM info ORDER BY usort";
$result = mysql_query($sql, $conn) or die(mysql_error());
// initialize a counter for rewriting usort
$usort = 1;
// while there is info to be fetched...
while ($r = mysql_fetch_assoc($result)) {
$name = $r['name'];
// update the usort number to the one in the next number
$sql = "UPDATE info SET usort = '$usort' WHERE name = '$name'";
$update = mysql_query($sql, $conn) or die(mysql_error());
// inc to next avail number
$usort++;
} // end while
} // end if del
// display data 1 row at a time
while ($r = mysql_fetch_assoc($result)) {
echo "<tr>";
// make the links to change custom order, passing direction and the custom sort id
echo "<td align = 'center'><a href='{$_SERVER['PHP_SELF']}?dir=up&id={$r['usort']}'>/\</a> ";
echo "<a href='{$_SERVER['PHP_SELF']}?dir=down&id={$r['usort']}'>\/</a></td>";
echo "<td>{$r['name']}</td>";
echo "<td><a href='{$_SERVER['PHP_SELF']}?del=true&id={$r['usort']}'>delete</a></td>";
echo "</tr>";
} // end while $r
echo "</table>";
// end display table
?>
Users todo list seems another table to me. You do not need to change any value from users info. Just add, delete or change order of tasks in another table. Something like the image below

PHP get mysql table info function

I am making a PHP function to return an array of a mysql database's table's info. I am new to coding in php and am looking for more efficient way to do the same thing I have done because my method does not seem very efficient. Would this be a good place to use a mysql join statement?
Here is my function.
public static function getAllTables()
{
// Get an array of all the tables in the database
$sql = "SHOW TABLES";
//this makes a connection to mysql database using mysqli
$mysqlConnection = new CMySqlConnection();
$result = $mysqlConnection->mysqli->query($sql);
$tablesArray = array();
while($row = $result->fetch_row()) {
$tablesArray[$row[0]]=array();
}
$result->close();
//Get an array of all the table names in database
$arrayKeys = array_keys($tablesArray);
//foreach table get the column's info
foreach($arrayKeys as $key){
$sql=" SHOW COLUMNS from " . $key;
$result = $mysqlConnection->mysqli->query($sql);
for($i = 0; $row = $result->fetch_row(); $i++) {
//format the array to use a descriptive key rather than a number
$row['columnName'] = $row[0];
$row['type'] = $row[1];
$row['null'] = $row[2];
$row['key'] = $row[3];
$row['default'] = $row[4];
$row['extra'] = $row[5];
unset($row[0]);
unset($row[1]);
unset($row[2]);
unset($row[3]);
unset($row[4]);
unset($row[5]);
// put the column info into the tables array
$tablesArray[$key][$i] = $row;
}
$result->close();
}
$mysqlConnection->Disconnect();
// return the tables array
return $tablesArray;
}
Thanks for any input :)
You can just query the INFORMATION_SCHEMA. They are virtual tables which contain information about your database: http://dev.mysql.com/doc/refman/5.5/en/information-schema.html
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES;
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='schema' AND TABLE_NAME='table';

PHP/MySQL outing a table from the data base but excluding a field from a table?

I have a form which allows the user to set what the sort the data by in the table and if it increase or decreasing order
http://damiensplace.co.uk/test/requestTableDisplay.htm
However I want the user to choose to exclude a field (Age Grade) form set the variable but been racking my brain on how to do this but only way I come up with is not neat as I basically need to write two lots of code am I missing a trick?
<html><head><title>MySQL Table Viewer</title></head><body>
<?php
$db_host = '****';
$db_user = '***';
$db_pwd = '***';
$sortOn = $_POST['SortOn'];
$sortIn = $_POST['SortIn'];
$database = '****';
$table = '***';
if (!mysql_connect($db_host, $db_user, $db_pwd))
die("Can't connect to database");
if (!mysql_select_db($database))
die("Can't select database");
// sending query
$result = mysql_query("SELECT * FROM {$table} order by {$sortOn} {$sortIn}");
if (!$result) {
die("Query to show fields from table failed");
}
$fields_num = mysql_num_fields($result);
echo "<h1>Table: {$table}</h1>";
echo "<table border='1'><tr>";
// printing table headers
for($i=0; $i<$fields_num; $i++)
{
$field = mysql_fetch_field($result);
echo "<td>{$field->name}</td>";
}
echo "</tr>\n";
// printing table rows
while($row = mysql_fetch_row($result))
{
echo "<tr>";
// $row is array... foreach( .. ) puts every element
// of $row to $cell variable
foreach($row as $cell)
echo "<td>$cell</td>";
echo "</tr>\n";
}
mysql_free_result($result);
?>
</body></html>
If someone can point me in the right direction I would be most grateful
Pretty simple. Instead of running this query:
SELECT * FROM {$table} order by {$sortOn} {$sortIn}
run this one:
"SELECT hats, cats, margarine FROM {$table} order by {$sortOn} {$sortIn}
...where hats, cats and margarine are to be replaced by fields in your table. You can specify any number of fields in this way, even down to grabbing only a single field.
You should have your query as follows:
SELECT (columns) FROM (table)
Do not SELECT all, it appears you only want specific columns.

Strange PHP output

I'm using this code to attempt to grab a table name and store it in a variable.
<?php
connectDB();
$sql = "SHOW TABLES";
$result = mysql_query($sql);
$tables = mysql_fetch_array($result);
foreach ($tables as $table) {
$table_name = $table[0];
echo $table_name;
}
closeConn();
?>
For one, its outputting 'aa' and 'bb' if i change the array index which i know arent table names in the db and two, what i want to do is run some code for every table in the db and insert the table name into a variable which i can use in said code? How would i do that?
$tables = mysql_fetch_array($result);
mysql_fetch_array fetches one row, not the entire set. This means that when you do $table[0], you are actually working on the string value of each field in the row.
You should put the mysql_fetch_array inside the loop instead:
while ($table = mysql_fetch_array($result)) {
$table_name = $table[0];
echo $table_name;
}
SHOW TABLES returns a table with one table name per row. You should use mysql_fetch_array as many times as there are rows in the table, because it only retrieves one row of the table...
Think of something like this:
while($row = mysql_fetch_array($result)) {
$table_name = $row[0];
// ...
}
$sql = "SHOW TABLES";
$result = mysql_query($sql);
while ($row = mysql_fetch_array($result, MYSQL_BOTH))
{
$tables[] = $row[0];
}
// To Display
foreach ($tables as $table) {
$table_name = $table;
echo $table_name;
}

Categories