Uncaught exception 'PDOException'

not very good at this php/pdo/mysql stuff. what i am trying to do is determine where i have a breakdown in my process.
i guess my question is, “how do i check to see if my form is passing data to the script?” i found a really simple template. i like it because there aren’t any validation issues because it is a drop down menu style shopping cart. but i have had to substitute the template values for mine. so my challenge is to be sure i get the backside of the cart correct. i’m thinking i can determine that with code.
i getting this error message:
“Connected to database
Notice: Undefined variable: query in /home/ewff/public_html/myconnection/prac0.php on line 61
Fatal error: Uncaught exception ‘PDOException’ with message ‘SQLSTATE[42000]: Syntax error or access violation: 1065 Query was empty’ in /home/ewff/public_html/myconnection/prac0.php:61 Stack trace: #0 /home/ewff/public_html/myconnection/prac0.php(61): PDO->prepare(‘’) #1 {main} thrown in /home/ewff/public_html/myconnection/prac0.php on line 61”

where can i add code to check if the submit button is passing the user data?
this is my code:

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") 

{ 
    $errors = []; 

    if (empty($_POST['description'])) {
        $errors[] = 'Description is required';
    }

// prepare sql and bind parameters
    $query = "INSERT INTO details (description, temple, quantity, price)
            VALUES (:description, :temple, :quantity, :price)";
}
    $stmt = $dbh->prepare($query);
        $stmt->bindParam(':description', $_POST['description']);
        $stmt->bindParam(':temple', $_POST['temple']);
        $stmt->bindParam(':quantity', $_POST['quantity']);
        $stmt->bindParam(':price', $_POST['price']);
        $stmt->execute();

$dbh = null;
?>

just looking for a little advice on how to proceed forward. i’m not that bright so please keep it 2nd grade. thanks yall.

Don’t bind tainted values. You should validate or sanitise the values in the tainted $_POST array and move them to new fields once you have confirmed that the value is valid/untainted.

Only untainted fields containing valid values should ever reach any of the actual processing code.

Hi carljr, welcome to the forum

The “undefined” is because it is first defined within the if(){, so when the if condition isn’t met it remains undefined.

In some cases you can define a variable before the if(){ and assign something else to it inside eg.
$query = “”;
if () {
$query =

But here I think it would be better to move the if(){ closing brace to after the PDO code. Especially since you don’t need to run it on initial file load anyway

The “uncaught” is because the code doesn’t have the PDO code inside any try{} catch() {} eg.

try {
// PDO code here
} catch (PDOException $exception) {
echo $exception->getMessage( ) . "<br />";
}

During development, echo works fine, but in production better to log instead.

Echoing exception and error messages is a security vulnerability. Log those and/or replace them with a more generic message for end users.

1 Like

The logic is quite odd actually. If the user doesn’t submit the form and just goes directly to the page, it’ll throw you a bunch more fatal errors and not just the one you are getting now. You’ll most likely receive an undefined index on the variable $query since the page is accessed directly. And you have defined $query in the form submission check, but it’s actually being executed outside of the form submission check. This means that if someone actually did submit the form, they’ll most likely receive a blank page or a few more error messages complaining about the rest of the snippet.

Also, to save you lines of resources and time, you can actually append all those variables in an array and execute that array. This would save you a lot of lines because instead having 10 + lines of $stmt->bindParam();, you can have 1 line with an array being executed. But that just depends on preference.

Last, but not least. You don’t technically have to close the database connection. PHP will do this for you. It’s best for practice to close the database connection, but it’s not necessary to open a new connection every time you make a query call.

thanks for the welcome. @felgall. hello. this shopping cart that i am using is totally drop down menu for all values. i don’t think validation is an issue at this point for that reason with the exception of a promotional field that will be removed altogether. a link to the cart is http://solutionm3.com/ordertest.html.
i hope i made the changes proffered by Mittineague correctly. i’ve looked at several examples and still haven’t got it quite together yet but i will. here is my latest error message and it looks like an sql error:
“Connected to database
SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘description’ cannot be null”.
that appears to be a sql issue so i’m going to look up what it means. after that i will be able to check if the user info was submitted. any thoughts will be most helpful.

you guys are great. you really helped me along.

My guess is that if you run a
SHOW CREATE TABLE details;
You’ll see that the description field is a NOT NULL

i.e. the code is trying to enter a NULL into the field and it isn’t allowed to be NULL
i.e. $_POST['description'] wasn’t set.

I think it also has to do with whether the input has any values in it. I’ve seen this before and it also happened in my topic about the PHP 7 error thingy. In order to not receive this error, OP has to set the description column to NULL. This is the only way to remove the error message. If OP is receiving this error message, that means that the $_POST value of description is empty and has no values in it.

If the $_POST value of description is not empty and has some sort of value or string, no matter if the column is set to NULL or NOT NULL, you will not be seeing the error message because you are appending a string or value to $_POST['description'] and therefore will nullify any errors pertaining to this error message.

1 Like

If validation is not an issue then sanitising definitely is. You should NEVER use TAINTED variables in your code - they must always be either validated or sanitised or you have a DEFINITE security hole in your code that needs to be fixed.

Sounds like you need to study “Introduction to Security for Beginners”.

At the very least, bindParam takes an optional data_type (default is String) that is easy enough to use

http://php.net/manual/en/pdostatement.bindparam.php

That doesn’t prevent any junk string from being entered as the value by someone who has decided to fill your database with junk. Simply set up an automated process to call the code a billion times with random data strings and it would then be difficult to find the real meaningful data in the database.

If you sanitise the fields and only allow the database to insert rows when all the fields contain values that at least might be valid then 99.99999% of the junk would get rejected and you’d still be able to find the real data in amongst the junk.

1 Like

is this better?

$stmt = $dbh->prepare($query);
$stmt->bindParam(‘:description’, $_POST[‘description’], DO::PARAM_STR, 4);
$stmt->bindParam(‘:temple’, $_POST[‘temple’], PDO::PARAM_STR, 3);
$stmt->bindParam(‘:quantity’, $_POST[‘quantity’], PDO::PARAM_STR, 1);
$stmt->bindParam(‘:price’, $_POST[‘price’], PDO::PARAM_STR, 4);
$stmt->execute();

i’ve done some reading but is this satisfactory or do i need implement more security?
thanks, yall.

Yes - you don’t have any security there at the moment to prevent junk insertion.

All of the code to insert to the database is output processing.

Validation/sanitising is input processing that should be completed before output processing is started. There can even sometimes be other processing in between the input processing and output processing. Any references to $_POST should only occur in the input processing.

@felgall: i know i’m not bright but how can junk strings be inserted when there are only 2 dropdown options to process the entire shopping cart? options don’t require strings…or so i thought. could you please explain how junk strings can be inserted in a drop down option? teach me…

Anything that is HTML or client available can be modified. Say I have a group of 3 radio buttons a user can choose from and all 3 of them have a value of an integer that I specified. First radio button has the value of 1, second radio button has a value of 2, and third radio button has a value of 3. If a user wanted to, they can change let’s say the second radio’s value to 69 and still have it passed when the actual values you are only looking for is 1, 2, and 3. The value 69 is not a legit value we are looking for therefore they can add that value into the database and might possibly be output later on as an empty selection.

Same can be done with anything from text fields, text areas, buttons, radio buttons, and drop down lists. These can be dynamic or they can be static. It doesn’t matter. All of these elements can be modified by the client and is considered not safe.

Then if you don’t do any validating to make sure that the values you are looking for are what they are and not a modified value, then you are allowing this scenario to play out. That’s why validating is pretty much important when it comes to user inputs.

Never trust any user supplied input.

1 Like

now i’m starting to get the picture…a little bit: especially after seeing Mittineague’s .gif. that along with spaceshiptrooper’s explanation made it more clear. thanks. i ran across a code that defined the validation issue with regard to list/menu and other input types. in fact it was a post on a sitepoint forum. here is the url

now that i have a grasp of what’s involved i copied the code and put it in a practice file to work through it in my own code. please take a look:

try {
    $dbh = new PDO("mysql:host=$hostname;dbname=new_order", $username, $password);
	
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

if ($_SERVER["REQUEST_METHOD"] == "POST")

{
$errors = [];
}

if(empty($errors)) {

// prepare sql and bind parameters
    $query = "INSERT INTO details (description, temple, quantity, price)
            VALUES (:description, :temple, :quantity, :price)";
}
    $stmt = $dbh->prepare($query);
        $stmt->bindParam(':description', $_POST['description']);
        $stmt->bindParam(':temple', $_POST['temple']);
        $stmt->bindParam(':quantity', $_POST['quantity']);
        $stmt->bindParam(':price', $_POST['price']);
       $stmt->execute();

{
	$error_msg = array();

	}
	if(!isset($_POST['temple'])){
		$error_msg[] = "No temple was selected.";
	}
	
	if(!isset($_POST['quantity'])){
		$error_msg[] = "No quantity was selected.";
	}

	if(isset($error_msg) && count($error_msg) == 0){
		// do some form processing
	}
	else{
		// redirect to the form again.
		http:soloutionm3.com/ordertest.html
	}

} catch (PDOException $exception) {
echo $exception->getMessage(), "<br />";
}

thanks for the look.

1 Like

They don’t have to use your form to send $_POST values - they can either create their own form to submit whatever they like or even intercept and change the values after your form is submitted.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.