I have a form with some optional fields. In the database those fields are set to accept NULL.
The code below will throw an error if some field is empty. Could you please assist on what is the best way to avoid this? The only solution I was thinking of is to set the vars to ' ' if is empty().
$query = "INSERT INTO gifts (dateRequest, firstName, lastName, note, lastUpdated)
VALUES (?, ?, ?, ?, NOW())";
if ($stmt = $dbc->prepare($query)) {
$dateRequest = $_POST['dateRequest'];
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$note = $_POST['note'];
$stmt->bind_param('ssss', $dateRequest, $firstName, $lastName, $note);
if ($stmt->execute()) {
$stmt->close();
header('Location: index.php');
} else {
echo $stmt->error;
}
}
I would rather suggest to check $_POST paramenters before definied them so if a variable is not empty set values otherwise set as NULL
if(!empty($_POST['dateRequest'])) { $dateRequest = $_POST['dateRequest']; } else { $dateRequest = NULL; }
if(!empty($_POST['firstName'])) { $firstName = $_POST['firstName']; } else { $firstName = NULL; }
if(!empty($_POST['lastName'])) { $lastName = $_POST['lastName']; } else { $lastName = NULL; }
if(!empty($_POST['lastName'])) { $note = $_POST['note']; } else { $note = NULL; }
This will prevent you to pass empty parameters in your query.
Since PHP 7 you can set the default value for a variable using the elvis-operator.
$dateRequest = $_POST['dateRequest'] ?: null;
$firstName = $_POST['firstName'] ?: null;
$lastName = $_POST['lastName'] ?: null;
$note = $_POST['note'] ?: null;
If any of the fields is empty or undefined it will set the value to NULL and insert that into database instead.
As a side note you should read How to get the error message in MySQLi? instead of print out the error messages manually.
Related
I need to change the first if statement into a PDO statement but I'm not sure how to go about it. Please can someone help?
When users submit a form I want their email address to be pulled from the users table on the database into this page on the website, using the numbered $id they are assigned when they sign up.
$table = 'suggestions';
$id = (isset($_SESSION['u_id']) ? $_SESSION['u_id'] : null);
if ( NULL !== $id) {
$sql = mysqli_query($conn, "SELECT email FROM users WHERE u_id='$id'");
$fetch = mysqli_fetch_assoc($sql);
$email = $fetch['email'];
}
$email;
$optionOne = '';
$optionTwo = '';
$suggestions = selectAll($table);
if (isset($_POST['new-suggestion'])) {
global $conn;
$id;
$email;
$optionOne = $_POST['optionOne'];
$optionTwo = $_POST['optionTwo'];
$sql = "INSERT INTO $table (user_id, email, option_1, option_2) VALUES (?, ?, ?, ?)";
if (!empty($optionOne) && !empty($optionTwo)) {
$stmt = $conn->prepare($sql);
$stmt->bind_param('ssss', $id, $email, $optionOne, $optionTwo);
$stmt->execute();
} else {
echo "All options must be entered";
}
}
Make a connection
Firstly you need to replace your mysqli connection with a PDO one (or at least add the PDO connection alongside the mysqli one!).
// Define database connection parameters
$db_host = "127.0.0.1";
$db_name = "name_of_database";
$db_user = "user_name";
$db_pass = "user_password";
// Create a connection to the MySQL database using PDO
$pdo = new pdo(
"mysql:host={$db_host};dbname={$db_name}",
$db_user,
$db_pass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => FALSE
]
);
Updating your code
Prepared statements with mysqli and PDO
It's almost always better to use prepared statements when putting variable data into an SQL query. Not only is it safer (if the data comes from any sort of user generated input) but it also makes it easier to read, and easier to run multiple times with different values.
Prepared query with mysqli:
$sql = "SELECT column1, column2 FROM table WHERE column3 = ? AND column4 = ?";
$query = $mysqli->prepare($sql);
$query->bind_param("si", $string_condition, $int_condition);
$query->execute();
$query->store_result();
$query->bind_result($column1, $column2);
$query->fetch();
echo "Column1: {$column1}<br>";
echo "Column2: {$column2}";
Prepared query with PDO:
$sql = "SELECT column1, column2 FROM table WHERE column3 = ? AND column4 = ?";
$query = $pdo->prepare($sql);
$query->execute([$string_condition, $int_condition]);
$row = $query->fetchObject();
# $row = $query->fetch(); // Alternative to get indexed and/or associative array
echo "Column1: {$row->column1}<br>";
echo "Column2: {$row->column2}";
Updated code
// Using the NULL coalescing operator here is shorter than a ternary
$id = $_SESSION['u_id'] ?? NULL;
if($id) {
$sql = "SELECT email FROM users WHERE u_id = ?";
$query = $pdo->prepare($sql); // Prepare the query
$query->execute([$id]); // Bind the parameter and execute the query
$email = $query->fetchColumn(); // Return the value from the database
}
// Putting "$email" on a line by itself does nothing for your code. The only
// thing it does is generate a "Notice" if it hasn't been defined earlier in
// the code. Best use:
// - The ternary operator: $email = (isset($email)) ? $email : "";
// - The NULL coalescing operator: $email = $email ?? "";
// - OR initialize it earlier in code, before the first `if`, like: $email = "";
// N.B. Instead of "" you could use NULL or FALSE as well. Basically in this case
// anything that equates to BOOL(FALSE); so we can use them in `if` statements
// so the following (2 commented lines and 1 uncommented) are effectively
// interchangeable.
$email = $email ?? "";
# $email = $email ?? FALSE;
# $email = $email ?? NULL;
// Presumably you will also want to change this function to PDO and prepared statements?
// Although it doesn't actually do anything in the code provided?
$suggestions = selectAll($table);
// Same as with email, we're just going to use the NULL coalescing operator.
// Note: in this case you had used the third option from above - I've just
// changed it so there is less bloat.
$optionOne = $_POST['optionOne'] ?? "";
$optionTwo = $_POST['optionTwo'] ?? "";
$newSuggestion = $_POST['new-suggestion'] ?? "";
// There's no point nesting `if` statements like this when there doesn't appear to be any
// additional code executed based on the out come of each statement? Just put it into one.
// We now don't need to use empty etc. because an empty, false, or null string all.
// equate to FALSE.
if($newSuggestion && $id && $email && $optionOne && $optionTwo) {
// Not sure why you've made the the table name a variable UNLESS you have multiple tables
// with exactly the same columns etc. and need to place in different ones at different
// times. Which seems unlikely so I've just put the table name inline.
$sql = "INSERT INTO suggestions (user_id, email, option_1, option_2) VALUES (?, ?, ?, ?)";
$query = $pdo->prepare($sql);
$query->execute([$id, $email, $optionOne, $optionTwo]);
}
else{
echo "All options must be entered";
}
Without comments
$id = $_SESSION['u_id'] ?? NULL;
if($id) {
$sql = "SELECT email FROM users WHERE u_id = ?";
$query = $pdo->prepare($sql);
$query->execute([$id]);
$email = $query->fetchColumn();
}
$email = $email ?? "";
$suggestions = selectAll($table);
$optionOne = $_POST['optionOne'] ?? "";
$optionTwo = $_POST['optionTwo'] ?? "";
$newSuggestion = $_POST['new-suggestion'] ?? "";
if($newSuggestion && $id && $email && $optionOne && $optionTwo) {
$sql = "INSERT INTO suggestions (user_id, email, option_1, option_2) VALUES (?, ?, ?, ?)";
$query = $pdo->prepare($sql);
$query->execute([$id, $email, $optionOne, $optionTwo]);
}
else{
echo "All options must be entered";
}
How to solve this i don't add data using by $_Post Method, but without $_POST method showing undefine variable?
if (isset($_POST['firstname']) && isset($_POST['lastname']) && isset($_POST['age'])){
//Getting values
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$age = $_POST['age'];
//Creating an sql query
$sql = "INSERT INTO info (firstname,lastname,age) VALUES ('$firstname','$lastname','$age')";
//Importing our db connection script
require_once('connect.php');
//Executing query to database
if(mysqli_query($con,$sql)){
echo 'Employee Added Successfully';
}else{
echo 'Could Not Add Employee';
}
//Closing the database
mysqli_close($con);
}
You need to define your variables to something if $_POST is not set.
So code would look something like this:
$firstname = isset($_POST['firstname']) ? $_POST['firstname'] ? "";
$lastname = isset($_POST['lastname']) ? $_POST['lastname'] : "";
$age = isset($_POST['age']) ? $_POST['age'] : "";
//if isset $_POST['age'] then assign it to $_POST['age'] else assign it to ""
if (isset($_POST['firstname']) && isset($_POST['lastname']) && isset($_POST['age'])){
//Creating an sql query
$sql = "INSERT INTO info (firstname,lastname,age) VALUES ('$firstname','$lastname','$age')";
//Importing our db connection script
require_once('connect.php');
//Executing query to database
if(mysqli_query($con,$sql)){
echo 'Employee Added Successfully';
}else{
echo 'Could Not Add Employee';
}
//Closing the database
mysqli_close($con);
}
Bonus:
You code can be easily injected. Use prepared statements to avoid this.
$sql = "INSERT INTO info (firstname,lastname,age) VALUES (?,?,?)"; // question marks are placeholders to bind values to
$stmt = $con->prepare($sql); // prepare query
$stmt->bind_param("sss", $firstname, $lastname, $age); // bind values to your query
if($stmt->execute()){ // if success
echo 'Employee Added Successfully';
}else{
echo 'Could Not Add Employee';
}
You can learn more about it here
Try changing this one:
$sql = "INSERT INTO info (firstname,lastname,age) VALUES ('$firstname','$lastname','$age')";
To this one:
$sql = "INSERT INTO info (firstname,lastname,age) VALUES ('".$firstname."','".$lastname."','."$age."')";
am getting the following error from my code:
Binding parameters failed: (1064) You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? (Name, Address, Location, Phone, Email, Time, Website, Photo1, Rating, Date_Pu' at line 1
Can anyone help me out please? Here is my code:
include("mysqli.php");
$search_tbl = mysql_query("SELECT * from listing_title where listing_title_ID = '$main_id'");
$tbl_name = $search_tbl['tbl_name'];
$stmt = $db->stmt_init();
global $tbl_name;
if($stmt->prepare("INSERT INTO ? (Name, Address, Location, Phone, Email, Time, Website, Photo1, Rating, Date_Published, categories_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"))
{
$stmt->bind_param('sssssssssisi',$tbl_name,$title,$address,$location,$phone,$email,$time,$website,$name,$rating,$date,$sub_cat);
$title = $_POST['name'];
$email = $_POST['email'];
$address = $_POST['address'];
$location = $_POST['location'];
$phone = $_POST['phone'];
$time = $_POST['time'];
$rating = $_POST['rating'];
$main = $_POST['main'];
$website = $_POST['website'];
$date = date('Y-m-d');
$stmt->execute();
$stmt->close();
}
else
{
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
else
{
echo 'a';
}
your script appears to be incomplete, but doing the best i could with what you had this is what you need. first of all, ditch whatever mysqli wrapper crap you are using. it is teaching you bad principles.
first file, your db info. call it config.php or whatever the hell you want. use require once instead of include. also, ditch the parenthesis around the requires these are not necessary at all, and use single quotes instead of double quotes. single quotes are treated as strings while double quotes php will search for variables inside, thus spending more resources from the cpu/cache.
config.php
$host = 'localhost';//your db host
$user = 'someuser'; //your db user
$pass = 'somepass'; //your db password
$name = 'somedb'; //the name of your db
$mysqli = new mysqli($host,$user,$pass,$name);
if(mysqli_connect_errno()) {
echo "Connection Failed: " . mysqli_connect_errno();
exit;
}else{
global $mysqli;//make your db connection available globally
}
Now for your script
script.php
require_once 'config.php';
//keep your post variables up here. you still need to santize and trim these
$title = $_POST['name'];
$email = $_POST['email'];
$address = $_POST['address'];
$location = $_POST['location'];
$phone = $_POST['phone'];
$time = $_POST['time'];
$rating = $_POST['rating'];
$main = $_POST['main'];
$website = $_POST['website'];
$date = date('Y-m-d');
global $mysqli;//fetch your db connection
$stmt = $mysqli->prepare("SELECT tbl_name from listing_title where listing_title_ID = ? ");
$stmt->bind_param('i',$main_id);
if($stmt->execute()) {
$stmt->bind_result($tbl_name);
$stmt->close();
$stmt = $mysqli->prepare("INSERT INTO ".$tbl_name."
(Name, Address, Location, Phone, Email, Time, Website, Photo1, Rating, Date_Published, categories_ID)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
$stmt->bind_param('ssssssssisi',$title,$address,$location,$phone,$email,$time,$website,$name,$rating,$date,$sub_cat);
if($stmt->execute()) {
$stmt->close();
}else{
$stmt->close();
//catch the error
}
}else{
$stmt->close();
//throw an exception or handle the error here.
}
Please note, this still needs work. you need to sanitize and trim your variables. here's an example function. to include funcs, just add a require_once to the config.php file, and it will be included in any file you include config.php in.
example of this:
require_once 'funcs.php';
example sanitize function:
funcs.php
function security($value) {
if(is_array($value)) {
$value = array_map('security', $value);
} else {
if(!get_magic_quotes_gpc()) {
$value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
} else {
$value = htmlspecialchars(stripslashes($value), ENT_QUOTES, 'UTF-8');
}
$value = str_replace("\\", "\\\\", $value);
}
return $value;
}
to call the function
$title = security(trim($_POST['name']));
I leave the sanitizing to you. its a valuable exercise and you have an example that will sanitize anything, whether it be integers, arrays, objects, or strings.
you should only use trims on strings though. if you want to sanitize an entire array, just use the security function.
good luck.
I've made a user class which validates the data passed through the form and then subsequently updates the database table users. I want to add extra functionality such as checking if the username and email exists in the table, I've added a little script however it doesn't seem to be working.
I inserted a duplicated email address and I did not get the error message "email exists" instead I get the success message "1 row inserted":
Am I doing something wrong below? Is there perhaps a better way to approach this?
public function insert() {
if (isset($_POST['submit'])) {
$email = isset($_POST['email']) ? $this->mysqli->real_escape_string($_POST['email']) : '';
$result = $this->mysqli->prepare("SELECT * FROM users WHERE email='".$email."'");
if ($result->num_rows) {
echo "email exisits!";
}
else
{
$stmt = $this->mysqli->prepare("INSERT INTO users (username, password, name, email) VALUES (?, ?, ?, ?)");
$stmt->bind_param('ssss', $username, $password, $name, $email); // bind strings to the paramater
//escape the POST data for added protection
$username = isset($_POST['username']) ? $this->mysqli->real_escape_string($_POST['username']) : '';
$cryptedPassword = crypt($_POST['password']);
$password = $this->mysqli->real_escape_string($cryptedPassword);
$name = isset($_POST['name']) ? $this->mysqli->real_escape_string($_POST['name']) : '';
$email = isset($_POST['email']) ? $this->mysqli->real_escape_string($_POST['email']) : '';
/* execute prepared statement */
$stmt->execute();
printf("%d Row inserted.\n", $stmt->affected_rows);
/* close statement and connection */
$stmt->close();
}
You are using the worst API you ever can choose.
With safeMysql it would be
$exists = $this->db->getOne("SELECT 1 FROM users WHERE email=?s", $_POST['email']);
if ($exists) {
echo "email exisits!";
}
With PDO it is slightly longer but usable
$stmt = $this->db->prepare("SELECT 1 FROM users WHERE email=?");
$stmt->execute(array($_POST['email']));
$exists = $stmt->fetchColumn();
if ($exists)
{
echo "email exisits!";
}
But with raw mysqli you will need a screenful of code only to check if user exists.
So, the whole function using safeMysql would be
public function insert()
{
if (!isset($_POST['submit'])) {
return FALSE;
}
$sql = "SELECT 1 FROM users WHERE email=?s";
$exists = $this->db->getOne($sql, $_POST['email']);
if ($exists)
{
echo "email exisits!";
return FALSE;
}
$sql = "INSERT INTO users SET ?u";
$allowed = array('username', 'name', 'email');
$insert = $this->db->filterArray($_POST, $allowed);
$insert['password'] = crypt($_POST['password']);
$this->db->query($sql, $insert);
return $this->db->afectedRows();
}
you need to use this code after prepare statement
$stmt->execute();
$stmt->store_result();
put this
if ($result->num_rows > 0) {
echo "email exisits!";
}
instead of
if ($result->num_rows) {
echo "email exisits!";
}
First, you are using prepare (great!) but then you are just passing in the value of email, effectively defeating the benefit of prepared statements.
Second, you never execute the query, which is why you don't get anything in num_rows.
public function insert() {
$result = $this->mysqli->prepare("SELECT COUNT(*) FROM users WHERE email=?");
$result->bind_param("s", $_POST['email']);
$result->execute();
$result->bind_result($email_count);
if ($email_count) {
echo "email exisits!";
} else {
# your other logic
From what I can see you're not assigning a value to num_rows prior to testing it with if ($result->num_rows), so it will always be 0
I am currently trying to make an update page for user profiles on my site and. The code below works fine if the user updates all of their info, but if they leave out a field it inserts a blank record into the table.
Currently to get past this problem if the user has left a field blank I replace the blank field with $_SESSION['user']['field'] so it just re-inserts current data.
Here is my php at the moment
<?php
session_start();
if($_SESSION['uname']) {
$logged_in=true;
} else {
$logged_in=false;
}
include_once("../connection/conn.php");
if(isset($_POST['update'])) {
if($_POST['firstname']){ $firstname = $_POST['firstname']; }
else { $firstname = $_SESSION['uname']['firstname']; }
if($_POST['lastname']){ $lastname = $_POST['lastname']; }
else { $lastname = $_SESSION['uname']['lastname']; }
if($_POST['email']){ $email= $_POST['email']; }
else { $email = $_SESSION['uname']['email']; }
$id = $_SESSION['uname']['id'];
$query = "UPDATE users SET firstname=?, lastname=?, email=? WHERE id=? ";
$results = $condb->prepare($query);
$results->execute(array($firstname, $lastname,$email,$id));
if($results) {
echo "updated";
}
}
?>
UPDATE `tablename`
SET `field` = IF(? <> '', ?, `field`)
WHERE ...
This subs the job of checking for empty entries to MySQL and field uses its previous value instead of an empty value. You need to pass the value into execute() twice for this to work. It's does basically the same thing as you are doing but without having to store the value in your PHP session.
Using this approach, your update code would look like this:
/*
This block is no longer necessary
if($_POST['firstname']){ $firstname = $_POST['firstname']; }
else { $firstname = $_SESSION['uname']['firstname']; }
if($_POST['lastname']){ $lastname = $_POST['lastname']; }
else { $lastname = $_SESSION['uname']['lastname']; }
if($_POST['email']){ $email= $_POST['email']; }
else { $email = $_SESSION['uname']['email']; }
*/
$query = "
UPDATE `users`
SET
`firstname` = IF(? <> '', ?, `firstname`),
`lastname` = IF(? <> '', ?, `lastname`),
`email` = IF(? <> '', ?, `email`)
WHERE `id` = ?
";
$results = $condb->prepare($query);
$results->execute(array(
$_POST['firstname'], $_POST['firstname'],
$_POST['lastname'], $_POST['lastname'],
$_POST['email'], $_POST['email'],
$_SESSION['uname']['id']
));
Your existing code would have stopped the user from entering a single 0 on its own, which this won't - you may want to add a check for that as well.
You have to give field validation
if($firstname!="" && $lastname!="" && $email!=""){
$query = "UPDATE users SET firstname=?, lastname=?, email=? WHERE id=? ";
$results = $condb->prepare($query);
$results->execute(array($firstname, $lastname,$email,$id));
if($results) {
echo "updated";
}
}
else{
echo "Fill all the fields!";
}