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
Related
/* 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
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.
I am trying to make the link <a href='{$_SERVER['PHP_SELF']}?del=true&orderid={$row['orderid']}' style='color:black;' onclick='return show_confirm();'>Delete</a>
delete the specific row from the MSSQL table using the while function. Currently, the bottom code works fine and deletes the specific row from the table, but I would now like it to unlink a file from the sharedstorage folder. The file that gets unlinked has it's filename stored in the name column for that table row. Each table row has a name column that contains a unique file's name from the file that is located in the sharedstorage folder.
My problem in simple terms is when a table row gets deleted, the file for that row in my website's sharedstorage folder remains and does not get deleted with the row.
Here is the code for when the delete link is hit for that specific row:
// delete from table
if ($_GET['del'] == 'true') {
// cast id as int for security
$id = (int) $_GET['orderid'];
// delete row from table
$sql = "DELETE FROM shareddrive WHERE orderid = '$id'";
$result = mssql_query($sql, $conn) or die(mssql_get_last_message());
// select the info, ordering by usort
$sql = "SELECT orderid, name, type FROM shareddrive ORDER BY orderid";
$result = mssql_query($sql, $conn) or die(mssql_get_last_message());
// initialize a counter for rewriting usort
$job_pos_sortt = 1;
// while there is info to be fetched...
while ($r = mssql_fetch_assoc($result)) {
$job_poss = $r['orderid'];
// update the usort number to the one in the next number
$sql = "update shareddrive SET orderid = '$job_pos_sortt' WHERE name = '$job_poss'";
$update = mssql_query($sql, $conn) or die(mssql_get_last_message());
// inc to next avail number
$job_pos_sortt++;
} // end while // end if del
}
All help is greatly appreciated.
// delete from table
if ($_GET['del'] == 'true') {
// cast id as int for security
$id = (int) $_GET['orderid'];
// delete row from table
$file = mssql_fetch_array(mssql_query("select name from shareddrive where orderid = $id"));
unlink($file[0]);
$sql = "DELETE FROM shareddrive WHERE orderid = '$id'";
$result = mssql_query($sql, $conn) or die(mssql_get_last_message());
// select the info, ordering by usort
$sql = "SELECT orderid, name, type FROM shareddrive ORDER BY orderid";
$result = mssql_query($sql, $conn) or die(mssql_get_last_message());
// initialize a counter for rewriting usort
$job_pos_sortt = 1;
// while there is info to be fetched...
while ($r = mssql_fetch_assoc($result)) {
$job_poss = $r['orderid'];
// update the usort number to the one in the next number
$sql = "update shareddrive SET orderid = '$job_pos_sortt' WHERE name = '$job_poss'";
$update = mssql_query($sql, $conn) or die(mssql_get_last_message());
// inc to next avail number
$job_pos_sortt++;
} // end while // end if del
}
say I have a variable
$id = mt_rand();
how can I query the mysql database to see if the variable exists in the row id, if it does exist then change the variable $id, once the variable is unique to all other stored ids, then insert it into the database?
Thanks you guys.
$con = mysql_connect("<host>","<login>","<pass>");
if ($con) {
mysql_select_db('<schemata>', $con);
$found = false;
while (!$found) {
$idIamSearching = mt_rand();
$query = mysql_query("SELECT count(*) FROM <table> WHERE <idColumnName>='".$idIamSearching."'");
$result = mysql_fetch_row($query);
if ($result[0] > 0) {
mysql_query("INSERT INTO <table> (<column>) VALUES ('".$idIamSearching."')");
$found = true;
}
}
mysql_close($con);
}
Your description is hard to understand, so, this is something that could give you pointers...
'SELECT COUNT(*) as count from table where row_id="'.$variable.'" LIMIT 1'
make sure to escape the variable if it's user input or if it's going to have more than alphanumeric characters
then fetch the row and check if count is 1 or greater than 0
if one, then it exists and try again (in a loop)
although, auto increment on the id field would allow you to avoid this step
$bExists = 0;
while(!$bExists){
// Randomly generate id variable
$result = mysql_query("SELECT * FROM table WHERE id=$id");
if($result){
if(mysql_num_rows($result) > 0){
$bExists = 1;
} else {
// Insert into database
$bExists = 1;
}
}
1 Randomly generate id variable
2 Query database for it
2.1 Result? exit
2.2 No result? Insert
I have a page that writes to a MySQL table. The table has a set amount of rows (24).
I have an $id variable that's set by a rand() function. I basically want to pull the row at that $id, so if $id was 3, I want to pull the third row. Then, I want to check if there is a price set at that row (indicating that the row is being used). If there is no price, I want to keep $id at the value it has been set at and proceed with the query. If there is a price, I want to re-randomize the $id variable, and check again if that row is used up. When it finds an empty row, proceed with the query.
My solution semi-works, but it seems to have a <10% chance of overwriting a used row, for some reason. I want it to never overwrite a used row.
Here's my code:
mysql_select_db("delives0_booklet", $con);
$query = "SELECT * FROM booklet WHERE id = '$id'";
$res = mysql_query($query,$con);
$newId = $id;
while($row = mysql_fetch_array($res))
{
if($row['price'] != 0)
{
do{
$newId = rand(1, 24);
}while($newId == $id);
}
}
$id = $newId;
mysql_query("UPDATE booklet SET price = '$price', advertiser = '$advertiser', image = '$image', monthsRemaining = '$monthsRemaining', availability = 1 WHERE id = '$id'");
Edit
I had the idea to do this. I loop through the table and I put the 'id' of each unfilled spot into an array. Then I pick randomly from that array. However, there seems to be a bug that I can't find, since the array keeps showing as having nothing in it, even after the loop is run, and $i is the correct figure.
mysql_select_db("delives0_booklet", $con);
$query = "SELECT * FROM booklet";
$res = mysql_query($query,$con);
$i = 0;
$isEmpty = array();
while($row = mysql_fetch_array($res))
{
if($row['price'] == 0)
{
$isEmpty[i] = $row['id'];
$i = $i + 1;
}
}
echo $i . " unfilled spots.";
$n = 0;
while($n<$i)
{
echo $isEmpty[$n];
$n = $n + 1;
}
if($i > 0)
{
$id = $isEmpty[rand(0, $i)];
}
if($i == 0)
{
echo 'All spots have been filled.';
}
I think it is a top level logic problem. Because you populate with random ids, you can get duplicate ids, and so when you update "WHERE id = '$id'" you may be picking up rows already populated.
I don't know your goal, but perhaps using an auto-increment id, and dropping rows that you want to get rid of, is the way to go. A rolling set of rows (24 at a time) but with ever increasing ids, would prevent mistaking one for the other.
If I understand the problem correct, this should work:
SELECT *
FROM booklet
WHERE price = 0 OR price IS NULL
ORDER BY RAND()