Having problems going from mysqli_query to mysqli_prepare - php

I'm new to PHP and made a simple php site that allows me to submit a form and delete data stored in a database. I was told it was better to use prepared statements to avoid SQL Injection.
I updated my delete and it still works, not sure if it's totally right:
<?php
include("dbconnect.php");
$getid = $_GET["id"];
$delete = mysqli_prepare($database,"DELETE FROM contacts WHERE id IN ($getid)");
mysqli_stmt_execute($delete);
header("Location:http://localhost/address-book");
exit;
?>
But I can't seem to get the add to database feature to work. I tried a variety of different ways to write it, but I'm sure that I'm missing something simple. Here's the unsafe code that I originally wrote:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
include("inc/dbconnect.php");
// assigns form data to table columns
$assign = "INSERT INTO contacts(firstName,lastName,email,phone,birthday) VALUES ('$_POST[firstName]','$_POST[lastName]','$_POST[email]','$_POST[phone]','$_POST[birthday]')";
//execute query
if (mysqli_query($database,$assign)) {
header("Location:http://localhost/address-book/");
exit;
} else {
exit;
}
?>
If someone could guide me in the right direction I'd be thankful. I'm new to all of this.
UPDATED: I've updated my original code and came up with this instead for delete:
<?php
include("dbconnect.php");
$getid = $_GET["id"];
$delete = mysqli_prepare($database,"DELETE FROM contacts WHERE id IN (?)");
mysqli_stmt_bind_param($delete, 's', $getid);
mysqli_stmt_execute($delete);
header("Location:http://localhost/address-book");
exit;
?>
and the add feature:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
include("inc/dbconnect.php");
$firstName = "$_POST[firstName]";
$lastName = "$_POST[lastName]";
$email = "$_POST[email]";
$phone = "$_POST[phone]";
// assigns form data to table columns
$assign = mysqli_prepare($database,"INSERT INTO contacts(firstName,lastName,email,phone) VALUES (?,?,?,?)");
mysqli_stmt_bind_param($assign, 'ssss', $firstName, $lastName, $email, $phone);
mysqli_stmt_execute($assign);
exit;
}
?>

A simple Prepare statement is something along the lines of
$query = $this->db->prepare("Query here WHERE something = ?") - note this example is taken from my site so you'll likely have something else instead of $this->->prepare.
The key thing is that the "= something " is denoted as a question mark.
You then bind the value of that question mark to the query
$query->bindValue(1, passed in parameter)
As a fully working example:
//function to add 1 to downloads each time a file is downloaded
public function addToDownload($filename){
$query = $this->db->prepare('UPDATE trainingMaterial SET downloads = downloads + 1 WHERE filename = ?');
$query->bindValue(1, $filename);
try{
$query->execute();
}catch(PDOException $e){
die($e->getMessage());
}
}
Your query `$assign = "INSERT INTO contacts(firstName,lastName,email,phone,birthday) VALUES ('$_POST[firstName]','$_POST[lastName]','$_POST[email]','$_POST[phone]','$_POST[birthday]')";
would be
$assign = "INSERT INTO contacts(firstName,lastName,email,phone,birthday) VALUES ?,?,?,?,?)";
$assign->bindValue(1, '$_POST[firstName]')
$assign->bindValue(2, '$_POST[lastName]')
etc etc

Related

How do I insert an entry to an SQL table using a variable received from POST

I am trying to pass text variables from a form form a previous page and insert it into a SQL table. The problem I'm having is on the line: $sql = "INSERT INTO CUSTOMER (fname, lname) VALUES ($firstName, 'smith')";.
If I were to replace "$firstName" with a basic string like "John", the name and last name would be inserted into the SQL table as intended. But, since I'm trying to insert a text value gathered from a form, I need to be able to use the non-static variables but for some reason that I cannot figure out, doesn't work. From everything I read online, just adding the variable into the parameter should make it work but it just doesn't.
I'm very new to this so I'm sorry if my question is confusing. Also, I am fairly certain that the issue does not lie on the file with the form on it.
Any help would be so awesome. thanks!
Here is the code that I'm having trouble with:
<html>
<?php
$username = $_Post['username'];
$email = $_Post['email'];
$phone = $_Post['number'];
$firstName = $_Post['firstName'];
$lastName = $_Post['lastName'];
$address = $_Post['address'];
$password = $_Post['password'];
$conn = new mysqli('localhost','root','password','database');
if($conn->connect_error){
echo "$conn->connect_error";
die("Connection Failed : ". $conn->connect_error);
} else {
$sql = "INSERT INTO CUSTOMER (fname, lname) VALUES ($firstName, 'smith')";
$conn->query($sql);
echo $execval;
echo "Registration successfully...";
$conn->close();
}
?>
</html>
To summarize all other answers,
First, you should replace $firstName to '$firstName' because otherwise the text (e.g. "John") will be placed in your query without quotes, like this: INSERT INTO CUSTOMER (fname, lname) VALUES (John, 'smith') This results in an error because it thinks John is some sort of variable.
Second, your code is vulnerable to SQL Injection. This is a very serious vulnerability in your website as attackers can use it to read your entire database, and in this case, even create entries in your database, which can result in attackers being able to completely take over your site by writing files!
More in-depth info here: https://owasp.org/www-community/attacks/SQL_Injection
The important thing is that the user can control the $firstName variable that you use in $sql = "INSERT INTO CUSTOMER (fname, lname) VALUES ('$firstName', 'smith')"; This way the attacker can change the query at that point. He could for example use the payload ', 'a'); DROP TABLE CUSTOMER;-- to delete all information in the CUSTOMER table.
There are multiple ways to prevent this, but the easiest is to use prepared statements. It looks something like this:
$stmt = $dbConnection->prepare("INSERT INTO CUSTOMER (fname, lname) VALUES (?, ?)");
$stmt->bind_param('ss', $param_firstName, $param_lastName);
$param_firstName = $firstName; // New line
$param_lastName = $lastName; // New line
$stmt->execute();
This way you make sure MySQL doesn't interpret any user input as SQL code, but only as values.
Again, more in-depth information here:
https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
If you get user input to insert into a database you should always use "Prepared statements" to prevent "SQL injection" or comparable things.
Check here:
PHP Prepared Statements - w3school
The solution of Aashish gaba should work as well but it's unsecure.
This should work for your code:
<?php
$username = $_POST['username'];
$email = $_POST['email'];
$phone = $_POST['number'];
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$address = $_POST['address'];
$password = $_POST['password'];
$conn = new mysqli('localhost','root','password','database');
if($conn->connect_error){
echo "$conn->connect_error";
die("Connection Failed : ". $conn->connect_error);
} else {
$stmt = $conn->prepare("INSERT INTO CUSTOMER (fname, lname) VALUES (?, ?)");
$stmt->bind_param("ss",$fname, $lname);
// set parameters and execute
$fname = $firstName;
$lname = $lastName;
$stmt->execute();
echo $execval;
echo "Registration successfully...";
$conn->close();
}
?>
A nice to have of a prepared statement is the fact that they are reusable like:
// set parameters and execute
$fname = "person1_fname";
$lname = "person1_lname";
$stmt->execute();
$fname = "person2_fname";
$lname = "person2_lname";
$stmt->execute();
Also don't forget to use somthing to prevent other injections if you print a value to a user. Like:
echo "Registration successfully for" . htmlspecialchars($_Post['username']);
In addition save the password as hash (with a secure hashfunction) into the database.
As a quick fix you can update your $sql like this:
$sql = "INSERT INTO CUSTOMER (fname, lname) VALUES ('{$firstName}', '{$lastName}')";
But now your code is vulnerable to SQL Injection.
At least you should use mysqli escape function before your $sql statement, like this:
$firstName = $mysqli->real_escape_string($firstName);
$lastName = $mysqli->real_escape_string($lastName);
But I strongly recommend you considering using more advanced options like PDO for the further steps and Production environments.
Remplace $firstName to '$firstName'.
or use prepared request

Why does the user input not append to my SQL database?

I'm developing a login/register form for my client. Right now I am working on the registration part of the form however I seem to have encountered an issue.
I am trying to append the user's input to a database if it does not currently exist. I'm developing this functionality using PHP version 7. However, the code does not seem to append the data to the database even when telling me it has done so successfully.
Here is code:
<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
//define variables and set values to null
$email = $code = "";
//set variable values to HTML input
$email = $_POST['email'];
$code = $_POST['code'];
//check if email exists
$stmt = $conn->prepare("SELECT userEmail FROM userDetails WHERE userEmail=?");
$stmt->bind_param("s", $prepemail);
//set parameters and execute
$prepemail = $email;
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "email exists";
return false;
} else {
//$stmt->close(); removed as per #Akintunde-Rotimi's suggestion
//insert email into database
$stmt = $conn->prepare("INSERT INTO userDetails (userEmail) VALUES (?)");
$stmt->bind_param("s", $newemail);
//set parameters and execute
$newemail = $email;
$stmt->execute();
echo "New records created successfully";
}
}
?>
The code successfully connects to the database and even tells me if the user already exists. It just doesn't add the user's email to the database and I can't seem to figure out why.
I have researched methods on how to insert the data into the database using prepared statements as I have done here. I've used W3Schools as a reference but still no luck.
The code doesn't seem to have any obvious spelling errors, so have you tried to catch errors? Replace
$stmt->execute();
with
if(!$stmt->execute()) {
trigger_error("there was an error....".$conn->error, E_USER_WARNING);
}
You can also check how many rows are affected, -1 meaning there was an error.
printf("%d Zeile eingefügt.\n", $stmt->affected_rows);
Also, enabling more errors to be shown (at least for development)
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// ...

prepare($sql) function not working on one script

I'm working on a school project involving a website with database integration. Currently working on adding new content (text, titles, images) to the website through it. I can already add new users to the database through the website, but for some reason the same code and logic doesn't apply for the content.
I noticed that printing $stmt with echo does not print anything.
<?php
include "../conn.php";
$sql = "INSERT INTO `contenido` (`id_contenido`, `tipo_contenido`, `id_seccion`, `orden_contenido`, `largo_contenido`, 'corto_contenido', 'extra_contenido') VALUES (NULL, '".$_POST["tipo"]."', '".$_GET['id']."','".$_POST["orden"]."','".$_POST["largo"]."','".$_POST["corto"]."','".$_POST["extra"]."')";
$stmt = $conn->prepare($sql);
if ($stmt = $conn->prepare($sql))
{
//echo "It worked";
$stmt->execute();
$last_id = $conn->insert_id;
header("Location: editarContenidos.php?id=".$_GET['id']);
}
?>
Expected Results: The content information is uploaded to the database and the user is redirected to the Edit Contents page (editarContenidos.php)
Actual Results: White screen, no errors. Since the if condition is false, you are never redirected and the content is not uploaded to the database.
NOTE: The Insert User .php is working with the same logic and syntax, I'm not experienced enough with php to understand what I'm doing wrong.
I am assuming id_contenido is an auto_increment field and I'm not sure houw the backticks work in various languages. I would recommend adding some error handling PDO::errorInfo
and changing the SQL code to:
$sql = "INSERT INTO contenido (tipo_contenido, id_seccion, orden_contenido, largo_contenido, corto_contenido, extra_contenido) VALUES ('".$_POST["tipo"]."', '".$_GET['id']."','".$_POST["orden"]."','".$_POST["largo"]."','".$_POST["corto"]."','".$_POST["extra"]."')";
There is a $_GET['id'] in the SQL code and I cant tell if that is intentional.
I would recommend using parameters and some debugging using print_r($_POST);.
Try the following code:
<?php
include "../conn.php";
$sql = "INSERT INTO contenido (id_contenido, tipo_contenido, id_seccion, orden_contenido, largo_contenido, corto_contenido, extra_contenido) VALUES (?,?,?,?,?,?)";
$stmt = $conn->prepare($sql);
if ($stmt))
{
//echo "It worked";
$stmt->execute(array($_POST["tipo"], $_GET['id'],$_POST["orden"],$_POST["largo"],$_POST["corto"],$_POST["extra"]));
$last_id = $conn->lastInsertId();
header("Location: editarContenidos.php?id=".$_GET['id']);
}
?>
I found out what the problem was. The quotation marks were not properly used.
The following code worked:
<?php
include "../conn.php";
$sectionid = $_GET['id'];
$sql = "INSERT INTO contenido (id_contenido, tipo_contenido, id_seccion, orden_contenido, largo_contenido, corto_contenido, extra_contenido) VALUES (NULL, '".$_POST["tipo"]."', '".$sectionid."','".$_POST["orden"]."','".$_POST["largo"]."','".$_POST["corto"]."','".$_POST["extra"]."')";
$stmt = $conn->prepare($sql);
//echo $sql;
if ($stmt = $conn->prepare($sql))
{
$stmt->execute();
$last_id = $conn->insert_id;
header("Location: editarContenidos.php?id=".$sectionid);
}
?>

mysqli multiple insert not submitting all lines from array

I have a big issue with my code I suspect.
It only adds the first of $species, $weight and $length. but if there is more than one value in the $_Post.
It should submit them as well from my form. I am having trouble seeing where I have gone wrong.
I hope somebody, can point me in the right direction?
<?php
require 'config.php';
$teamid = $_POST['teamid'];
$species = $_POST['species']; // Can be multiple values depending on how many lines added from form
$weight = $_POST['weight']; // Can be multiple values depending on how many lines added from form
$length = $_POST['length']; // Can be multiple values depending on how many lines added from form
// count($species),($weight),($length) - Should always be the same length
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
// Prepare an insert statement
$sql = "INSERT INTO indvejninger ( teamid, artid, vaegt, laengde) VALUES (?, ?, ?, ?)";
if($stmt = $mysqli->prepare($sql)){
foreach ($species as $key => $value) {
// Bind variables to the prepared statement as parameters
$stmt->bind_param("ssss", $_POST['teamid'], $param_species, $param_weight, $param_length);
$param_species = $species[$key];
$param_weight = $weight[$key];
$param_length = $length[$key];
// Attempt to execute the prepared statement
if($stmt->execute()){
// Records created successfully. Redirect to landing page
header("location: index.php?limit=");
exit();
} else{
echo "Something went wrong. Please try again later.";
}
}
// Close statement
$stmt->close();
}
// Close connection
$mysqli->close();
}
I found the error, after first submit it changes url. So it does not finish the other submissions.
// Attempt to execute the prepared statement
if($stmt->execute()){
// Records created successfully. Redirect to landing page
header("location: index.php?limit=");
exit();
} else{
echo "Something went wrong. Please try again later.";
}
So instead, I need it to finish the other submissions, and then redirect to landing page.

Submit variable in URL to MySQL Database

I would like to have a page that, when someone clicks a pre-formatted link I've sent, writes a variable in the URL to a MySQL database and just displays "Thank You" or something to the user.
Example:
The user would click a link formatted something like http://www.example.com/click.php?id=12345
When the page loads the 12345 would be written to a table in a MySQL database, it would show a Thank you, and that is it.
Seems like it should be simple enough but I can't find anything on it. I'm probably searching wrong, since this is all new to me.
Your best bet is to utilise $_GET['id'] which will take in the value from your url.
After grabbing the id from your url you will want to use PDO or mysqli prepared statements in order to protect yourself from sql injection.
I hope this helps.
Updated as per Kevin Voorn's comment.
if(isset($_GET['id']) && !empty($_GET['id'])) {
$logged_id = $_GET['id'];
$stmt = $mysqli->prepare("INSERT INTO tableName (`logged_id`) VALUES (?)");
$stmt->bind_param('i', $logged_id);
$stmt->execute();
if($stmt->affected_rows > 0){
echo "Thank You.";
}
$stmt->close();
}
User $_GET to retrive the value and put into your table.
Example:
code inside click.php
<?php
$id=$_GET['id'];
$sql="Insert into table1 VALUES ($id)";
mysqli_query($connect,$sql);
echo "<script>alert('Thank you')</script>";
?>
Thanks for the responses. I ended up finding this page: https://www.binpress.com/tutorial/using-php-with-mysql-the-right-way/17 that described the process for using mysqli to connect to my database. I used that page to create the necessary functions in ../db.php and included it in the actual PHP script that would catch the url. My script ended up looking like this:
<?php
require '../db.php';
date_default_timezone_set('UTC');
$date = date("Y-m-d H:i:s T");
$db = new Db();
$db_id = $db -> quote($_GET['id']);
$db_date = $db -> quote($date);
$result = $db -> query("INSERT INTO `table` (`id`,`GUID`,`AccessTime`) VALUES (NULL, " . $db_id . "," . $db_date . ")");
if($result === false) {
exit();
} else {
echo "<html><body><center><br><h1>Thank You!</h1></center></body></html>";
}
?>

Categories