Evening,
I am currently handling PDO exceptions like this:
try{
$db = Db::connect();
$query = $db->prepare( "SELECT * FROM table;" );
$query->execute();
}
catch( PDOException $e ) { error( 'MySQL error: ' . $e->getMessage(), __FILE__, __LINE__ ); }
My handling each time is exactly the same. So I am wondering if there is a way I can set up that when there is a PDO exception that it automatically runs:
catch( PDOException $e ) { error( 'MySQL error: ' . $e->getMessage(), __FILE__, __LINE__ ); }
Take a look at the Documentation of PDO
You can change the error handling to PDO::ERRMODE_SILENT or PDO::ERRMODE_WARNING
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
Or use set_exception_handler and define a handler for all your exceptions.
Try and edit the class itself to catch it.
Related
I have this little snippet that connects to sql server using PDO, and it fails because my server is down (which is correct, it's the scenario I want to test). However, the exception is not caught!
$dsn = "sqlsrv:Server=$host,$port;Database=$database";
$conn = new PDO($dsn, $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$works = false;
try {
$works = ($conn->exec('SELECT * FROM INFORMATION_SCHEMA.TABLES') !== false);
}
catch (\PDOException $e) {
}
echo "works? " . ($works ? 'yes' : 'no') . "\n";
The output I get in console:
➜ backend git:(dev) ✗ php mssql-pdo-test.php
PHP Fatal error: Uncaught PDOException: SQLSTATE[HYT00]: [Microsoft][ODBC Driver 17 for SQL Server]Login
timeout expired in /path/mssql-pdo-test.php:10
Stack trace:
#0 /path/mssql-pdo-test.php(10): PDO->__construct()
#1 {main}
thrown in /path/mssql-pdo-test.php on line 10
I guess the exception is thrown outside the try / catch block here:
$conn = new PDO($dsn, $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Here is my code:
<?php
try{
// connect to database and select database
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "spy";
$dbh_conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$dbh_conn->exec("set names utf8");
$dbh_conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>
My code works as well. But I seen a similar code which checks the connection like this:
if ( !$dbh_conn ){
// Something Went Wrong
} else {
// All Fine
}
Well do I need to this ^ condition? Or using try catch is enough to check db connection?
It depends on what you set for PDO::ATTR_ERRMODE. In your case, it's set as PDO::ERRMODE_EXCEPTION, so an error will throw an Exception.
$dbh_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
This error mode however is not applied when you connect (i.e., when __constructor() is called in PDO), since a PDOException is always thrown:
PDO::__construct() will always throw a PDOException if the connection fails regardless of which PDO::ATTR_ERRMODE is currently set. Uncaught Exceptions are fatal.
You can read about the different modes here.
I have the following connection being made using PDO. Obviously it won't connect as I've not specified host or database (or user or password)
$dbh = new PDO('mysql:host=;dbname=', '', '');
..so how do I catch the exception? I'm trying something like this:
try {
$dbh = new PDO('mysql:host=;dbname=', '', '');
} catch (Exception $e) {
echo 'Error: ', $e->getMessage(), "\n";
}
.. but no message is displayed. Why?
Are you using custom namespace? then you need to change
} catch (\Exception $e) {
echo 'Error: ', $e->getMessage(), "\n";
}
notice the backslash before Exception.
You need to pass the attribute ERRMODE_EXCEPTION in order to receive exceptions on a failing connection attempt:
$dbh = new PDO('mysql:host=;dbname=', '', '', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
Check the manual page of PDO::__construct() for more info.
Please also check #Ali's answer!
Ok so I can't catch the exeption:
require_once 'config/config.php';
try {
$dbh = new PDO('mysql:host='.DB_HOST.';dbname='.DB_DATABASE, DB_USER, DB_PASS,array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (PDOException $e) {
print "Unable to connect!: " . $e->getMessage() . BR;
die();
}
try {
$stmt = $dbh->prepare("SELECT id,email FROM no_table ORDER BY id DESC LIMIT 5");
$stmt->execute();
$stmt->bindColumn(1, $id, PDO::PARAM_INT);
$stmt->bindColumn('email', $email, PDO::PARAM_STR);
while ($row = $stmt->fetch(PDO::FETCH_BOUND)) {
echo $id . "\t" . $email . BR;
}
} catch (PDOException $e) {
echo "Failed: " . $e->getMessage();
}
Ok I connect I have an error in the syntax (there isn't any no_table) it throws the exception but i can't catch it. In browser I see this:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]:
Base table or view not found: 1146 Table 'no_table' doesn't exist' in 'somepath'
PDOStatement->execute() #1 {main} thrown in some.php on line 15
The exception is thrown and i can't catch it, but if I put another try catch between $stmt->execute(); it catches it.
My php version 5.3.14
Have you been using namespaced classes in this project maybe?
If so, please try to use
\PDOException
instead of
PDOException
in your "catch" statement.
I just got similar problem and this move helped.
I'm new to using PDO and I'm finding that exceptions due to errors in the query statements are not being caught and displayed properly. The page output when this happens typically looks like:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: ...
I make PDO queries using the following function:
/**************************************************************************************************************
* Function: makeQuery *
* Desc: Makes a PDO query. *
* Pre conditions: The statement/query and an array of named parameters (may be empty) must be passed. *
* Post conditions: The PDO query is executed. Exceptions are caught, displayed, and page execution stopped. *
**************************************************************************************************************/
function makeQuery($stmt, $array, $errMsg = '')
{
try
{
$stmt->execute($array);
}
catch (PDOException $e)
{
print $errMsg != ''?$errMsg:"Error!: " . $e->getMessage() . "<br/>";
die();
}
}
Any idea why the exceptions are not being caught?
EDIT: This is how I create PDO objects:
function createPDO()
{
// MySQL connection details
$dbhost = '';
$dbuser = '';
$dbpass = '';
$dbname = '';
try
{
$db = new PDO("mysql:$dbhost=localhost;dbname=$dbname;charset=utf8", $dbuser, $dbpass, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
}
catch (PDOException $e)
{
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
return $db;
}
Any chance the file you're catching the exception uses namespaces? In that case it should be:
catch (\PDOException $e)
Or add:
use PDOException;
On the top of the file
Are you sure every query is running through that function? Might look through your code to be 100% certain.
Another option is to define a global exception handler then just ask the thrown exception which line & file it came from:
http://php.net/manual/en/function.set-exception-handler.php
function exception_handler($exception)
{
echo "Uncaught exception: " . $exception->getMessage() . PHP_EOL;
echo "In file: " . $exception->getFile() . PHP_EOL;
echo "On line: " . $exception->getLine() . PHP_EOL;
}
set_exception_handler('exception_handler');
EDIT:
After some dialog w/ OP I'm now certain that the call to PDOStatement::prepare is where the Exception is being thrown, hence I'm recommending yet another wrapper function to the library:
function prepareStmt(PDO $oPdo, $sStmt, array $aDriverOptions=array())
{
try
{
return $oPdo->prepare($sStmt, $aDriverOptions);
}
catch(PDOException $e)
{
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
}