I have an online courses CRUD application. It has, among other pages, an instructor BIO page.
First, the instructors are added, in an users table, with basic data: first_name, last_name, and email; then a BIO can be added, optionally, for any instructor. There is a second database table, called "bios", to serve this purpose.
I need to pass $user_id into the courses table, (as foreign KEY) an for that purpose i use $_GET:
<?php
$user_id = $_GET['id'];
if(isset($_POST['submit-btn'])) {
$no_courses = $_POST['no_courses'];
$years_exp = $_POST['years_exp'];
$fav_lang = $_POST['fav_lang'];
$courses = $_POST['courses'];
$sql = "INSERT INTO courses (user_id, no_courses, years_exp, fav_lang, courses) VALUES ('$user_id', '$no_courses', '$years_exp', '$fav_lang', '$courses')";
if (mysqli_query($con, $sql)) {
echo("<p>Instructor bio was added.</p>");
} else {
echo "Error: " . mysqli_error($con);
}
}
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" id="add_bio">
...
</form>
Using $_GET seems convenient because in a table with a lot of rows, containing instructors, on the right most cell/column, I have a set of link buttons for CRUD operations, "Add bio" being one of those buttons.
<a title="Add bio" href="add_bio.php?id=<?php echo $arr['id']?>"><span class="glyphicon glyphicon-plus-sign"></span></a>`
But instead of passing the $user_id variable so that the bio can be added, the server throws these errors:
Notice: Undefined index: id in E:\xampp\htdocs\courses\add_bio.php on line 7
Error: Cannot add or update a child row: a foreign key constraint fails
How can I pass the user's id if I want to keep the CRUD links mentioned above?
Thank you!
You may have some issues with the content being submitted.
A great troubleshooting approach would be to:
print_r($_GET);
or
print_r($_POST);
Another option is to also:
echo print_r($_GET, true);
The Second argument (True) tells the print_r function to return as a string instead of output to the browser.
Review that output and verify you are actually getting an "ID" value in your GET and POST variables.
Also, some security concerns, any data you take in from GET or POST or REQUEST or COOKIE should be "cleaned" you can look at:
mysqli_real_escape_string
Additionally, Never use PHP_SELF. In almost all cases, it can be manipulated to execute a Cross Site Scripting Attack, and that is bad news. if you want to submit the form to the current script, you can leave the "action" attribute as an empty string.
action=""
Hope this helps!!!
The form was missing this line, right above the submit button:
<input type="hidden" name="id" value="<?php $user_id;?>">
Related
I'm working on a CMS site, I've got blog posts that I store in a database. I can create, edit and delete them. There's an issue though when I want to edit them.
I can't specify the WHERE clause in the update query to match the id of the blog post I'm trying to edit!
Suppose I've got a blog post with an id of '5'.
If I write this code for it, it works exactly the way it should.
$sqledit = "UPDATE paginas SET message='$_POST[message]' WHERE id= $_POST[id]";
But I don't want to edit just blog post #5, I want to edit the blog post that I'm updating. It seems to me this should work,
WHERE id= $_POST[id]";
... but it doesn't.
That just throws me an undefined id error. But it shouldn't because I can delete blog posts the exact same way with this particular code:
$sqldel = "DELETE FROM `paginas` WHERE id= $_POST[id]";
This does allow me to.
The code below is on the blog page, the edit query is in its own edit.php page
if (isset($_POST['edit'])) // if pressed, execute
{
echo
'<br><br> <div class="blogscript">
<form action="edit.php" method="post">Edit your stuff<br>
<input type="text" placeholder='. $pagetitle . ' ><br><br>
<textarea id="message2" name="message"><p>' . $message . '</p></textarea><br>
<input type="submit" name="editsubmit" value="Confirm" />
<input type="hidden" name="id" value="' . $id . '">. </form></div>';
}
I look forward to any tips I should try out.
EDIT:
This is my edit.php page
<?php
$DB_host = "localhost";
$DB_user = "root";
$DB_pass = "";
$DB_name = "cmsbase";
$MySQLi_CON = new MySQLi($DB_host,$DB_user,$DB_pass,$DB_name);
if($MySQLi_CON->connect_errno)
{
die("ERROR : -> ".$MySQLi_CON->connect_error);
}
$sql = "UPDATE paginas SET message='$_POST[message]' WHERE id= $_POST[id]";
if ($MySQLi_CON->query($sql) === TRUE) {
echo "";
} else {
echo "Error: " . $sql . "<br>" . $MySQLi_CON->error;
}
$MySQLi_CON->close(); //close connection
echo "<script>alert('Edited');location.href='index.php';</script>";
?>
EDIT: This is what the var_dump contains
In order for values to be present in $_POST, you need to have some element (e.g. <input>, <select>, <textarea>) inside your form with a name attribute set to the $_POST key you want.
You can add a hidden input to your form for id.
<input type='hidden' name='id' value='" . $id . "'>
Assuming you are getting the $message variable shown in that form code by selecting from your database, you should be able to get the id from there as well, or potentially from your $_GET if that is how you determine which post is being displayed.
(While this is not actually an answer, what I want to say does not fit in the comments)
Your line
$sql = "UPDATE paginas SET message='$_POST[message]' WHERE id= $_POST[id]";
Is horrific. This is the stuff of nightmares. Lets say that POSTed data in a form, is posted from a script from some robot somewhere, because I'm pretty sure you don't prevent XSRF in your code.
What if that script chose to post:
$_POST ==> array => message = "mwahahaha";
=> id = "1; DROP TABLE paginas;"
And you may think "how would they know my table name?" ,but that's easily found from other nefarious id inserts or other hacks on your code from other entry points which give a SELECT result, and many tables have common names such as "users" / "orders" / "baskets" / "touch-me" etc. (Ok well maybe not touch-me, but you get the idea).
Mysqli_real_escape_string() Could be used but thats only escaping quote marks and special characters, it does not mitigate SQL injection and compromise.
So, what should you do?
In this instance I want to draw your attention to PHP type juggling. Unlike many other languages, PHP has implied data types rather than specific data tyes, so a data type of "1.06" can be string and juggled to being a float as well.
Your id parameter in your MySQL is very probably a numeric integer value, so how can you be sure that the value of $_POST['id'] is also in integer rather than a SQL Instruction?
$id = (int)$_POST['id'];
This forces the value to be an integer, so
$id = (int)"1; DROP TABLE paginas;";
Is actually processed as $id = 1. Therefore saving you lots of compromised tables, spam rows and other nefarious rubbish all over your website, your database and your reputation.
Please take the following concept on board:
NEVER EVER TRUST ANY USER SUBMITTED CODE.
EVER
I have a form that submits to firstpage.php, this page includes the code to insert all form values into the database and check for duplicate entries, if the entry is a duplicate , display the duplicate entry using the following php code
$checkstudentID = mysqli_query
($dbcon, "SELECT studentid from courses WHERE studentid = '$studentid'");
if(mysqli_num_rows($checkstudentID) > 0){
if ($stmt = mysqli_prepare($dbcon, "SELECT ckb from courses WHERE studentid = ?")) {
mysqli_stmt_bind_param($stmt,"s",$studentid);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $ckb);
mysqli_stmt_fetch($stmt);
printf("<br /><center><h1>Your Student ID is</h1> <h2>%s.</h2><h1> Subjects Registered : %s\n </h1>", $studentid, $ckb );
mysqli_stmt_close($stmt);
}
mysqli_close($dbcon);
die(" <p> The Student ID <strong>$studentid </strong>already exists. Update</p>");
the page update.html includes an update form that submits to update.php
how can I pass the the single fetched row variable (subjects registered/$ckb) to update.html ?
I tried the following so far:
at the firstpage.php I started a session
session_start();
$_SESSION['subjects'] = '$ckb';
and at the update.html > renamed to update2.php and added the following at the top of the page
<?php
session_start();
echo $_SESSION['sujects'];
?>
and at the input field the value="<?php echo $ckb;?>"
What am I missing ?
Please note, that the variable I want to pass is the subjects registered related to the student id checked in firstpage.php file meaning this :
printf("<br /><center><h1>Your Student ID is</h1> <h2>%s.</h2><h1> Subjects Registered : **%s**\n </h1>", $studentid, $ckb );
but its either completely wrong or I'm just passing the wrong variable
Remove quotes in:
$_SESSION['subjects'] = '$ckb';
So it will be:
$_SESSION['subjects'] = $ckb;
And update 2nd file to this:
<?php
session_start();
$ckb = $_SESSION['subjects'];
?>
....
<input type='text' value="<?php echo $ckb;?>" />
Note: also, you wrote sujects in second file, its ok in my code example.
In answer to my question I found an easy and effective by passing the variables through the url.
Meaning...
In my firstpage.php, the href links to my update2.php page became as follows:
Update
The $studentid and $cc variables are previously defined in my code where I "get" them from the input fields of the form.
In update2.php, the page which I would like to pass the variables to I inserted the following code
<?php
$studentid= $_GET['studentid'];
$cc = $_GET['ckb'];
?>
Which allowed me to use the variables throughout the rest of the php code, where for my case I wanted them to be the "values" of a new form input field, as shown below :
<input name="newcourses" type="text" id="newcourses" maxlength="70" value="<?php echo $cc?>"" />
I recommend anyone who wants a more clear idea and read more about other methods to pass variables across php pages to check this out >> Pass PHP fetch variable...
I have a button on a webpage that allows users to add a video on that page to their list of favourites. behind this button is a form and some php. The PHP code uses a session variable to retrieve the username. This information is used to get the relevant user id from the database and store its value in a variable. Using the input value from the form it was possible to retrieve the tuple from the videos database table that related to the video in question and store the values of the video title and URL attributes in variables. The code then checks if the user has already added the video as a “favourite”. The favourites database entity is checked for tuples containing both the user id and video id. If both are contained in a single row of the database table the user has already added the video and is notified of this. Otherwise, the user id, video id, video title and URL are inserted into the favourites database entity and the user is informed that the video has been added
this all works fine in chrome or safari but does nothing in ie or firefox. The database is updated and message is displayed only in Chrome and safari. I've attached the code, please note the session has already been started in earlier code on the webpage. Any assistance would be greatly appreciated.
<div id="addfav">
<form action="python.php" method="post">
<input name="add" src="images/add.png" type="image"
value="3">
</form>
<?php
$user=$_SESSION['user'];
if ( isset( $_POST['add'] ) )
{
$vid = $_POST["add"];
$sql = "SELECT * FROM `users` WHERE username = '$user'";
$result = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_array($result);
$uid= $row['user_id'];
$sql = "SELECT * FROM `Video` WHERE Video_id = '$vid'";
$result = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_array($result);
$url=$row['URL'];
$title=$row['Title'];
$check = mysql_query("SELECT * FROM `favourites` WHERE Uid = '$uid' AND vid_id = '$vid'") or die (mysql_error());
$r = mysql_num_rows($check);
if ($r>=1)
{
echo "already added to favourites";
echo '<script type="text/javascript">window.alert("Already added to favourites")</script>';
//'<span style="color: red;" />Already added to favourites </span>' ;
}
else
{
mysql_query("INSERT INTO `favourites` (`Uid`,
`vid_id`,`url`,`title`) VALUES ('$uid',
'$vid','$url','$title')")or die(mysql_error());
echo "Added to favourites";
}
}
?>
</div>
(Just a debug idea) Try to change your input image to a hidden element like this :
<form action="python.php" method="post">
<!-- I don't remove this, to keep the image shown-->
<input name="addimg" src="images/add.png" type="image" value="3">
<input type='hidden' name='add' value='3' />
</form>
Does it works now?
PHP is run server-side. This means that regardless of what browser you're using, it works as expected. The problem is definitely from HTML codes you've written if IE and Firefox can connect to your website without any problem.
I think the problem is inside your form tag because I think it's not standard you can either use a GET method inform that your form is submitted, or use a hidden input indicating it.
P.S. I think your code has security issues. (SQL Injection)
When user clicks on <input type="image" /> browser will pass coordinates of a click. Chrome will send three values:
add.x = x_coord
add.y = y_coord
add = input_value (3 in your case)
Note that in php you can access add.x/add.y value with $_POST["add_x"]/$_POST["add_y"] (see dot replaced with underscore)
At the same time, IE will not pass third value. That is why your if ( isset( $_POST['add'] ) ) will never return true. Option is to put video id value into some hidden field and use its name in that if.
You can easily check that behavior by doing var_dump($_POST); in php
PS:
You should never use values received in request without them being sanitized in sql queries. Right now code below is opened to sql injections:
$sql = "SELECT * FROM `Video` WHERE Video_id = '$vid'";
You should, at least, user mysql_real_escape_string function before value is inserted into a query:
$sql = "SELECT * FROM `Video` WHERE Video_id = '".mysql_real_escape_string($vid)."'";
And take a look at warning message on top of php manual page linked above: mysql_* functions are deprecated and you should better use PDO or mysqli extension.
This code works. I can't figure out how to insert data into db If user pressed "SAVE" button for the first time or update data.
The php side
<?php
require '../../core/includes/common.php';
$name=filter($_POST['name'], $db);
$title=filter($_POST['title'], $db);
$parentcheck=filter($_POST['parentcheck'],$db);
if(isset ($_POST['parent'])) $parent=filter($_POST['parent'],$db);
else $parent=$parentcheck;
$menu=filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);
$result=$db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')") or die($db->error);
$new_id = $db->insert_id;
$result2=$db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')") or die($db->error);
if ($new_id>0){
echo "{";
echo '"msg": "success" ';
echo "}";
}else{
echo "{";
echo
'"err": "error"';
echo "}";
}
?>
UPDATE
Thanks to #jmlsteeke i found the way
Place this piece of code in html part
<?php
$result=$db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('555', 'new', '0')") or die($db->error);
$new_id = $db->insert_id;
$result2=$db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', 'new', 'new')") or die($db->error);
?>
And added following code into form
<input type="hidden" name="id" value="<?=$new_id?>"/>
In serverside script used
$result=$db->query("UPDATE pages AS p, menu AS m SET m.parent='$parent', m.name='$name', m.showinmenu='$menu', p.id='$id', p.title='$title', p.content='$content' WHERE m.id='$id' AND p.id=m.id") or die($db->error);
Thank you #jmlsteeke
A common way would be to store the id as a hidden field when you are editing the page. This way when the user submits the page, if there is an id present, you issue the UPDATE commands, and if there isn't one present, you know it's a new page, and issue the INSERT commands.
If you need me to be more thorough let me know.
Edit: Being More Thorough
I'll make a simple, complete, example of what I mean.
Form.php pseudo code
//set default values for fields
//print form tag
if (isset($'id',$_GET)) {
//fetch data from database
//print hidden id field
//override default values for fields
}
//print rest of fields using default values (possibly overridden)
DoForm.php pseudo code
//Sanitize user input
if (isset('id',$_POST)) {
//UPDATE database with user input
} else {
//INSERT new rows into table with user input
}
Let's say you have a php file called Form.php which is responsible for displaying the form, and another php script called DoForm.php which is responsible for handling the form.
If a user visits Form.php with no ID specified (http://example.com/Form.php) then it will display the following form:
<form method="post" action="DoForm.php">
<input type="text" name="name" value="" />
<input type="text" name="title" value="" />
... other stuff ...
</form>
The user will add some information, click on the submit button and DoForm will get the following POST variables:
"name" => "NewPageName"
"title" => "My First Webpag" [intetional typo, see later]
... other stuff ...
DoForm will check to see if $_POST['id'] exists. Since it doesn't DoForm issues the INSERT commands to add a new page.
Later on, the user realises the made a typo, and goes to fix it. The user clicks on the "Edit Page" control for "NewPageName" which will be http://example.com/Form.php?id=1
Form.php see's that id is set, so the form it prints out is as follows:
<form method="post" action="DoForm.php">
<input type="hidden" name="id" value="1"
<input type="text" name="name" value="NewPageName" />
<input type="text" name="title" value="My First Webpag" />
... other stuff ...
</form>
The user fixes their type, changing Webpag to Webpage, and hits submit. DoForm gets the following Post variables
"id" => 1
"name" => "NewPageName"
"title" => "My First Webpage"
... other stuff ...
DoForm sees that id is set, and so uses UPDATE instead of INSERT.
Any more clear?
MySQL has an INSERT ... ON DUPLICATE KEY UPDATE feature that will let you try to insert a row, or fall back to an update if it discovers a duplicate key (i.e. the row already exists).
I am new to PHP and working on small local webpage and database that takes user information and database stores the same user information .If i Login with ADMIN it shows all data. My requirement is that the loggined user is an admin, then he has a right to edit all the informtion of the users that i stored in the database.And this is to be done using GET method . How it will be working?
Heres some example code purely to demonstrate how to update a table using a GET method form. The code doesn't have any kind of error checking and assumes you already know how to connect to your database (and that its MySQL).
Assuming you've landed on a page which invites you to edit data, which record you're editing is referenced by an 'id' variable on the URL which matches a numerical primary key in your database table.
<?php
$SQL = "SELECT myField1,myField2 FROM myTable WHERE myKeyField = '".intval($_GET['id'])."'";
$QRY = mysql_query($SQL);
$DATA = mysql_fetch_assoc($QRY);
?>
<form method='get' action='pageThatStoresData.php'>
<input type='hidden' name='key' value='<?php echo $_GET['id']; ?>' />
<input type='text' name='myField1' value="<?php echo $DATA['myField1']; ?>" />
<input type='text' name='myField2' value="<?php echo $DATA['myField2']; ?>" />
<button type='submit'>Submit</button>
</form>
So, this will give you a page that takes the data out of your table, displays it in a form with pre-filled values and on submit, will go to a URL like:
http://mydomain.com/pageThatStoresData.php?key=1&myField1=someData&myField2=someMoreData
In that page, you can access variables 'key', 'myField1', 'myField2' via the $_GET method.
Then you just need to update your table within that page:
$SQL = "UPDATE myTable
SET myField1 = '".mysql_real_escape_string($_GET['myField1'])."',
myField2 = ".mysql_real_escape_string($_GET['myField1'])."
WHERE key = '".intval($_GET['key'])."'
";
$QRY = mysql_query($SQL);
PLEASE NOTE: The code above is unsuitable for a straight copy/paste as it doesn't do any error checking etc, its purely a functional example (and typed straight in here so I apologise if there are any typos!).