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.
Related
What is the proper way to "encapsulate" the sql queries scripts and connection script with try/catch or if/else blocks? I want to have a config.php file that will contain the connection part:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=myDB", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
?>
Now taken from w3schools, when they insert a value to the database, they simply re-write the entire connection part again:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com')";
// use exec() because no results are returned
$conn->exec($sql);
echo "New record created successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
but I want to properly separate the two. Also, if I use prepared statements, do I need to check if on each part? i.e the prepare, bindParam and execute? Or a single try/catch or if/else is enough:
// Prepare an insert statement
$sql = "INSERT INTO table(value) VALUES (:value)";
$stmt = $conn->prepare($sql);
// Bind variables to the prepared statement as parameters
$stmt->bindParam(':value', $value, PDO::PARAM_STR);
$stmt->execute(); //does each part here need an if/else?
You should only make the connection once. There's no need to close and reopen the connection between queries. I assume the reason the example at w3schools is written that way is so that it will be self-contained, executable as-is without relying on a connection established in another example.
If you have the code that defines your connection in one file like the first example you showed, you can include that file in other files that need a connection to execute queries, and $conn will be available there. For a simple project, that's all you really need.
As far as if/else or try/catch, since you have set the PDO::ATTR_ERRMODE attribute on your connection to PDO::ERRMODE_EXCEPTION, then wrapping bits of code where a query may fail in if/else probably won't be that useful, because an exception will be thrown if the query fails, so handling the exception in a catch block will work better. You can examine the exception to see exactly what went wrong, log the error, and show an appropriate error message to the user where applicable. Dumping every exception message to the screen as shown in the second example is generally not a good way to show appropriate error messages to users.
You should include the prepare, bind, and execute in the try block. execute() is not the only thing that can cause an exception. prepare() may throw an exception if you aren't using emulated prepared statements (depending on the setting of PDO::ATTR_EMULATE_PREPARES), and bind can also cause an exception, for example if you mess up a named placeholder.
if/else is more useful for checking the results of queries that executed successfully (e.g. did this select statement return any records). The level of detail of error handling you need determines how many if/else, try/catch blocks you need.
I don't know the best way to ask you this question, but I am using Android Studio, phpMyAdmin, MySQL and the PostMan plugin to debug my php files.
I am trying to create an app that will take user registration and login, and am having problems trying to register a user. The following error I'm getting in Android Studio:
org.json.JSONException: Value Error of type java.lang.String cannot be converted to JSONObject
This Value "Error" regards to my PHP file, which is returning a String because it is complaining about my sql query (or that is how I understood it?):
<?php
$servername = "my server";
$username = "my user";
$password = "my password";
$dbname = "my db";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare sql and bind parameters
$stmt = $conn->prepare("INSERT INTO User (username, email, passcode)
VALUES (:username, :email, :passcode)");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':passcode', $passcode);
$stmt->execute();
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>
Now, the error I'm getting from PostMan is this:
Error: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null
I don't know how to properly handle this...
This isn't an error with PHP, it is with your database. In your table structure you are not allowing the email field to have a null value but you are sending a null value in your php $email value.
the Variable $email is not initialized so it's null.
Your table constraint does not allow null-values in the email column
I'm trying to get a simple PDO insert to work. I have successfully created a tabled named mydb10 using PDO, and the next part I want to do is insert data into that table. Running the script does not return any errors (PDO error mode exception is enabled), but the table still contains null values.
I'm using a local server to run the PHP file, and am connecting to an Amazon RDS database. Currently all inbound traffic through SSH, HTTP, HTTPS, and MYSQL is allowed through the database's security group
$link = new PDO("mysql:host=$dbhost;dbname=$dbname",$username,$password);
$statement = $link->prepare("INSERT INTO mydb10 (selectedMain, selectedSide)
VALUES(:selectedMain, :selectedSide)");
$statement->execute(array(
"selectedMain" => "test",
"selectedSide" => "test2"
));
This might be silly, but I've been stuck for a while now and any help is appreciated. If you'd like any more information, let me know. I'm trying to utilize PHP in my app, but can't even get this simple test to work, so it's a bit discouraging.
EDIT # 1
This snippet is part of a larger file. I am able to successfully
connect to the database with my credentials and create new tables on the server. I do have PDO error reporting enabled in exception mode, and it has helped me work past syntax errors, but I am no longer getting any errors when I run the code. There are also no errors on the MYSQL server log.
I can provide any additional information that may be useful in debugging if desired.
First you need to properly set connection to MySQL database. You can write this code to sql.php:
<?php
$ServerName = "******";
$Username = "******";
$Password = "******";
$DataBase = "******";
try {
$CONN = new PDO("mysql:host=$ServerName; dbname=$DataBase", $Username, $Password);
$CONN->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$CONN->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
Now, when you properly set connection, you need to execute sql, but before this you need to include sql.php:
try {
$SQL = 'INSERT INTO MyDB10 (SelectedMain, SelectedSide) VALUES(:SelectedMain, :SelectedSide)'; // Write SQL Query to variable
$SQL = $CONN->prepare($SQL); // Prepare SQL Query
$SQL->execute(array('SelectedMain' => 'Test', 'SelectedSide' => 'Test2')); // Execute data to Insert in MySQL Databse
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
When you finish all queries you must close connection with:
$CONN = null;
I have writen this pice of code that should insert into my Database some event data, but it does not insert a thing in the DB, can you tell me why?
try {
$pdo = new PDO("mysql:host={$dbhost};dbname={$dbname}", $dbuser, $dbpass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch( PDOException $excepiton ) {
echo "Connection error :" . $excepiton->getMessage();
}
try{
$sql = "INSERT INTO events_DB (event_id, event_end_time, event_location, event_name) VALUES (:event_id, :event_end_time, :event_location, :event_name) ON DUPLICATE KEY UPDATE event_id = :event_id, event_end_time = :event_end_time, event_location = :event_location, event_name = :event_name";
$stm = $db->prepare($sql);
$stm->execute(array(":event_id" => $event[id], ":event_end_time" => $event[end_time], ":event_location" => $event[location], ":event_name" => $event[name]));
}
catch ( PDOException $exception )
{
// decomentati sa vedeti erorile
echo "PDO error :" . $exception->getMessage();
}
Thanks
The code you've posted is different than the code you're running as the posted code would result in a syntax error at parse time and never actually run.
However, what's happening is the SQL being sent to the prepare method is not valid in some way so that the result returned and stored in $stm is a boolean (false) rather than a valid statement object. Double check your SQL (you could try running it in another application such as phpMyAdmin or via the mysql command-line program) to ensure its validity. You could also add some error handling to find the cause with:
$stm = $db->prepare($sql);
if (!$stm) {
die($db->errorInfo());
}
Edit: You've modified the posted source code which now shows use of exception handling. However, you've commented out the line that echos the exception message. This information will be useful in telling you what's causing the error condition. Uncomment to see the message (which will most likely inform you that the SQL is invalid and which part of it caused the error).
Try to remove the <br> tag from the first line and a " is messing
$sql = "INSERT INTO events_DB (event_id, event_end_time, event_location, event_name);"
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.