PDO Can't catch exception which is thrown - php

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.

Related

Getting undefined variable: pdo in index.php

I am creating a recipe's database and after adding 'add' and 'delete' functionality, the system throws an error:
Notice: Undefined variable: pdo in C:\xampp\htdocs\COMP1321\recipes\index.php on line 52
Fatal error: Uncaught Error: Call to a member function query() on null in C:\xampp\htdocs\COMP1321\recipes\index.php:52 Stack trace: #0 {main} thrown in C:\xampp\htdocs\COMP1321\recipes\index.php on line 52
Index.php
try // selection block
{
$sql = 'SELECT * FROM recipe';
$result = $pdo->query($sql);
}
Databaseconnection.inc.php
<?php
try
{
//new PDO('mysql:host=mysql.cms.gre.ac.uk; dbname=mdb_', '', '');
$pdo = new PDO('mysql:host=localhost; dbname=mdb_recipes', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES "utf8"');
} catch (PDOException $e) {
$error = 'Unable to connect to database server';
include 'error.html.php';
exit();
}
I have been trying to solve this problem for 3 hours already. Some help would be appreciated!
Full Index.php
<?php
if(isset($_GET['addrecipe'])) {
include 'form.html.php';
exit();
}
//insert block
if (isset($_POST['recipename'])) {
include 'admin/includes/db.inc.php';
try
{
//prepared statement
$sql = 'INSERT INTO recipe SET
recipename = :recipename,
recipedate = CURDATE()';
$s = $pdo->prepare($sql);
$s->bindValue(':recipename', $_POST['recipename']);
$s->execute();
} catch (PDOException $e) {
$error = 'Error adding submitted recipe' . $e->getMessage();
include 'error.html.php';
exit();
}
header('Location: .');
exit();
}
//delete block
if(isset($_GET['deleterecipe']))
{
include '../includes/db.inc.php';
try
{
$sql = 'DELETE FROM recipe WHERE id = :id';
$s = $pdo->prepare($sql);
$s->bindValue(':id', $_POST['id']);
$s->execute();
}
catch (PDOException $e)
{
$error = 'Error deleting recipe' . $e->getMessage();
include 'error.html.php';
exit();
}
header('Location: .');
exit();
}
try // selection block
{
$sql = 'SELECT * FROM recipe';
$result = $pdo->query($sql);
}
catch (PDOException $e) {
$error = 'Error fetching recipes' . $e->getMessage();
include 'error.html.php';
exit();
}
foreach ($result as $row) {
$recipes[] = array(
'id' => $row['id'],
'recipename' => $row['recipename'],
'time' => $row['time'],
'ingredients' => $row['ingredients'],
'recipetext' => $row['recipetext'],
'servings' => $row['servings'],
'nutritionfacts' => $row['nutritionfacts'],
'recipedate' => $row['recipedate'],
'image' => $row['image'],
);
}
include 'recipes.html.php';
Looks like you never include the database connection file.
If $_POST['recipename'] is not set, and $_GET['deleterecipe'] is not set, then when you get to that line, db.inc.php has never been included, so $pdo is not defined.
You need to move your include 'admin/includes/db.inc.php'; line to be right below the form.html.php include.
This will make it available for the entire page as it is required regardless of whether or not you are inserting or deleting a recipe since you need it for the selection block at the bottom.
You only need to include the file once per page and I would normally use require_once() at the top of the file for the DB and other global dependencies like this, rather than trying to include it each place you need it 3+ times per file and then end up unnecessarily including the file and possibly generating warnings or errors. Generally it just makes your code more complicated. It's a shared resource, let it be shared. Or create a singleton to creates or retrieve the PDO instance for you in a standard way so you only have 1 PDO connection instead of potentially multiple per request.

Why is this PDOException not caught?

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);

connection to the database using PDO

im trying to learn PDO
i've made this code to connect to the database
<?php
$dbhost = "localhost";
$dbname = "testcreate";
$dbuser = "root";
$dbpass = "mysql";
if (!$db) {
throw new Exception('failed to connect to mysql')
}
try {
$db = new PDO('mysql:host='.$dbhost.';dbname='.$dbname.';charset=utf8', ''.$dbuser.'', ''.$dbpass.'');
} catch (MyFunkyException $e) {
echo "Caught exception : ", $e->getMessage();
}
?>
the connection works, but when i try to make an error and i want to catch the error
this error popup
Fatal error: Uncaught exception 'Exception' with message 'failed to connect to mysql' in C:\Program Files (x86)\Ampps\www\test.php:8 Stack trace: #0 {main} thrown in C:\Program Files (x86)\Ampps\www\test.php on line 8
can you help me fix the error or shows me the right way to do it
the problem is that
You're trying to throw exception before connection and outside of try.
There is no need to throw your own exception because PDO throws its own exception if connection fails.
Also you'd consider exception type.
try {
$db = new PDO('mysql:host='.$dbhost.';dbname='.$dbname.';charset=utf8', ''.$dbuser.'', ''.$dbpass.'');
} catch (PDOException $e) {
echo "Caught exception : ", $e->getMessage();
}
Also, there is no need to turn PDO on exceptions to catch an exception. But if you are trying to handle errors with exceptions you must turn on that feature right after connection is established.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
The problem is that you don't want to catch anything.
At least until you want it only to echo the error message out.
Also, exceptions has nothing to do with PDO syntax.
The real problem here is in this line:
} catch (MyFunkyException $e) {
MyFunkyException is a classname of the type of exception you want to catch.
PDO doesn't throw a MyFunkyException exception - the docs state that it throws a PDOException exception.
You can fix this by changing the line like this:
} catch (PDOException $e) {
Or by catching all exceptions regardless of type, like this:
} catch (Exception $e) {
try by using this code below
<?php
$dbhost = "localhost";
$dbname = "testcreate";
$dbuser = "root";
$dbpass = "mysql";
try {
$db = new PDO('mysql:host='.$dbhost.';dbname='.$dbname.';charset=utf8', $dbuser, $dbpass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
?>

PDO exceptions not being caught

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();
}
}

Automatically Catch Exceptions for PDO in PHP

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.

Categories