This question already has answers here:
How to prevent duplicate usernames when people register?
(4 answers)
Closed 12 months ago.
I want to take email addresses from users to add them to a mailing list. However, I want to prevent duplicate entries, so I am using the INSERT IGNORE approach. I am using the PHP script below, but constantly receive this error:
Fatal error: Uncaught Error: Call to a member function bind_param() on bool
I've reviewed a LOT of SO articles on this error but still can't get it to work. I have confirmed that the $email and $id variables do have values. I suspect the error must have something to do with the use of IGNORE, but I honestly don't know.
Here's my code:
$email = filter_input(INPUT_POST, 'email',FILTER_SANITIZE_EMAIL);
$id = filter_input(INPUT_POST, 'id',FILTER_VALIDATE_INT) ?: NULL;
$sqlQuery = 'INSERT IGRNORE INTO email(email, id) VALUES(:email,:id);';
$stmt = $dbc->prepare($sqlQuery);
$stmt->bind_param(':email',$email);
$stmt->bind_param(':id',$id);
$stmt->execute();
mysqli_close($dbc);
I've tried including only one variable for the insert but I get the error against both bind_param lines. I also got the error when I had this structured to have both variables in a single bind_param entry.
I'm open to other ways of avoiding duplicate emails in the database, so long as they can be done with a single PHP file.
You are mixing PDO and mysqli syntax. You need to pick one.
PDO
Open the connection, execute the statement without IGNORE, and then catch the exception to see why it failed. The code 1062 means that MySQL tried to insert a duplicate value.
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", 'user', 'pass', [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false
]);
try {
$stmt = $pdo->prepare('INSERT INTO email(email, id) VALUES(:email,:id)');
$stmt->execute([
'email' => $email,
'id' => $id
]);
} catch (PDOException $e) {
if ($e->errorInfo[1] === 1062) {
// duplicate
} else {
// If not 1062 then rethrow
throw $e;
}
}
mysqli
Using mysqli it's a little bit more work, but the same logic. With mysqli you can't use named placeholders and you can't bind-in-execute. The bind_param() function is very peculiar so pay special attention to the syntax.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$mysqli->set_charset('utf8mb4'); // always set the charset
try {
$stmt = $mysqli->prepare('INSERT INTO email(email, id) VALUES(?, ?)');
$stmt->bind_param('ss', $email, $id);
$stmt->execute();
} catch (mysqli_sql_exception $e) {
if ($e->getCode() === 1062) {
// duplicate
} else {
// If not 1062 then rethrow
throw $e;
}
}
Related
This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed last year.
I have an insert statement that is executed with PDO. Insert works great however if there is an error I would like it displayed to the user.
I have the below try-catch block.
try{
$insertuser = $db->prepare('INSERT INTO `she_she`.`Persons` (`idnumber`,`addedby`,`firstname`, `middlename`, `surname`, `fullname`, `gender`, `birthdate`, `homelanguage`, `department`, `employeetype`, `employeestatus`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
$insertuser->execute(array($idnumber,$user,$firstname, $middlename, $surname, $fullname, $gender, $birthdate, $language, $department, $employmenttype, $personstatus));
}
catch(PDOException $exception){
return $exception;
}
If the query fails, or let's say a duplicate IDNumber, I want this displayed to the user.
If I simply try to echo the variable $exception it does not work.
I want to return the MySQL error to the user.
By default PDO is not in a state that will display errors. you need to provide the following in your DB connection
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
More info can be seen Here
1.Add ERRMODE_EXCEPTION mode after your db connection:
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
2.And than you must use try{} catch{} method for all your mysql query. Like this:
try {
$SQL = "DELETE FROM items WHERE item_id=:item_id";
$m = $dbh->prepare($SQL);
$m->bindParam(':item_id', $item_id, PDO::PARAM_INT);
$m->execute();
//success
$return = "Your success message.";
}
catch (PDOException $e) {
//error
$return = "Your fail message: " . $e->getMessage();
}
You should use this:
return $exception->getMessage();
See the page on the documentation of Exception class:
http://www.php.net/manual/en/exception.getmessage.php
This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
PHP's white screen of death [duplicate]
Closed 5 years ago.
I am new to using PDO and I am getting an http 500 server error when the form is submitted.
The php page with the processing code is in the correct folder so I don't know why its throwing up a 500 error.
There is NO url rewrite going on neither .
Here is my code:
try {
$dbh = new PDO("mysql:host=$hostname;dbname=crm",$username,$password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // <== add this line
$stmt = $db->prepare("INSERT INTO testdrives (forename, surname,phone,email,add1,add2,add3,city,county,postcode,car,date) VALUES (:forename, :surname,:phone,:email,:add1,:add2,:add3,:city,:county,:postcode,:car,:date)");
$stmt->bindParam(':forename', $_POST['forename']);
$stmt->bindParam(':surname', $_POST['surname']);
$stmt->bindParam(':phone', $_POST['phone']);
$stmt->bindParam(':email', $_POST['email']);
$stmt->bindParam(':add1', $_POST['add1']);
$stmt->bindParam(':add2', $_POST['add2']);
$stmt->bindParam(':add3', $_POST['add3']);
$stmt->bindParam(':city', $_POST['city']);
$stmt->bindParam(':county', $_POST['county']);
$stmt->bindParam(':postcode', $_POST['postcode']);
$stmt->bindParam(':car', $_POST['car']);
$stmt->bindParam(':date', $_POST['date']);
$stmt->execute();
if ($dbh->query($sql)) {
echo "<script type= 'text/javascript'>alert('New Record Inserted Successfully');</script>";
}
else{
echo "<script type= 'text/javascript'>alert('Data not successfully Inserted.');</script>";
}
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
Edit:
I missed the incorrect variable used for the connection being $dbh and $db in the prepare; my bad.
Original answer.
This line:
if ($dbh->query($sql)) {...}
is failing for two reasons:
Calling query() on what is already being prepared/executed.
Using a non-existant variable, $sql.
Get rid of that statement with the related brace and replace it with simply and replacing the $stmt->execute(); with:
if($stmt->execute()){
// success
} else{
// error
}
and using PDO's error handling (as you are doing now) and PHP's error reporting:
http://php.net/manual/en/pdo.error-handling.php
http://php.net/manual/en/function.error-reporting.php
Check your logs also.
Found the problem
The above code shows
$stmt = $db->prepare
Needed to be changed to
$stmt = $dbh->prepare
Thanks for help with the other issue
Quick question how to i insert into a table that has an auto increment column ?
I'm new to PHP and MySQL and I'm trying to insert data in to a database, which had worked fine until i attempted to use PDO's prepare method. It returns the catch error and i cannot figure out why - i'd also like to know whether it's best practice to use unnnamed placeholders or named placeholders?
The username and password variables are defined earlier in my code and catches data from the user using $_POST.
EDIT: getMessage() error displays SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'username' cannot be null
if (!empty($user) && (!empty($password)) ) {
try {
$results = $db->prepare("INSERT INTO user_info (username, pass) VALUES (?,?)");
$results->bindParam(1,$username);
$results->bindParam(2,$password);
$results->execute();
} catch (Exception $e) {
echo "Could not insert data in to the database";
}
}
You have two different variable names. You're checking $user to make sure it's not empty() but then you tell bind $username to the first parameter. You'll just need to rename one of them to match the other.
Try this one.
if (!empty($user) && (!empty($password)) ) {
try {
$results = $db->prepare("INSERT INTO user_info (username, pass) VALUES (?,?)");
$results->bindParam(1,$user);
$results->bindParam(2,$password);
$results->execute();
} catch (Exception $e) {
echo "Could not insert data in to the database";
}
}
Please try yourself first to find the error.
This question already has answers here:
Reference — frequently asked questions about PDO
(3 answers)
Closed 9 years ago.
I'm trying to insert values to mysql database, but for some reason this is not working. I can get it to work with normal PHP but I have been told that PDO would be safer to use. This is the code I use, the values are posted to the php file, but not updated to mysql. What could be the reason for that?
<?php
include 'config.php';
// database connection
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
// new data
$value1 = $_POST["value1"];
$value2 = $_POST["value2"];
$value3 = $_POST["value3"];
$value4 = $_POST["value4"];
// query
$sql = "INSERT INTO `database`.`table`
(`id`, `value1`, `value2`, `value3`, `value4`, `timeStamp`)
VALUES (NULL, ?, ?, ?, ?, CURRENT_TIMESTAMP)";
$q = $conn->prepare($sql);
$q->execute(array($value1, $value2, $value3, $value4));
?>
Change this line
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
to this
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
and use try catch on
try
{
$q->execute(array($value1, $value2, $value3, $value4));
}
catch(Exception $e)
{
echo $e->getMessage();
//other code to handle exception for example logging, rollback transaction if exists etc.
}
When you make these changes then PDO Exceptions will be thrown and you will see what problem is. With PDO exception you can do more to handle error, for example if you use transactions then you can in catch block rollback it.
You can use error_reporting(E_ALL); and display_errors with ini_set().
You can also use PDO::errorInfo
From manual:
PDO::errorInfo — Fetch extended error information associated with the last operation on the database handle
To see examples check this link
Check these links:
how to set display errors
info about exceptions
pdo exception
I have a register.php file which takes the input from a form and tries to create a user account in a database. I have an innoDB MySQL database which has a 'UNIQUE' key added to the 'username' field of the users table. This is to prevent duplicate usernames.
Below is an extract from my php code. In my database I currently have a user called 'testUser'. However, when running the code below with $username = testUser, the php file returns 'Account created', even though a duplicate row is not created in the database. I would have expected there to be an exception thrown if the user already existed?
try{
$stmt = $db->prepare("INSERT INTO users (username, password, salt) VALUES (:username, :password, :salt)");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $hash);
$stmt->bindParam(':salt', $salt);
$stmt->execute();
}catch(PDOException $e){
returnJSON(0,'Error creating account');
}
returnJSON(1,'Account created');
function returnJSON($errorCode, $message){
$arr = array("returnCode" => $errorCode, "returnMessage" => $message);
echo json_encode($arr);
die();
}
----
try{
$db = new PDO('mysql:host='.$host.';dbname='.$dbname, $username, $password);
}
catch(PDOException $e){
$arr = array("returnCode" => 0, "returnMessage" => "unable to connect to server");
echo json_encode($arr);
die();
}
My question is, how should I find out if the user's account was successfully added to the database.
PS. I do have code to query the database first and see if there exists a user with the same name before calling this code. But I'd still like to fix/understand this as well.
PDO by default has silent errors: you need to check then yourself by actually looking for them.
If you want to use exceptions, you need to tell PDO to do it. Check http://php.net/manual/en/pdo.error-handling.php
The specific code you want is
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
in the try/catch immediately after you create the connection.
catch (PDOException $er) {print("error".$er."<br />");}
When you catch an Error, the flow of the program continues, try catching the Error and stopping the flow, using exit();
What I am saying is , even if an exception is caught, the following line of code should stil execute,
returnJSON(1,'Account created');
unless you are stopping the flow somehow. Would really appreciate if you post the entire file, including functions you are using.