I am connecting to MySQL through PDO with Zend\Db from ZF2. How can I report the last errorInfo()?
Here's what I have:
$sqlWriter = new Sql($this->getAdapter());
$insert = $sqlWriter->insert('table_name')->columns(array_keys($data))->values($data);
$stmt = $sqlWriter->prepareStatementForSqlObject($insert);
try {
$stmt->execute();
$object->id = $this->getAdapter()->driver->getLastGeneratedValue();
} catch (\Exception $e) {
//
// HOW CAN I display errorInfo() here?
//
throw new Exception\Exception('Unable to insert record...');
}
I have tried calling methods on the adapter, driver, statement, platform, result, etc... But all to no avail...
EDIT: I found that I can get the info I am looking for by posting the following at the top of the catch block:
$pdoException = $e->getPrevious();
var_dump($pdoException);
I'll leave the question open however since it would be good to know how to execute PDO::errorInfo() directly.
Related
I have a PHP psql query. I am doing try catch to prevent Duplicates. When I ran the script I can see it's inserting something into my DB. But when I check my DB it's empty.
foreach($data as $n){
$query = $psql->pdo_prepared("INSERT INTO students(id,email,address,phone)VALUES".myFunction($array);
}
and I have a PHP class to handle the exception:
public function pdo_prepared($query,array){
try{
// some logic
}
catch(EXCEPTION $e){
//empty
}
}
The reason why I am doing try catch is to catch duplicates and ignore it. If I throw an exception in my catch block my insert statement won't execute because my current data contains duplicates.
I've got a (example) Oracle Stored Procedure:
CREATE OR REPLACE FUNCTION EXCEPTION_TEST
RETURN NUMBER
AS
BEGIN
raise_application_error(-20500, 'This is the exception text I want to print.');
END;
and I call it in PHP with PDO with the following code:
$statement = $conn->prepare('SELECT exception_test() FROM dual');
$statement->execute();
The call of the function works perfectly fine, but now I want to print the Exception text only.
I read somewhere, that you should not use try and catch with PDO. How can I do this?
You have read that you shouldn't catch an error to report it.
However, if you want to handle it somehow, it's all right to catch it.
Based on the example from my article on handling exception in PDO,
try {
$statement = $conn->prepare('SELECT exception_test() FROM dual');
$statement->execute();
} catch (PDOException $e) {
if ($e->getCode() == 20500 ) {
echo $e->getmessage();
} else {
throw $e;
}
}
Here you are either getting your particular error or re-throwing the exception back to make it handled the usual way
You check the execute response and get the error, for example, like this:
if ($statement->execute() != true) {
echo $statement->errorCode();
echo $statement->errorInfo();
}
You can find more options at the PDO manual.
I've been trying to use a sqlite database (php with PDO), but have been running into a problem. Generally the commands work, and everything is fine (including storing files), but for some reason when I run these two commands (which have been simplified), I get the error
SQLSTATE[HY000]: General error: 5 database is locked
I've tried for a while, but have been unable to fix whatever is wrong. The code is below.
Things I've done:
Tried to put sleep(2) between commands
Found out that commenting either of the commands out will cause the error not to happen (which doesn't really help, as both commands must run)
Note that (unlike other problems I saw while looking at similar questions) the database operates correctly in other cases.
$db = new MyDB();
$STH = $db->catchMistakes('SELECT PASSWORD FROM USERS WHERE USERNAME = ?', "test");
$STH->fetchColumn();
$db->catchMistakes("UPDATE ISSUES SET NAME = ? WHERE NUM = ?", ["test", "1"]);
And here's the code for MyDB
public function catchMistakes($cmd, $params = []) {
if (!is_array($params)) {
$params = [$params];
}
try {
$DBH = new PDO("sqlite:" . DB);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$DBH->beginTransaction();
$query = $DBH->prepare($cmd);
$toReturn = $query->execute($params);
$DBH->commit();
return $query;
}
catch(PDOException $e) {
$DBH->rollback();
$error = $e->getMessage();
exit;
}
}
Sorry if there's a simple fix, I'm pretty new at this. Any help would be greatly appreciated.
You can use closeCursor() method on a PDOStatement object to free the connection to the database so the statement can be executed. You can refer to the PHP manual.
I'm currently working on a proyect on cakephp 2.0 where i need to insert multiple users to a sql server database.
I need to make a rollback if something fails, but not necessarilly if the stored procedure failed, but if something within the php file logic fails throws an exception to make the rollback.
The code works like this:
try {
...$this->db->beginTransaction();//The connection to the DB is already on.
foreach($users as $user){
//some logic
if(something) {
throw new Exception('blah blah');
}
$query = $this->sqlsrv->prepare('storedProcedure1');
//bind parameters
if(!$query->execute()) {
throw new Exception('blah blah');
}
//some logic...
if(something) {
throw new Exception('blah blah');
}
$query = $this->sqlsrv->prepare('storedProcedure2');
bind parameters
if(!$query->execute()) {
throw new Exception('blah blah');
}
}
$this->db->commit();
}
catch (Exception $e){
$this->db->rollBack();
}
I dont know if something like this may be possible, the functions return true, but the succesfull inserts from the stored procedures are still there, and i would like to tollback all of those even when they were succesfull.
I'm using the following script to use a database using PHP:
try{
$db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options);
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
Now, I want to use this database handle to do a request using this code:
try{
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
Here is the problem:
When the connection to the DB is OK, everything works,
When the connection fails but I don't use the DB, I have the $GLOBALS['errors'][] array and the script is still running afterwards,
When the connection to the DB has failed, I get the following fatal error:
Notice: Undefined variable: db in C:\xampp\htdocs[...]\test.php on line 32
Fatal error: Call to a member function prepare() on a non-object in C:\xampp\htdocs[...]\test.php on line 32
Note: Line 32 is the $query = $db->prepare(...) instruction.
That is to say, the script crashes, and the try/catch seems to be useless. Do you know why this second try/catch don't works and how to solve it?
Thanks for the help!
EDIT: There are some really good replies. I've validated one which is not exactly what I wanted to do, but which is probably the best approach.
try/catch blocks only work for thrown exceptions (throw Exception or a subclass of Exception must be called). You cannot catch fatal errors using try/catch.
If your DB connection cannot be established, I would consider it fatal since you probably need your DB to do anything meaningful on the page.
PDO will throw an exception if the connection cannot be established. Your specific problem is that $db is not defined when you try to call a method with it so you get a null pointer (sort of) which is fatal. Rather than jump through if ($db == null) hoops as others are suggesting, you should just fix your code to make sure that $db is either always defined when you need it or have a less fragile way of making sure a DB connection is available in the code that uses it.
If you really want to "catch" fatal errors, use set_error_handler, but this still stops script execution on fatal errors.
In PHP7, we now can using try catch fatal error with simple work
try {
do some thing evil
} catch (Error $e) {
echo 'Now you can catch me!';
}
But usualy, we should avoid using catch Error, because it involve to miss code which is belong to programmer's reponsibility :-)
I will not report what has already been written about testing if $db is empty. Just add that a "clean" solution is to artificially create an exception if the connection to the database failed:
if ($db == NULL) throw new Exception('Connection failed.');
Insert the previous line in the try - catch as follow:
try{
// This line create an exception if $db is empty
if ($db == NULL) throw new Exception('Connection failed.');
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
Hope this will help others!
If database connection fails, $db from your first try .. catch block will be null. That's why later you cannot use a member of non-object, in your case $db->prepare(...). Before using this add
if ($db) {
// other try catch statement
}
This will ensure that you have db instance to work with it.
Try adding the following if statement :
if ($db) {
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(....);
}
else die('Connection lost');
try{
if(!is_null($db))
{
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}