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();
}
}
Related
I'm porting a class from a non-frameworked php library to Zend Framework 2. This class has methods to run an input query on multiple databases and multiple servers. We have 5 servers, each with anywhere from 5 to over 100 PostgreSQL databases. It works fine with low level postgres calls, but using \Zend\Db\Adapter\Adapter seems to be causing problems because connections aren't being released. Here's the code:
foreach($params['databases'] as $database):
$db_conn['database'] = trim($database);
$dsn = "pgsql:dbname=" . $db_conn['database'] .
";host=" . $db_conn['hostname'] .
";port=" . $db_conn['port'];
$db = array(
'driver' => 'Pdo',
'dsn' => $dsn,
'username' => $db_conn['username'],
'password' => $db_conn['password'],
);
$adapter = new \Zend\Db\Adapter\Adapter($db);
$connection = null;
$connect_count = 0;
$connected = false;
while (!$connected && $connect_count < 5) {
try {
$connect_count ++;
$connection = $adapter->getDriver()->getConnection();
$connection->connect();
$connected = true;
} catch (RuntimeException $e) {
sleep(2);
echo("\n<br>RuntimeException {$connect_count}: {$db_conn['database']} {$e->getCode()} {$e->getMessage()}");
}
}
try {
if (self::checkTablesExist($args['tables_exist'], $connection)) {
$results[trim($database)] = #$connection->execute(self::$arguments['query']);
} else {
log::error(__FUNCTION__." Missing tables", $db_conn['hostname']." : ".$db_conn['database']." : ".join(",", $args['tables_exist']));
}
} catch (PDOException $e) {
echo('\n<br>PDOException : ' . $e->getCode() . " " . $e->getMessage());
} catch (RuntimeException $e) {
echo("\n<br>RuntimeException : {$db_conn['database']} {$e->getCode()} {$e->getMessage()}");
} catch (Exception $e) {
echo('\n<br>Exception : ' . $e->getCode() . " " . $e->getMessage());
}
$connection->disconnect();
endforeach;
Everything works fine until around the 50th database, then I start getting
"RuntimeException: 7 Connect Error: SQLSTATE[08006] [7] FATAL: sorry, too many clients already"
I added the loop with the sleep() statement, which helped slightly. Now it gets to the point where it throws exceptions and the first few it might only go through 2 or 3 times, but then it goes back to not making any connections for the next several databases.
So it seems like $connection->disconnect() isn't working at all, connections are still not being released, at least not in a timely manner. I could just skip using Zend Framework in that part of the code and it would work, but I wanted to do it "canonically", so it wouldn't just be messy like that.
I'm trying to create a library for a personal project using php sockets. For that I started using phpUnit, to learn and to write a (more or less) qualitative library.
When i don't provide the try/catch block in the testConnection method, php gives an error that the connection has timed out (wich is normal, 'cause the device isn't connected). But php should handle the exception in the execute method below, not in the testConnection method. And I can't seem to figure this out.
This is the error:
PHPUnit_Framework_Error_Warning : stream_socket_client(): unable to connect to tcp://x.x.x.x:* (A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.)
Testclass with method and try/catch that should not be there:
public function testConnection() {
$adu = new Adu();
$adu->setPort('AS0');
$adu->setData('?');
$command = new Command('x.x.x.x', *);
$command->setAduSent($adu);
try
{
$command->execute();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
This (the execute method) is where the Exception should be handled:
public function execute()
{
try {
$this->stream = $this->createStream($this->address, $this->port, $this->timeout);
}
catch(Exception $e) {
$this->logger->error('Exception (' . $e->getCode() . '): ' . $e->getMessage() . ' on line ' . $e->getLine(), $e);
}
$this->send($this->stream, $this->aduSent);
$this->aduReceived = $this->receive($this->stream);
}
private function createStream($address, $port, $timeout = 2)
{
$stream = stream_socket_client('tcp://' . $address . ':' . $port, $errorCode, $errorMessage, $timeout);
if(!$stream) {
throw new Exception('Failed to connect(' . $errorCode . '): ' . $errorMessage);
}
return $stream;
}
Solution
Because a try/catch won't catch errors/warnings I had to suppress the warnings triggered by the stream_socket_client. An then check if the return value is false or a stream object. If false, throw an appropriate Exception.
$stream = #stream_socket_client('tcp://' . $address . ':' . $port, $errorCode, $errorMessage, $timeout);
The stream_socket_client sentence produces a warning, not an Exception, and warnings are not captured by try / catch blocks.
But PHPUnit do capture warnings, and throws an Exception in that case, so an error is triggered. You can configure PHPUnit not to consider warnings as errors, although I would not recommend it. Your code should be warnings free. PHPUnit docs.
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.
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();
}
?>
I'm trying to validate my php form using exception, but somehow it doesn't work. The exception is supposed to be thrown if the user enters in "nameg" any character which is not string and in the "amountg" anything which is not integer. Should Exceptions even be used in this case:
if(!empty($_POST['nameg']) && !empty($_POST['amountg']))
{
$user="rootdummy";
$pass="password";
$db="practice";
$nameg=$_POST['nameg'];
$amountg=$_POST['amountg'];
try{
if(!is_int($amountg) || !is_string($nameg)){
throw new Exception("This is the exception message!");
}
}
catch (Exception $e){
$e->getMessage();
}
mysql_connect('localhost',$user,$pass) or die("Connection Failed!, " . mysql_error());
$query="INSERT INTO practable (name,given) VALUES('$nameg',$amountg) ON DUPLICATE KEY UPDATE name='$nameg', given=IFNULL(given + $amountg,$amountg)";
mysql_select_db($db) or die("Couldn't connect to Database, " . mysql_error());
mysql_query($query) or die("Couldn't execute query! ". mysql_error());
mysql_close() or die("Couldn't disconnect!");
include("dbclient.php");
echo "<p style='font-weight:bold;text-align:center;'>Information Added!</p>";
}
Presumably you want to output the exception? Do:
echo $e->getMessage();
Edit: In response to your later comment regarding script ending, put the MySQL queries in the try block.
Edit 2: Changed validation in response to your comments.
if(!empty($_POST['nameg']) && !empty($_POST['amountg']))
{
$user="rootdummy";
$pass="password";
$db="practice";
$nameg=$_POST['nameg'];
$amountg=$_POST['amountg'];
try{
if(!ctype_numeric($amountg) || !ctype_alpha($nameg)){
throw new Exception("This is the exception message!");
}
mysql_connect('localhost',$user,$pass) or die("Connection Failed!, " . mysql_error());
$query="INSERT INTO practable (name,given) VALUES('$nameg',$amountg) ON DUPLICATE KEY UPDATE name='$nameg', given=IFNULL(given + $amountg,$amountg)";
mysql_select_db($db) or die("Couldn't connect to Database, " . mysql_error());
mysql_query($query) or die("Couldn't execute query! ". mysql_error());
mysql_close() or die("Couldn't disconnect!");
include("dbclient.php");
echo "<p style='font-weight:bold;text-align:center;'>Information Added!</p>";
}
catch (Exception $e){
echo $e->getMessage();
}
}
It does, but you're doing nothing with your exception, except catching it.
Try
echo $e->getMessage()
You are catching it and performing a statement that does virtually nothing.
$e->getMessage(); just gets it as a string and throws it away without echoing it.
Either echo it or rethrow or, if you just wanted to exit at that point, don't catch the exception at all (you can remove both the try and catch blocks).