Rifthy
Rifthy

Reputation: 751

Why does this PDO statement silently fail?

This is my PHP SQL statement and it's returning false while var dumping

$sql = $dbh->prepare('INSERT INTO users(full_name, e_mail, username, password) VALUES (:fullname, :email, :username, :password)');
$result = $sql->execute(array(
                    ':fullname' => $_GET['fullname'], 
                    ':email' => $_GET['email'], 
                    ':username' => $_GET['username'],
                    ':password' => $password_hash));

Upvotes: 62

Views: 20483

Answers (3)

tronman
tronman

Reputation: 10115

This shouldn't happen anymore if using PHP 8, which changed PDO error handling. PDO::ERRMODE_EXCEPTION is now the default mode. PDO will throw a PDOException with the error code and set its properties to reflect the error code and error information.

Source: PDO error handling doc

Upvotes: 1

Your Common Sense
Your Common Sense

Reputation: 157839

TL;DR

  1. Always have PDO::ATTR_ERRMODE option set to PDO::ERRMODE_EXCEPTION in your PDO connection code. It will let the database tell you what the actual problem is, be it with SQL, data, server or database. Also, make sure you can see PHP errors in general.
  2. Always replace every PHP variable in the SQL query with a question mark, and execute the query using prepared statement. It will help to avoid syntax errors of all sorts.

Explanation

Sometimes your PDO code produces an error like Call to a member function execute() or similar. Or even without any error but the query doesn't work all the same. It means that your query failed to execute. The reasons can be split into four categories:

  1. The code didn't execute at all
  2. The input data is wrong.
  3. There was an error during execution.
  4. It was executed successfully but a correct result is not observed due to some observational error.

In order to deal with first two you need to use some debugging techniques, that's out of scope of this answer, but you can get some hints from my article on PHP debugging.

The 3rd category is the most common one. But easiest to investigate, because every time a query fails, MySQL has an error message that explains the reason. Unfortunately, by default such errors are not transferred to PHP, and all you have is a silence or a cryptic error message mentioned above. Hence it is very important to configure PHP and PDO to report you MySQL errors. And once you get the error message, it will be a no-brainer to fix the issue.

In order to get the detailed information about the problem, either put the following line in your code right after connect

$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

(where $dbh is the name of your PDO instance variable) or - better - add this parameter as a connection option. After that all database errors will be translated into PDO exceptions which, if left alone, would act just as regular PHP errors.

After getting the error message, you have to read and comprehend it. It sounds too obvious, but learners often overlook the meaning of the error message. Yet most of time it explains the problem pretty straightforward:

  • Say, if it says that a particular table doesn't exist, you have to check spelling, typos, letter case. Also you have to make sure that your PHP script connects to a correct database
  • Or, if it says there is an error in the SQL syntax, then you have to examine your SQL. And the problem spot is right before the query part cited in the error message.

You have to also trust the error message. If it says that number of tokens doesn't match the number of bound variables then it is so. Same goes for absent tables or columns. Given the choice, whether it's your own mistake or the error message is wrong, always stick to the former. Again it sounds condescending, but hundreds of questions on this very site prove this advice extremely useful.


Note that in order to see PDO errors, you have to be able to see PHP errors in general. To do so, you have to configure PHP depends on the site environment:

  • on a development server it is very handy to have errors right on the screen, for which displaying errors have to be turned on:

      error_reporting(E_ALL);
      ini_set('display_errors',1);
    
  • while on a live site, all errors have to be logged, but never shown to the client. For this, configure PHP this way:

      error_reporting(E_ALL);
      ini_set('display_errors', 0);
      ini_set('log_errors', 1);
    

Note that error_reporting should be set to E_ALL all the time.

Also note that despite the common delusion, no try-catch have to be used for the error reporting. PHP will report you PDO errors already, and in a way better form. An uncaught exception is very good for development, yet if you want to show a customized error page, still don't use try catch for this, but just set a custom error handler. In a nutshell, you don't have to treat PDO errors as something special but regard them as any other error in your code.


Observational errors

Sometimes there is no error but no results either. Then it means, there is no data to match your criteria. I've got a short answer that would help you to pinpoint the matching issue, Having issue with matching rows in the database using PDO. Just follow this instruction, and the linked tutorial step by step and either have your problem solved or have an answerable question for Stack Overflow.

Upvotes: 80

Atanas Yordanov
Atanas Yordanov

Reputation: 541

Some time ago I had the same problem of not seeing any error messages from mysql. After a research it turned out that the problem has got nothing to do with PHP itself, but with mysql server configuration. The default value of the variable lc_messages_dir pointed to non existing directory. After adding a line in mysqld.cnf, then restarted the mysql server, and finally I was able to see the error messages. For me the following was the right one:

lc_messages_dir=/usr/share/mysql

It is described in the mysql reference manual: https://dev.mysql.com/doc/refman/5.7/en/error-message-language.html

Upvotes: 1

Related Questions