PDO reports failed execution but error code suggests otherwise - php

I'm just using PDO to insert customers into my table but it has been overcomplicated by something which is unexplainable by myself or other research.
It gives the error code: 00000 (which means that is a success, apparently) but no data was actually inserted into the database and the error is only supposed to be outputted if the query was a failure, but the error is.. success?
$insertUser = $database->prepare("INSERT INTO customer (Surname, Forename, AddressRow1, AddressRow2, AddressRow3, AddressRow4, PostCode, Telephone, mobileNumber, Email, assignedGarage)
VALUES (:surname, :forename, :addressrow1, :addressrow2, :addressrow3, :addressrow4, :postcode, :telephone, :mobilenumber, :email, :assignedgarage)");
$insertUser->bindParam(':surname', $_POST['surname']);
$insertUser->bindParam(':forename', $_POST['forename']);
$insertUser->bindParam(':addressrow1', $_POST['addressrow1']);
$insertUser->bindParam(':addressrow2', $_POST['addressrow2']);
$insertUser->bindParam(':addressrow3', $_POST['addressrow3']);
$insertUser->bindParam(':addressrow4', $_POST['addressrow4']);
$insertUser->bindParam(':postcode', $_POST['postcode']);
$insertUser->bindParam(':telephone', $_POST['telephone']);
$insertUser->bindParam(':mobilenumber', $_POST['mobilenumber']);
$insertUser->bindParam(':email', $_POST['email']);
$insertUser->bindParam(':assignedgarage', $_SESSION['garageId']);
if(!$insertUser->execute()) {
$err[] = $database->errorCode();
}
elseif ($insertUser->rowCount() == 1) {
$id = $database->lastInsertId();
echo "<script type=\"text/javascript\">
<!--
window.location = \"updateUser.php?id=$id\"
//-->
</script>";
}
if(count($err)) {
echo "<p style=\"color:red;\">The following errors were detected:</p><br/>";
foreach ($err as $key => $error) {
echo "<p style=\"color:red;\">$error</p><br/>";
}
}
I first started without defining all the columns I wanted to insert into but that didn't work so I predefined them.
My table in its early, rudimentary stages. I have my reasons for choosing varchars for mobile/telephone numbers.

Summarising, you have this:
$insertUser = $database->prepare(...);
if(!$insertUser->execute()) {
$err[] = $database->errorCode();
^^^^^^^^^
}
So you're calling PDO::errorCode() rather than PDOStatement::errorCode(). As the manual explains:
PDO::errorCode() only retrieves error codes for operations performed
directly on the database handle. If you create a PDOStatement object
through PDO::prepare() or PDO::query() and invoke an error on the
statement handle, PDO::errorCode() will not reflect that error. You
must call PDOStatement::errorCode() to return the error code for an
operation performed on a particular statement handle.
Depending on your needs and current code, you might also be interested in PDOStatement::errorInfo(), which provides error details in friendly format. And, of course, you can also instruct PDO to throw exceptions and get rid of manual error checking.

Try this instead and tell me what you find:
try{
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
$insertUser = $database->perepare("INSERT INTO customer (Surname, Forename, AddressRow1, AddressRow2, AddressRow3, AddressRow4, PostCode, Telephone, mobileNumber, Email, assignedGarage) VALUES (:surname, :forename, :addressrow1, :addressrow2, :addressrow3, :addressrow4, :postcode, :telephone, :mobilenumber, :email, :assignedgarage)");
$insertUser->execute(array(':surname'=>$_POST['surname'], ':forename'=>$_POST['forename'], ':addressrow1'=>$_POST['addressrow1'], ':addressrow2'=>$_POST['addressrow2'], ':addressrow3'=>$_POST['addressrow3'], ':addressrow4'=>$_POST['addressrow4'], ':postcode'=>$_POST['postcode'], ':telephone'=>$_POST['telephone'], ':mobilenumber'=>$_POST['mobilenumber'], ':email'=>$_POST['email'], ':assignedgarage'=>$_SESSION['garageId']));
if ($insertUser->rowCount() == 1) {
$id = $database->lastInsertId();
echo "<script type=\"text/javascript\">
<!--
window.location = \"updateUser.php?id=$id\"
//-->
</script>";} else{
//sum'n sum'n
}catch(PDOException $e){
echo 'Error occured'.$e-getMessage();
}

This is because the $database->errorCode(); will not work for operations not directly performed on DB handle as in your case (you used PDO->prepare()). In your case this error code is reffering to last successful query not the one you are trying to execute, hence the 0000 error code.
You most likely have an error in your params array (values that are passed from $_POST). Also when using bindParams method you should specify the type of variable that is expected by database.

Related

INTRO-LVL PROGRAMMER: Verify & Execute Guidance in PHP/MySQL

I'm a non-CIS major taking an intro programming classes for a minor through my university. I've been able to successfully code most of the PHP files I need but have been getting hung up over how to perform two functions within the same document. Hopefully you can help.
Within the website, I want to be able to first use MySQL to check a table, called User (where a user is initially registered by the site) to verify that they are in fact registered and that the credentials they provided are correct, and then execute an query to add them to another table.
I've tried mysqli_multi_query to no avail and am just generally inexperienced and unsure of my options as far as functions go.
I have included the code below but be aware that it is a mess as I've attempted several different things before I decided to get some help
<?php
session_start();
require_once("config.php");
$GroupDesc = $_GET["GroupDesc"];
$LeaderID = $_GET["LeaderID"];
$URL = $_GET["URL"];
$Email=$_GET["Email"];
$con = mysqli_connect("$SERVER","$USERID","$DBPASSWORD","$DATABASE");
$query2= "INSERT INTO FA15_1052_tuf02984.WebsiteGroups (ID, Description, LeaderID, URL, LeaderEmail) VALUES ('$GroupDesc', '$LeaderID', '$URL', '$Email');";
/* Here I want to perform the first query or $query1 which checks if the
user exists in MySQL and the info submitted in form is same */
$query1= "SELECT * from USER where LeaderID = '$ID' and Email = '$Email';";
if ($status = mysqli_query($con, $query1)) {
} else {
print "Some of the data you provided didn't match our records. Please contact the webmaster.".mysqli_error($con)." <br>";
$_SESSION["RegState"]= -11;
$_SESSION["ErrorMsg"]= "Database insertion failed due to inconsistent data: ".mysqli_error($con);
header("Location:../index.php");
die();
}
/* How do I tell the file to move onto the next query, which is $query2?
if ($query2) {
$query = "INSERT INTO FA15_1052_tuf02984.WebsiteGroups (ID, Description, LeaderID, URL, LeaderEmail)
VALUES ('$GroupDesc', '$LeaderUID', '$URL', '$Email');";
} */
} else {
print "Membership update failed. Please contact webmaster.".mysqli_error($con)." <br>";
$_SESSION["RegState"]= -11; // 0: Not Registered, 1: Register, -1: Error
$_SESSION["ErrorMsg"]= "Database Insert failed: ".mysqli_error($con);
header("Location:../index.php");
die();
}
There are a few points where your code can be rearranged to make the logic easier to follow. (Don't worry; this is just stuff that comes with experience.) I'll include some comments within the following code to explain what I've done.
<?php
session_start();
require_once("config.php");
$GroupDesc = $_GET["GroupDesc"];
$LeaderID = $_GET["LeaderID"];
$URL = $_GET["URL"];
$Email=$_GET["Email"];
// mysqli_connect is deprecated; the preferred syntax is
$con = new mysqli("$SERVER","$USERID","$DBPASSWORD","$DATABASE");
$query1= "SELECT * from USER where LeaderID = '$ID' and Email = '$Email';";
$result = mysqli_query($con, $query1);
// I personally prefer the following opening-brace style; I just find it
// easier to read. You can use the other style if you want; just do it
// consistently.
if ($result)
{
$row = mysqli_fetch_assoc($result);
if($row)
{
if (($row['ID'] != $LeaderID) or ($row['Email'] != $Email))
{
// Handle the error first, and exit immediately
print "Some of the data you provided didn't match our records. Please contact the webmaster.".mysqli_error($con)." <br>";
$_SESSION["RegState"]= -11;
$_SESSION["ErrorMsg"]= "Database Insert failed due to inconsistent data: ".mysqli_error($con);
header("Location:../index.php");
die();
}
else
{
// If the query succeeded, fall through to the code that processes it
$query = "INSERT INTO FA15_1052_tuf02984.WebsiteGroups (ID, Description, LeaderID, URL, LeaderEmail)
VALUES ('$GroupDesc', '$LeaderUID', '$URL', '$Email');";
$status = mysqli_query($con, $query);
if ($status)
{
// membership has been updated
$_SESSION["RegState"]=9.5; // 0: Not Registered, 1: Register, -1: Error
$message="This is confirmation that you the group you lead has been added to our database.
Your group's ID in our database is "$GID". Please keep this in your records as you will need it to make changes.
If this was done in error, please contact the webmaster at tuf02984webmaster#website.com";
$headers = 'From: tuf02984webmaster#example.com'."\r\n".
'Reply-To: tuf02984webmaster#example.com'. "\r\n".
'X-Mailer: PHP/' . phpversion();
mail($Email, "You are a group leader!", $message, $headers);
header("Location:../index.php");
// die();
// You only use die() to return from an error state.
// Calling die() creates an entry in the server's error log file.
// For a successful completion, use
return;
}
}
}
}
// If we get here, then something has gone wrong which we haven't already handled
print "Membership update failed. Please contact webmaster.".mysqli_error($con)." <br>";
$_SESSION["RegState"]= -11; // 0: Not Registered, 1: Register, -1: Error
$_SESSION["ErrorMsg"]= "Database Insert failed: ".mysqli_error($con);
header("Location:../index.php");
die();
?>
The basic idiom is: Do something, handle the specific error, handle success, do something else, etc., and finally handle any errors that can come from multiple points. If anything is unclear, just ask and I'll edit into my answer.
I haven't covered prepared statements here. Prepared statements are the preferred way to perform non-trivial queries; they help to resist SQL injection attacks as well as simplify type-matching, quoting and escaping of special characters.

Reject PDO MySQL statement if a specified value is found in a field?

I've searched Google but not had much luck with this, so maybe SO can help. I am developing a user authentication system for a couple of projects and need to ensure that the email address, which is also the username, is unique.
I set the field as unique in the MySQL query, but I need a way to cancel an SQL query and notify the user that "the specified email is already in use" if the supplied email matches an existing record.
I could do a select query before the insert, but I am wondering if there is a way to write the SQL query so that an insert is performed IF NOT EXISTS existing#example.com IN email or something like that.
Then if the insert is not performed, I need to know, and I need to be able to tell it apart from another error.
Is this possible? How?
If you're using PDO, you can just catch the exception and check the status code, eg
// make sure you're set to throw exceptions
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('INSERT INTO `user` (`email`) VALUES (?)');
try {
$stmt->execute([$email]);
} catch (PDOException $e) {
$errorInfo = $stmt->errorInfo(); // apparently PDOException#getCode() is pretty useless
if ($errorInfo[1] == 1586) {
// inform user, throw a different exception, etc
} else {
throw $e; // a different error, let this exception carry on
}
}
See http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html#error_er_dup_entry_with_key_name
The process would be similar if using MySQLi
$stmt = $mysqli->prepare('INSERT INTO `user` (`email`) VALUES (?)');
$stmt->bind_param('s', $email);
if (!$stmt->execute()) {
if ($stmt->errno == 1586) {
// inform user, throw a different exception, etc
} else {
throw new Exception($stmt->error, $stmt->errno);
}
}

What does this undefined index message mean

this code calls the values entered into a form and enters them into a database (or at least it's supposed to) every time the page loads it gives "undefined index" messages, and I am struggling to determine why.
Any help that can be offered to me is greatly appreciated!
<?php
$dbc=mysql_connect('localhost', 'user', '');
mysql_select_db('database', $dbc);
$sqlInsertString = "INSERT INTO band_information (Name, Photo, Bio, City, State, Zipcode, Genre, Link)
VALUES ({$_POST['bandname']}, {$_FILES['bandphoto']['name']}, {$_POST['bandbio']}, {$_POST['bandcity']},
{$_POST['bandstate']}, {$_POST['bandzipcode']}, {$_POST['bandgenre']},{$_POST['bandlink']});";
if($_SERVER['REQUEST_METHOD']=='POST'){
if(move_uploaded_file($_FILES['bandphoto']['tmp_name'], "C:\\HTML\\mgertenbach\\BAND\\photos\\{$_FILES['bandphoto']['name']}") && $mysql_query($sqlinsertString, $dbc)){
print '<p>Thanks for submitting your band!</p>';
} else {
print '<p>Could not submit band because: <br/>' .
mysql_error($dbc) . '</p>';
}
}
Since you are getting values from your <form> , you need to first check whether they are set or not.
You should make use of the isset construct for that. Like this
if(!isset($_POST['bandname'])) // And whichever variables you get from your <form>
{
echo "Band Name was not Provided";
exit;
}
else
{
//.... do your CRUD operations here
}
Secondly, you are using mysql_* functions which will be deprecated soon. Switch to MySQli or PDO instead.

mysqli - warning and error

i have this code but i got two errors. I put in the comments the errors
if(!empty($_POST['email']) && validateEmail($email)) {
$email = $_POST["email"];
if ($sql = $db->prepare("select email from users where email=?")) {
$sql->bind_param('s', $email);
$sql->execute();
$sql->bind_result($email);
while ($sql->fetch()) {
$salt = "PiuwrO1#O0rl#+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";
$password = md5($salt . $userExists["email"]);
$pwrurl = "www.yoursite.com/reset_password.php?q=" . $password;
$mailbody = "Dear user,<br><br>If this e-mail does not apply to you please ignore it. It appears that you have requested a password reset at our website www.yoursitehere.com<br>
To reset your password, please click the link below. If you cannot click it, please paste it into your web browser's address bar.<br> <a href='$pwrurl'>$pwrurl</a> <br> <br>
Thanks,\nThe Administration";
$mail->MsgHTML($mailbody);
$mail->AddAddress("dxxb#hotmail.com","Nome da Pessoa");
$mail->IsHTML(true);
if(!$mail->Send()) {
echo "Deu erro: " . $mail->ErrorInfo;
} else {
echo "Enviado com sucesso";
}
}
$sql->close();
$db->close();
}
($sql = $db->prepare('insert into password_reset (code) values (?)')); // Warning: mysqli::prepare() [mysqli.prepare]: Couldn't fetch mysqli in
$sql->bind_param('s', $password); // Fatal error: Call to a member function bind_param() on a non-object
$sql->execute();
$sql->fetch();
$sql->close();
$db->close();
}
all code works fine, but now i need to insert the salt in the db but i can't, and i don't know why
thanks
Edited code to the last version
After you execute a query, fetch returns one result. There may be more -- there may be many, many more -- so you should be calling fetch in a loop to get them all. You aren't supposed to prepare a new query until you've finished dealing with the old one, which would usually mean fetching every row of the result and closeing (in your case) $sql. Otherwise, the database is still in the middle of answering one request when you're trying to issue another one.
The first error says it all - you can't have more than 1 prepared statement/query "in flight" at once. You've not finished fetching data from the first query (select email ...) when you tried to prepare another statement (insert into ...).

How to handle error for duplicate entries?

I have a PHP form that enters data into my MySQL database. My primary key is one of the user-entered values. When the user enters a value that already exists in the table, the MySQL error "Duplicate entry 'entered value' for key 1" is returned.
Instead of that error, I would like to alert the user that they need to enter a different value. Just an echoed message or something.
How to turn a specific MySQL error into a PHP message?
To check for this specific error, you need to find the error code. It is 1062 for duplicate key. Then use the result from errno() to compare with:
mysqli_query('INSERT INTO ...');
if (mysqli_errno() == 1062) {
print 'no way!';
}
A note on programming style
You should always seek to avoid the use of magic numbers (I know, I was the one to introduce it in this answer). Instead, you could assign the known error code (1062) to a constant (e.g. MYSQLI_CODE_DUPLICATE_KEY). This will make your code easier to maintain as the condition in the if statement is still readable in a few months when the meaning of 1062 has faded from memory :)
You can check the return value from mysql_query when you do the insert.
$result = mysql_query("INSERT INTO mytable VALUES ('dupe')");
if (!$result) {
echo "Enter a different value";
} else {
echo "Save successful.";
}
try this code to handle duplicate entries and show echo message:
$query = "INSERT INTO ".$table_name." ".$insertdata;
if(mysqli_query($conn,$query)){
echo "data inserted into DB<br>";
}else{
if(mysqli_errno($conn) == 1062)
echo "duplicate entry no need to insert into DB<br>";
else
echo "db insertion error:".$query."<br>";
}//else end
With mysql_error() function
http://php.net/manual/en/function.mysql-error.php
Use mysql_errno() function, it returns the error numbers. The error number for duplicate keys is 1062.
for example
$query = mysql_query("INSERT INTO table_name SET ...);
if (mysql_errno() == 1062){
echo 'Duplicate key';
}
This is my full code that I used and works perfect. Its PDO friendly, and can handle your error easily, (once you have used die to discover what that is. Then you can copy the error message from there, and enclose it in an if. This came from a signup page, where I wanted to redirect to the login page, if the primary key (email) was found, and produced an error.
function insertUserDetails($email, $conn){
try {
$query = $conn->prepare ("INSERT INTO users (emailaddress) VALUES (:email)");
$query ->bindValue('email', $email);
$query->execute();
}
catch (PDOException $e) {
if(str_contains($e, '1062 Duplicate entry')) {
header("Location: login.php");
}
die("Error inserting user details into database: " . $e->getMessage());
}
}

Categories