Prepared statement not populating DB - php

I'm trying to make my first prepared statement work, but so far I'm unsuccesful. I hope you're able to help me out. I have an index.html with a simple form that parses it's data to insert.php. However, the data is not being written into my DB. Here's what I've got:
insert.php
if (isset($_POST['submit'])) {
$mysqli = new mysqli("hosts","user","pass","db");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$stmt = $mysqli->prepare("INSERT INTO mail_platform (first_name, last_name, email, preference_exchange, preference_news) VALUES (?, ?, ?, ?, ?)");
$stmt->bind_param('sssii', $first_name, $last_name, $email, $preference_exchange, $preference_news);
$first_name = isset($_POST['first_name'])
? $mysqli->real_escape_string($_POST['first_name'])
: '';
$last_name = isset($_POST['last_name'])
? $mysqli->real_escape_string($_POST['last_name'])
: '';
$email = isset($_POST['email'])
? $mysqli->real_escape_string($_POST['email'])
: '';
$preference_exchange = isset($_POST['preference_exchange'])
? $mysqli->real_escape_string($_POST['preference_exchange'])
: '';
$preference_news = isset($_POST['preference_news'])
? $mysqli->real_escape_string($_POST['preference_news'])
: '';
$stmt->execute();
$stmt->close();
}
echo "Thank you for signing up!";
?>
index.html
<form method="post" action="insert.php">
First name: <input type="text" name="first_name"><br>
Last name: <input type="text" name="last_name"><br>
E-mail: <input type="text" name="email"><br>
Please choose what kind of e-mails you would like to receive:<br>
News from my exchange: <input type="checkbox" name="preference_exchange" value="true"> <br>
Generel news: <input type="checkbox" name="preference_news" value="true"><br>
<input type="submit" value="Subscribe">
</form>
And here's my MySQL:
CREATE TABLE `mail_platform` (
`ID` int(20) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(60) CHARACTER SET utf8 NOT NULL,
`last_name` varchar(60) CHARACTER SET utf8 NOT NULL,
`email` varchar(100) CHARACTER SET utf8 NOT NULL,
`registration_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`preference_exchange` tinyint(1) NOT NULL DEFAULT '0',
`preference_news` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
)
Thanks in advance!

First, break yourself of the habit of using mysqli_real_escape_string(). The best part of using query parameters is that it's not necessary to do escaping. In fact, you should not, because you'll end up with literal backslash characters in the strings stored in your database.
Second, you should always check the return status of prepare() and execute(). If any error occur in parsing or execution, these functions return false. Check for this and then if that has happened, you should look at the error returned.
The reason it's important to check for errors is that if the statement fails, you won't know it or the reason why unless you examine the error.
Also if you use PHP 5.3, you can use the ?: shortcut to make this code a little more brief.
$stmt = $mysqli->prepare("INSERT INTO mail_platform
(first_name, last_name, email, preference_exchange, preference_news)
VALUES (?, ?, ?, ?, ?)");
if ($stmt === false) {
trigger_error($mysqli->error, E_USER_ERROR);
}
$stmt->bind_param('sssii', $first_name, $last_name, $email,
$preference_exchange, $preference_news);
$first_name = $_POST['first_name'] ?: '';
$last_name = $_POST['last_name'] ?: '';
$email = $_POST['email'] ?: '';
$preference_exchange = $_POST['preference_exchange'] ?: '';
$preference_news = $_POST['preference_news'] ?: '';
if ($stmt->execute() === false) {
trigger_error($stmt->error, E_USER_ERROR);
}
Notice that an error on prepare() returns its message in $mysqli->error, but an error on execute() returns its message in $stmt->error;
Re your comment:
I just tested it myself with PHP 5.3.15 and MySQL 5.6.12. It worked perfectly. So I'm not sure what to suggest as a reason it fails in your case. Are you saying it doesn't return any error, but the row just never shows up in your table?
If you added another line for $stmt->execute() without adding error handling for that, you're back to the problem of not knowing whether it succeeded. In other words, it sounds like you did the following:
$stmt->execute(); // without checking if this had an error
if ($stmt->execute() === false) { // execute a second time
trigger_error($stmt->error, E_USER_ERROR);
}
You don't need to execute twice. I showed calling execute() as part of the if statement, but this is a pretty common style of coding when you want to check the return value without storing the return value in a variable. It still performs the execute.

Related

PHP + MySQLi Query post null row

dear Stackoverflow users, I start learning PHP and MySQLi. And now I have some issues. On every page reload in DB added 1 full empty row, every cell is null. Can someone give me advice about issue? Code below:
PHP before html tag:
<?php
$mysqli = new mysqli("", "", "", "");
$mysqli->set_charset('utf8');
$name = $mysqli->real_escape_string($_POST['name']);
$email = $mysqli->real_escape_string($_POST['email']);
$link = $mysqli->real_escape_string($_POST['link']);
$query = "INSERT INTO demos (name, email, link) VALUES ('$name', '$email', '$link')";
$mysqli->query($query);
$mysqli->close();
?>
HTML inside body tag:
<form action="" method="post">
<input type="text" name="name" maxlength="20" required />
<input type="text" name="email" required />
<input type="text" name="link" required />
<input type="submit" value="Send" />
</form>
You should first check if your form is submitted by using isset or !empty.
By using isset, you can check wether or not a variable is set:
<?php
if(isset($_POST['name']) && isset($_POST['email']) && isset($_POST['link'])) {
// your code
}
?>
By using !empty, you can check if a variable is set and not empty. Note however that if you are using empty you can not submit a '0' or leave a field blank.
<?php
if(!empty($_POST['name']) && !empty($_POST['email']) && !empty($_POST['link'])) {
// your code
}
?>
Try using prepared statement for easier use and protection for SQL injection:
$stmt = $mysqli->prepare("INSERT INTO demos (name, email, link) VALUES(?, ?, ?)");
$stmt->bind_param("sss", $name, $email,$link);
$stmt->execute();
Read more about prepared statements: https://www.w3schools.com/php/php_mysql_prepared_statements.asp
Use var_dump to debug your code to make sure the values are not null
Add this before and after escaping the strings:
var_dump(array($name, $email, $link));
Also, switch to using prepared statements
$stmt = $mysqli->prepare("INSERT INTO demos (name, email, link) VALUES (?,?,?)");
$stmt->bind_param('sss', $name, $email, $link); // bind vars to the parameter
$stmt->execute(); // Execute statement

php function returns no result

I wrote a simple php function in an attempt to learn php and functions within php.
The goal of the function is to upload a new user to a db
Here is my function
function upload_user($pId, $pName, $pEmail, $pPhone ){
$sql = "INSERT INTO users (member_id, name, email, phone) VALUES ('$pId', '$pName', '$pEmail', '$pPhone')";
mysql_query($sql);
}
Here Is my Form
<form name="register" method="post">
<input type="text" value="name" name="name">
<input type="text" value="email" name="email">
<input type="text" value="phone" name="phone">
<input type="submit" name="submit" value="register" />
</form>
if(isset($_POST['submit'])){
$id = rand(100, 10000);
$name = $_POST['name'];
$email= $_POST['email'];
$phone = $_POST['phone'];
upload_user($id,$name,$email,$phone);
}
I know I am connecting successfully to the db since I did a test to echo out if the connection is successful or not. I also have php errors switched onini_set('error_reporting', E_ALL); but it gives me no warnings or errors
My Problem
Nothing happens with the above function, i.e. the result is just blank. If anyone can point out to me what I am doing wrong it will be really appreciated.
I think most likely that the function doen't know about the database connection so you need to either pass the db connection object as a parameter to the function or use the global identifier inside the function.
function upload_user($dbconn, $pId, $pName, $pEmail, $pPhone ){
$sql = "INSERT INTO `users` (`member_id`, `name`, `email`, `phone`) VALUES ('$pId', '$pName', '$pEmail', '$pPhone')";
mysql_query($sql,$dbconn);
}
function upload_user($pId, $pName, $pEmail, $pPhone ){
global $dbconn;
$sql = "INSERT INTO `users` (`member_id`, `name`, `email`, `phone`) VALUES ('$pId', '$pName', '$pEmail', '$pPhone')";
mysql_query($sql,$dbconn);
}
Neither of these will return a value - what you return from the function is up to you , if indeed you even want to return a value. You could use the response from the query ( true or false ) as the return:
function upload_user($pId, $pName, $pEmail, $pPhone ){
global $dbconn;
$sql = "INSERT INTO `users` (`member_id`, `name`, `email`, `phone`) VALUES ('$pId', '$pName', '$pEmail', '$pPhone')";
return mysql_query($sql,$dbconn);
}
if(isset($_POST['submit'])){
$id = rand(100, 10000);
$name = $_POST['name'];
$email= $_POST['email'];
$phone = $_POST['phone'];
/* using ternary notation to echo something based on return value of function */
echo upload_user($id,$name,$email,$phone) ? 'Success' : 'Sorry, it failed';
}
You should be aware that certain words, in mysql and other rdbms, have special significance - so it is better to always ( imo ) to encase the field names in backticks. Also worth noting is that the mysql_* suite of functions are deprecated and it s advised to use either mysqli or pdo ~ and where you use user supplied content in your code ( form submission data generally or querystrings ) you should use prepared statements to guard against sql injection.
mysql accepts a link_identifier
link_identifier : The MySQL connection. If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If no connection is found or established, an E_WARNING level error is generated. reference
So you should pass a connection parameter as noted in other answers. After every connection made, you should close the connection so that you don't run into too manny connections server errors.

Checking for duplicates in database table before inserting

I need to create a form that gathers a first name, last name, and an email address. I have created a table in MySQL called guestbook. The table looks something like the following:
CREATE TABLE guestbook (
id int unsigned NOT NULL AUTO_INCREMENT,
firstName varchar(50) NOT NULL,
lastName varchar(50) NOT NULL,
email varchar(250) NOT NULL,
status int NOT NULL,
sort int NOT NULL
);
And here is my code thus far:
<?php
Global $Conn;
$Conn = new mysqli("localhost","151_millet","2gZMXYGC","GUESTBOOK");
if(!$Conn) {
$ErrorMsg = "Couldn't connect to the database";
}
$FName = $_POST["fname"];
$LName = $_POST["lname"];
$Email = $_POST["email"];
// The series of ifs below tests to see if each field is blank
// If it is blank it will output an error message for each that is blank
if($FName == "") {
$ErrorMsg .= "First Name Was Left Blank<br>";
}
if($LName == "") {
$ErrorMsg .= "Last Name Field Was Left Blank.<br>";
}
if($Email == "") {
$ErrorMsg .="Email field was left blank.<br>";
}
I have no idea how to check for duplicates in the email field. Any help would be appreciated. I think I need to come up with a way to test $_POST against whats already in the db.
Alrighty, now we've cleaned up this question a bit. Let's get down to business.
You want to check for duplicates in your database. There are a couple of things you need to do for this. Let's try to keep this as simple as possible while we're working on it too.
First off, it's good to see you're using MySQLi and not the deprecated mysql_* functions. But we can handle MySQLi in a more object oriented manner. Also, using globals is frowned upon (and is actually not necessary, even in your current code!)
One other thing to note is that there are slightly different styles of code used in modern PHP, like camel case, and how you format if statements. If you're interested in learning PHP, then you should take a look at the PHP-FIG PSRs.
<?php
$conn = new mysqli("localhost", "151_millet", "2gZMXYGC", "GUESTBOOK");
if ($conn->connect_errno) {
// This is an error that will stop us from continuing, so assigning
// the error message to a string, doesn't really help us in this case
// The application NEEDS to stop
throw new RuntimeException("Unable to connect to MySQL database.");
}
$firstName = $_POST["fname"];
$lastName = $_POST["lname"];
$email = $_POST["email"];
if (!$firstName || !$lastName || !$email) {
echo "Please make sure to fill in all of your details.";
// You may want to handle this differently, this is just to keep things
// Very simple
exit;
}
$query = "SELECT COUNT(1) FROM guestbook WHERE email = ?";
$stmt = $conn->prepare($query);
$count = 0;
if ($stmt) {
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->store_result();
$count = $stmt->num_rows;
$stmt->close();
}
if ($count > 0) {
echo "A user with that email address already exists.";
exit;
}
// Do other stuff
That should help you out with what you need to do to check if an email address already exists. But you should also enforce this in your database by adding a unique key to the email column. That will mean that even if your code fails and would allow a duplicate email address entry, your database won't.

Null Values in DB

I am trying to make a VERY simple PHP form that posts a form to MySQL Database, however I am having some issues, and would welcome a simple fix for this if possible:
My PHP:
<?php
$con=mysqli_connect("serveraddress","db","password","dbname");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$sql="INSERT INTO Persons (email, type, cats)
VALUES
('$_POST[email]','$_POST[type]','$_POST[cats]')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
echo "1 record added";
mysqli_close($con);
?>
My HTML:
<form action="personuploader.php" method="post">
<table class="#">
<tr>
<th colspan="2">Test</th>
</tr>
<tr>
<td>Email Address:</td>
<td><input type="text" name="email"> </td>
</tr>
<tr>
<td>Type:</td>
<td><input type="text" name="type"> </td>
</tr>
<tr>
<td>Cats:</td>
<td><input type="text" name="cats"> </td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="upload" name="upload">
</tr>
</table>
</form>
My SQL Configuration:
Even though I have not null set in the DB I am getting empty results, is it possible to stop the form resubmitting on refresh causing null results be entered into the DB. I will enter some form validation to stop null results passing into the post script in the future but refreshing the page still sends over null results.
Edit:
Your column names have mixed-case letters (Cats and cats are not the same)
I edited my answer, where I changed it from:
$sql="INSERT INTO `Persons` (`email`, `type`, `cats`)
to
$sql="INSERT INTO `Persons` (`Email`, `Type`, `Cats`)
I also made a mistake with a missing ) for if(empty($_POST['email'] which has been fixed.
Please make sure also, that your column names are indeed called Email Type Cats and not email type cats Change it to the letter-case that is in your DB.
Your table's original structure: (larger image)
You should have talked to me first, instead of posting a new question with my code
See the rest below in the code.
As I stated in my comments under your original question, have put this together for you.
Don't use this method VALUES ('$_POST[email]','$_POST[type]','$_POST[cats]') you're open to SQL injection
To avoid re-submissions causing an empty entry, you can use a header() to redirect to another page, or use AJAX
However, I am sure there are other ways of doing this in the query itself, I just don't remember how right now.
I.e.: In place of where you have echo "1 record added";
you can do header("Location: added.php"); exit();
You can also use a conditional statement:
if(empty($_POST['variable'])){ die("Fill this in.");}
Try the following. It will check for empty fields, as well as check if the upload submit-type button is set.
Plus, I modified the way your query was done, replacing POST variables with mysqli_real_escape_string()
<?php
$con=mysqli_connect("serveraddress","db","password","dbname");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if(isset($_POST['upload'])){
// You can replace the || with && if required
// depending on what you want to check for.
if(empty($_POST['email']) || empty($_POST['type']) || empty($_POST['cats']))
{
die("You need to fill in all the fields.");
}
$email = mysqli_real_escape_string($con, $_POST['email']);
$type = mysqli_real_escape_string($con, $_POST['type']);
$cats = mysqli_real_escape_string($con, $_POST['cats']);
$sql="INSERT INTO `Persons` (`Email`, `Type`, `Cats`)
VALUES ('$email','$type','$cats')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
// Uncomment out if you're going to use echo, but not with header.
// echo "1 record added";
header("Location: redirect_to_other_page.php");
exit();
} // end of if(isset($_POST['upload']
// else conditional statement for if(isset($_POST['upload']
else{ echo "You cannot do this operation from here."; }
mysqli_close($con);
?>
Footnotes:
Just saying, the following:
('$_POST[email]','$_POST[type]','$_POST[cats]')
should have been:
('$_POST['email']','$_POST['type']','$_POST['cats']')
However, using this method is highly discouraged, as I already mentioned.
You need to check if a submit actually occured:
if ($_SERVER["REQUEST_METHOD"] == 'POST') {
... submit occured, do DB stuff
}
And note that an empty string is NOT the same as an SQL null. Empty string is just that - a string which happens to be empty/zero-length. An SQL null is quite literally "unknown". Your code cannot insert an actual null - it can only ever insert empty strings.
You should check whether the Upload button has been clicked on the "personuploader.php" file.
// Initializing Variables
$email = '';
$type = '';
$error = false;
if ( isset ( $_POST['upload'] ) ) {
// Then capture the POST Variables
$email = $_POST['email'];
// Do Some Validations
if ($email == '') {
$error = true;
}
// Process the Form if NO Errors
if ($error == false) {
// Insert The Data into DB
}
}

Problem with $_POST

This wont work. All the fields are correct etc and I have a db connection.
To the problem
I use this script to insert a post into the db:
<?php
if (isset($_POST['msg'])) {
$title = mysql_real_escape_string($_POST['title']);
$msg = mysql_real_escape_string($_POST['msg']);
// kolla efter tomma fält
if (empty($title) || empty($msg)) {
$reg_error[] = 1;
}
if (!isset($reg_error)) {
mysql_query("INSERT INTO messages (title, message, date, user_id)
VALUES('$title', '$msg', '".time()."', '2')");
header('location: /');
exit;
}
}
?>
The Form:
<form action="post_msg.php" method="post">
<b>Title:</b>
<input type="text" name="title" size="40" />
<b>Message:</b>
<textarea rows="15" cols="75" name="msg"></textarea>
<input type="submit" value="Post Message" />
</form>
Worked fine the other day. Not today. No errors. The "post stuff" shows up in the url. I thought it only did when using $_GET which i dont.
http://localhost/post_msg.php?title=fdsg&msg=sdfg
i dont get any errors the page just reloads
messages db
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(140) COLLATE utf8_unicode_ci DEFAULT NULL,
`message` text COLLATE utf8_unicode_ci
`date` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `title` (`title`,`message`)
Sounds like your form isn't set to use POST
<form action="post_msg.php" method="post">
A few comments that might help:
Please provide log output, error messages
Print the SQL and run it manually on the server, what errors occur?
Your SQL construction using string concatenation is really grim and probably a security hazard.
Look at the documentation for PDO. The API in PHP, although inconsistently named is fairly stable. So it is most likely that you did something wrong, in which case an error should ensue.
If everything works fine you get a result. But if anything "fails" you get nothing, no message what so ever. It leaves you in the dark, clueless. And that's bad.
Turn on the error reporting. Don't just have an if-block, add an else-block, too.
<?php
error_reporting(E_ALL); ini_set('display_errors', true);
if (isset($_POST['msg'])) {
$title = mysql_real_escape_string($_POST['title'])
or die('escape_string title failed');
$msg = mysql_real_escape_string($_POST['msg'])
or die('escape_string msg failed');
// kolla efter tomma fält
if (empty($title) || empty($msg)) {
$reg_error[] = 1;
}
if (!isset($reg_error)) {
mysql_query("INSERT INTO messages (title, message, date, user_id)
VALUES('$title', '$msg', '".time()."', '2')")
or die(mysql_error());
header('location: /');
exit;
}
else {
print_r($reg_error);
}
}
else {
echo 'post parameter "msg" missing';
}
?>
echo what the query result
echo mysql_errno($link) . ": " . mysql_error($link) . "\n";
did the script enter to the line that doing the query ?
Remove the redirect header and type this at the end of the script for debugging:
var_dump($_POST);
echo mysql_error();
I just noticed something weird...
$reg_error is an array the way you wrote it.
$reg_error[] = 1;
So.. assign a key to that array, like $reg_error[0] or whatever.. and then
if(count($reg_error) > 0) { /* your code */ }
..or just remove the [] brackets from $reg_error and leave the if/else as is.
With the code provided, reg_error is only used to determine whether or not perform the SQL. Instead of setting a variable (since its only set dependent upon a conditional statement), why not just change your code to do:
<?php
if (isset($_POST['msg'])) {
$title = mysql_real_escape_string($_POST['title']);
$msg = mysql_real_escape_string($_POST['msg']);
// kolla efter tomma fält
if (!empty($title) && !empty($msg)) {
mysql_query("INSERT INTO messages (title, message, date, user_id)
VALUES('$title', '$msg', '".time()."', '2')");
header('location: /');
exit;
}
else {
echo "There was an error";
}
}
?>
This would simply the code. The else statement would obviously, eventually be modified, but for now would give you a fall back way of showing you if it even attempted the SQL query. If its not, the condition is failing and you arent getting values from the post for some reason.
The only way your URL would change is if the method of the form tag was changed. If it's set to post, it shouldnt show in the URL.
I found the problem! i checked my header.php file and guess what? there was a form i hadent closed :/ sorry for bothering you guys

Categories