How to Squeeze Error Message Out of Pdo

PDO not throwing errors

change your code to

$sql = "INSERT into utenti (nome,username,segreto,password,validity,ruolo,funzione) "
. "VALUES (?,?,?,?,?,?,?)";
$s = $pdo->prepare($sql);
$s->execute([$nome, $username, $segreto, $password, $validity, $ruolo, $funzione]);
echo "ok";

you will have either ok or informative error message

Show WARNINGS in MySQL + PDO

When constructing your PDO instance, pass an array of options, containing this key-value pair:

array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)

To force PDO to throw exceptions (PDOException instances) when an error occurs. Also, when using prepepared statements, you don't add quotes of your own... if the value is a string,

WHERE value = :value

Is just fine, PDO/MySQL will quote the value correctly for you.

PS: You can always change the error mode later on, by calling setAttribute:

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);//raise warnings, don't throw errors

Here's a list of attributes

Here, you'll find examples where options are set via the constructor

example from the doc pages, only extended a bit:

$pdo = new PDO('mysql:host=myhost;dbname=mydb', 'login', 'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL)
);

Edit:

After a second glance at your question, I noticed the actual warning you got. That warning will evidently not throw an Exception. Prepared statements check the datatypes upon statement preparation, after that job is done, the statement gets executed. In your case, the double is cast to a varchar, and then the query is executed, comparing the varchars in value with the varchar in the query. No warnings, no fuss, it just does the job.

Here's a related question

And here's a more detailed explanation on how prepares work

Why does this PDO statement silently fail?

TL;DR

  1. Always have set PDO::ATTR_ERRMODE to PDO::ERRMODE_EXCEPTION in your PDO connection code. It will let the database tell you what the actual problem is, be it with query, server, database or whatever.
  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.

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.

P.S.

Sometimes there is no error but no results either. Then it means, there is no data to match your criteria. So you have to admit this fact, even if you can swear the data and the criteria are all right. They are not. You have to check them again. I've 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.

Why PDO Exception Error Not Caught?

Your call to setAttribute() lacks the first parameter:

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

If you didn't get a

Warning: PDO::setAttribute() expects exactly 2 parameters, 1 given

your error_reporting level is too low for a development server and/or you didn't keep an eye on the error log or didn't set display_errors=On (which ever you prefer; I prefer the error log over display_errors).


edit: please try

<?php
echo 'php version: ', phpversion(), "\n";

try {
$dbh = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly');
echo 'client version: ', $dbh->getAttribute(PDO::ATTR_CLIENT_VERSION), "\n";
echo 'server version: ', $dbh->getAttribute(PDO::ATTR_SERVER_VERSION), "\n";
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $err) {
var_dump($err->getMessage());
die('...');
}

$id = 'foo';

try
{
$stmt = $dbh->prepare("SELECT COUNT(*) FROM Product WHERE `non-existent_column`=?");
$stmt->bindValue(1, $id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetchColumn();
}
catch(PDOException $err)
{
var_dump($err->getMessage());
var_dump($dbh->errorInfo());
die('....');
}

echo 'done.';

printed on my machine

php version: 5.3.5
client version: mysqlnd 5.0.7-dev - 091210 - $Revision: 304625 $
server version: 5.5.8
string(94) "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'non-existent_column' in 'where clause'"
array(3) {
[0]=>
string(5) "42S22"
[1]=>
int(1054)
[2]=>
string(54) "Unknown column 'non-existent_column' in 'where clause'"
}
....

Error binding PDO query in PHP

Except for the $pdo = null line which is after a return and therefore never executed, and the $db = $db1() where the function is used as a variable, the code hasn't anything obviously wrong. Since you say that replacing the bindings with variables work, I assume the last is a typo.

So I suggest you try and var_dump what the values of $var1 and $var2 are at that point in the script.

UPDATE

I have duplicated the setup like this

<?php

$db = new PDO("mysql:host=localhost;dbname=test");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$var1 = 1; // See answer text below
$var2 = 2;

$query = $db->prepare("SELECT * FROM test WHERE column5=:col1 AND column6=:col2");
$query->bindValue(':col1', $var1, PDO::PARAM_INT);
$query->bindValue(':col2', $var2, PDO::PARAM_STR);
$query->execute();
$row = $query->fetch(PDO::FETCH_ASSOC);
print_r($row);
?>

Then I created a first table like this

CREATE TABLE test ( column5 INTEGER, column6 INTEGER );

and then like this

CREATE TABLE test ( column5 varchar(5), column6 varchar(5) );

and I tried defining $var1 and $var2 as 1,2 (integer) and "1","2" (strings).

It always worked, i.e., I expected to get a single row as output, and I did:

Array
(
[column5] => 1
[column6] => 2
)

At this point I think the only possibility left is something strange in the database content.

Therefore I also expect the test below, on your system, not to work, i.e. not to return the desired row:

$query = $db->prepare("SELECT column1, column2, column3, column4 FROM table_name WHERE (column4=2 OR column4=3) AND column5=2 AND column6='1'");
$query->execute();
$row = $query->fetch(PDO::FETCH_ASSOC);
var_dump($row);

PHP PDO INSERT query failing

Add the following to the top of your PHP script so that you can see all PHP error messages:

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

You could also check the return, or error, values from some of your database methods.

In some databases user is a reserved keyword and needs to be surrounded in back-ticks or square-brackets, depending on the database.



Related Topics



Leave a reply



Submit