PHP form update best practices - php

I'm sure i've badly written this. I have a simple form which you enters bits into, which sends the info onto a process page and inserts a row into a table on the database. My problem is that the insert part works fine. But my template class within the page or anything else is shown. Just a blank page. Its driving me nuts.
The function
Public function UpdateReason($reason, $bundlereference) {
error_reporting(E_ALL ^ E_NOTICE);
$db_selected = mysql_select_db(DB_DATABASE_NAME, $this->conn);
if (!$db_selected) {
die("Can't use db : " . mysql_error());
}
$_reason = mysql_real_escape_string($reason,$this->conn);
$_bundlereference = mysql_real_escape_string($bundlereference,$this->conn);
$sql = "UPDATE `ArchiveBundle`
SET `Issue` = '" . $_reason . "'
WHERE `BundleReference` = '" . $_bundlereference . "'";
mysql_query($sql, $this->conn);
die(mysql_error());
exit;
}
The form
<table>
<form method='post' action='addissue.php'>
<p>Reason: <input type='text' name='reason' /></p><br/>
<p><input type='hidden' name='bundlereference' id='Username'
value='" . $x['Reference'] . "' /></p>
<input type='submit' name ='add'/>
</form>
</table>
The process page
<?php
// First of all initialise the user and check for permissions
require_once "/var/www/users/user.php";
$user = new CHUser(2);
// Initialise the template
require_once "/var/www/template/template.php";
$template = new CHTemplate();
// And create a cid object
require_once "/var/www/Testing/DisplayWIPOnLocation.php";
$BundleProgress= new CHWIPProgress();
$reason = $_POST['reason'];
$reference = $_POST['bundlereference'];
$issue = $BundleProgress->UpdateReason($_POST['reason'],$_POST['bundlereference']);
Print "Your information has been successfully added to the database.";
$template->SetTag("content", $content);
echo $template->Display();
?>
I also want to know/learn what the best practices are for forms in php

The reason you aren't getting output is the following two lines. This is killing your script in place. Just remove these.
die(mysql_error());
exit;
Overall, it's not terrible. You're using objects, and you're sanitizing your user input before inserting into the db. I do have a couple suggestions.
Don't use die() in a production script. Handle errors and exceptions properly.
Look into prepared statements (PDO) or stored procedures for mysql.
Instead of the print "Your information has been added..." line, can you create a field in your template and pass in that value through your template class?
You set $reason and $reference then pass in the value from $_POST, making those unused variables. Maybe this is just due to testing code though?
Depending on your needs, you may want to consider checking that the data the form has received is valid before running an update query. What if $reason or $bundlereference aren't valid values?

Related

PHP not retrieving new data until page refresh

What is happening is I think my code is selecting the data first (basically old data) then updating it but what I want is for it to update then select the data (new data). How can I do this?
I am going to post where it goes wrong and if you need the full code just ask:
$select_links = $db->query("SELECT pid, added_by,link_title,lid,link_order FROM " . TABLE_PREFIX . "homepage_links WHERE pid='$pid'
ORDER BY link_order DESC LIMIT $start,$show");
$check_link_count_rows = $db->num_rows($select_links);
echo "<b> You Current Have " . $check_link_count_rows . " Links On Your Page: </b><br>";
echo "<form action='' method='POST'>
";
while($select_links_array = $db->fetch_array($select_links)) {
$link_title_display = $select_links_array['link_title'];
$link_id_display = $select_links_array['lid'];
if(!$mybb->input["order_edit_$link_id_display"]) {
$link_order_display = $select_links_array['link_order'];
} else {
$link_order_display = $mybb->input["order_edit_$link_id_display"];
}
$order_edit_value1 = $mybb->input["order_edit_$link_id_display"];
$order_edit_value = $db->escape_string($order_edit_value1);
echo "<br>" . $link_title_display . " <a href='?operation=edit_links&link=$link_id_display'> (edit) </a>
<input type='number' name='order_edit_$link_id_display' value='$link_order_display' style='width:40px;'>
<input type='hidden' name='get_link_id_display_value_$link_id_display' value='$link_id_display'><br>
";
$get_link_id_display_value1 = $mybb->input["get_link_id_display_value_$link_id_display"];
$get_link_id_display_value = $db->escape_string($get_link_id_display_value1);
$update_quick_edit_query = $db->query("UPDATE spud_homepage_links SET link_order='$order_edit_value'
WHERE lid='$get_link_id_display_value'");
}
I cannot find a solution as everything is in the right place for it to work besides this bug.
After a discussion in the comments, I determined that you were attempting to render a page after a post form submission that amends the database. It is perfectly possible to re-read your new database state and render it in a post operation, but it is inadvisable, since browsers cannot refresh the page without asking you if you wish to run the operation again. This does not make for a good user experience, especially in relation to using the back/forward buttons.
The reason for this behaviour is that post operations generally modify the database. They are used for example in credit card purchases or profile amendments where some change in the state of the server is expected. Thus, it is good practice to execute a new round-trip to the server, after the write operation, to change the page method from post to get.
The header() call I linked to will do this, and will resolve your rendering problem too.

Relate an input to a button in php

I have a script that creates a series of inputs and buttons, retreiving them from a database like this:
while ($row = mysql_fetch_array($sql)){
echo "<input value='".$row['val']."'/><button type='submit'>delete</button>";
}
This script can retreive any number of rows from the database. And the delete button is supposed to delete the input right next to it like this:
$sql="DELETE FROM $tbl WHERE ......";
$delete= mysql_query($sql5, $dbh) or die ("there was a problem");
My question is... is there a way to relate each button with the input next to it?
Thanks in advance!
Utilizing your code as a starting point, make some changes like so:
while ($row = mysql_fetch_array($sql)){
echo "<input value='".$row['val']."'/><button name='delete[" . $row['id'] . "]' type='submit'>delete</button>";
}
Then, where the form gets posted to, in your php:
// Check if the delete button was posted and get the value
$delete = (isset($_POST['delete'])) ? $_POST['delete'] : NULL;
// $delete should contain an array of ids. Iterate over them
foreach((array)$delete AS $id=>$x) {
// NOTE: DO NOT use mysql_ - used here ONLY because your question contains mysql_
$sql="DELETE FROM [table] WHERE id = " . (int)$id;
// Delete the record where the id matches
// Also - on your die, let's SEE the problem, by echoing mysql_error()
$results = mysql_query($sql, $dbh) or die ("there was a problem<br>" . mysql_error());
if ($results) {
// .. code to run if query executed successfully...
}
}
Do not use mysql_
I can't leave an answer without telling you it is insecure and a bad idea to use the mysql_ database extension. It's deprecated in php 5.5.
See Choosing a database API for help with choosing / switching to mysqli or PDO
You shouldn't use button and input together this way.
You can achieve it this way:
while ($row = mysql_fetch_array($sql)){
echo '<input type="submit" name="'.$row['val'].'" value="delete" />";
}
Or you can create many forms - one for each record and set input type as hidden.

SQL database not inserting data?

I am working on a program that takes HTML code made by a WYSIWYG editor and inserting it into a database, then redirecting the user to the completed page, which reads the code off the database. I can manually enter code in phpmyadmin and it works but in PHP code it will not overwrite the entry in the code column for the ID specified. I have provided the PHP code to help you help me. The PHP is not giving me any parse errors. What is incorrect with the following code?
<?php
//POST VARIABLES------------------------------------------------------------------------
//$rawcode = $_POST[ 'editor1' ];
//$code = mysqli_real_escape_string($rawcode);
$code = 'GOOD';
$id = "1";
echo "$code";
//SQL VARIABLES-------------------------------------------------------------------------
$database = mysqli_connect("localhost" , "root" , "password" , "database");
//INSERT QUERY DATA HERE----------------------------------------------------------------
$queryw = "INSERT INTO users (code) VALUES('$code') WHERE ID = '" . $id . "'";
mysqli_query($queryw, $database);
//REDIRECT TO LOGIN PAGE----------------------------------------------------------------
echo "<script type='text/javascript'>\n";
echo "window.location = 'http://url.com/users/" . $id . "/default.htm';\n";
echo "</script>";
?>
Your problem is that mysql INSERT does not support WHERE. Change the query to:
INSERT INTO users (code) VALUES ('$code')
Then to update a record, use
UPDATE users SET code = '$code' WHERE id = $id
Of course, properly prepare the statements.
Additionally, mysqli_query requires the first parameter to be the connection and second to be the string. You have it reversed. See here:
http://php.net/manual/en/mysqli.query.php
It should also be noted that this kind of procedure should be run before the output to the browser. If so, you can just use PHP's header to relocate instead of this js workaround. However, this method will still work as you want. It is just likely to be considered cleaner if queries and relocation is done at the beginning of the script.

page not refreshing after clicking delete button

good day
need some help here, my Delete button works but page is not automatically refreshing after i clicked the delete button. i still need to manually retrieve the data from db and it would reflect that data is deleted already...
here is my code for delete php: how can i make this to refresh the page automatically?
<?php
require 'include/DB_Open.php';
$id = $_POST['id'];
$idtodelete = "'" . implode("','",$id) . "'";
$query = "DELETE FROM tbl WHERE ticket in (" . $idtodelete . ")";
$myData = mysql_query($query);
echo "DATA DELETED";
if($myData)
{
header("Location: delete.php");
}
include 'include/DB_Close.php';
?>
I suggest fetching the data after your delete logic. Then the delete logic will be executed before fetching the tickets.
Then a redirect to the same page isn't even necessary.
//
// DELETE
//
if (isset($_POST['delete'] && isset($_POST['id'])) {
// Do delete stuff,
// notice delete variable which would be the name of the delete form button e.g.
// If you like, you can still echo "Data deleted here" in e.g. a notification window
}
//
// FETCH data
//
$query = "Select * FROM tbl";
...
if you use post method better with this
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$id = $_POST['id'];
$idtodelete = "'" . implode("','",$id) . "'";
$query = "DELETE FROM tbl WHERE ticket in (" . $idtodelete . ")";
if (mysql_query($query))
{
header("Location: delete.php");
} else {
echo "Can not delete";
}
}
As suggested on one of the comments, and on the php documentation:
http://it2.php.net/manual/en/function.header.php :
Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include, or require, functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.
Basically you have to take out the :
echo "DATA DELETED";
What's the point to try to echo that string if the page is going to be redirected anyway?
If you want to make it fancy you could use Ajax to delete it, and trigger a setTimeout() on JavaScript x seconds after showing the message.
Or if you really really really really, REALLY, want to do it this way, you could disable the errors report/display (using error_reporting(0) and ini_set('display_errors', 'Off'). By experience I know that it will work, but it's nasty and extremately ultra highly not recommended

SQL WHERE ID carryover

Basically I've created two php papes. One selects my entire table, and displays just date, and id number from it. Each date has a link directing to a display.php file. It pulls the ID number with it to the next display.php page. What I want to do on the display.php file is to display the entire row using that PHP.
So I know that Select * from tablename WHERE id=1 will pull that data, but how to get the ID number into there WHERE statement?
This is the main page code:
// SQL query
$strSQL = "SELECT * FROM table1";
// Execute the query (the recordset $rs contains the result)
$rs = mysql_query($strSQL);
// Loop the recordset $rs
while($row = mysql_fetch_array($rs)) {
// DATE
$strName = $row['date'];
// Create a link to display.php with the id-value in the URL
$strLink = "<a href = 'display.php?ID = " . $row['ID'] . "'>" . $strName . "</a>";
// List link
echo "<li>" . $strLink . "</li>";
}
That code links works and goes to display.php.
How would I create the link using the ID number pulling with it. Would I use a post command?
$id= Post['id']
then WHERE id = '$id'
?
TBH I did try that and got nothing. Any suggestions?
USING GET now...still not luck
I've tried the GET statement. In my address bar it shows the ID number. So I see the ID number pulling over with it. I tried even just echoing the ID to see if maybe it was just my code messing up.
<?php
$dbhost = 'localhost';
$dbuser = 'myusername';
$dbpass = 'mypw';
$dbname = 'mydbname';
$id = $_GET['id'];
mysql_connect($dbhost, $dbuser, $dbpass) or die('MySQL connect failed. ' . mysql_error());
mysql_select_db($dbname) or die('Cannot select database. ' . mysql_error());
?>
<body>
ID #<?php echo $id ?>
</body>
</html>
<body>
ID #<?php echo $id ?>
</body>
</html>
Still no luck
So in your display file you'd do something like this
$id = $_GET['ID'];
//DO SANITIZATION ETC ON THE ID HERE TO MAKE SURE ITS SOMETHING WE EXPECTED (AN INT)
$sql = "SELECT STUFF WHERE ID = {$id}"; //FOR BREVITY SAKE DOING AWAY WITH SECURITY
So basically what your first script is doing is passing the id in the url query string, values passed here are accessible in the $_GET super globals array.
Anything you access in here and the other super globals should be treated as completely dangerous to your application. You should filter and escape the hell out of it, and then before inserting it into the database you must escape it using the correct mechanism for your database. Otherwise you leave yourself open to SQL injection attacks.
Values passed in the querystring use GET not POST.
Post is for form variables.
You should also be aware of the danger of a SQL injection attack when taking values from the querystring.

Categories