PDO beginTransaction Not Letting Script Execute - php

I have a PHP script using PDO Transactions.
$PDO->beginTransaction();
$sth = $PDO->prepare("INSERT INTO tbl_last_packing_upload (folderID, subfolderID) VALUES (1, 1)");
$sth->execute();
For some reason, this works locally (the INSERT runs), but not when I push it to my remote server.
To get my INSERT to work remotely, I need to put it ABOVE the $PDO->beginTransaction(); line. The following works remotely:
$sth = $PDO->prepare("INSERT INTO tbl_last_packing_upload (folderID, subfolderID) VALUES (1, 1)");
$sth->execute();
$PDO->beginTransaction();
Why does my INSERT not fire on my remote server when I have it placed inside the beginTransaction? I have many other PHP scripts on the same remote server using transactions and they all work fine.
Any ideas?

Unless there is an existing open transaction ($PDO->beginTransaction() was previously called but uncommitted), there should be no issue with the code as posted. If there was an open transaction, PDO would throw an exception when attempting to start a new one.
You already have PDO setup to throw exceptions rather than error silently with
$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
and if your transaction and INSERT statement code are wrapped in a try/catch block, you will need to debug and inspect the error caught in the catch block.
An error caught in catch (PDOException $e) {...} won't go into PHP's built-in error reporting mechanism on its own, so you'll need to force it to print to a location you can read. On a production web server, you won't want to print it to the screen, so instead I would recommend writing it to the web server's error log with PHP's error_log() function. A simple write to the default log location requires only the message as a parameter.
try {
// everything posted above
} catch (PDOException $e) {
// Caught an error, write it to the log
error_log("Error at line " . __LINE__ . " in " . __FILE__ . ": " . $e->getMessage());
// Whatever else you already do to handle the error...
// etc...
}

Related

PHP Halts Upon PDO Execute()

I'm using WAMP as my platform. Running the following code (pdodb is a framework for working with PDO):
<?PHP
$mysql = pdodb::getInstance();
$query = " SELECT PhysicalID FROM PhysicalInfo
WHERE barcode=0";
$mysql->Prepare($query);
$res = $mysql->Execute($query);
?>
PHP halts upon "Execute()" e.g. the next lines are not executed! I used try/catch to catch (Exception e) but even the error message in catch is not displayed! needless to say that there's no use inserting $res->errorInfo() after the execute() because it won't run either. Although, if I set the database in my code:
$query = " SELECT PhysicalID FROM **carinfo.**PhysicalInfo
WHERE barcode=0";
The code runs perfectly. Using PHPMyAdmin, I get the following error on the first query:
#1046 - No database selected
The problem is:
Why does PHP halt on this and the rest of the program after
$mysql->Execute($query); is not run.
How could I get the error message to check for it in my program (it's pretty ugly to have your code stop without any warning).

Try & catch pdo close database connection

try{
//PDO CONNECT DB, $db
}catch(PDOException $e){die("ERROR"));}
I have a query user PDO connect to database.
I use try & catch, my question is if my query is error
Do i need to close conncetion before die();?
}catch(PDOException $e){$db="NULL"; die("ERROR"));}
As a matter of fact, you shouldn't die() at all
Until you learn how to use try and catch properly, you shouldn't use this statement. It is not intended for echoing "ERROR". It has totally different purpose.
If you want to echo silly "ERROR" in case of an erroneous query, you have to do it properly.
Namely,
send appropriape HTTP header
log the error to notify a developer of the problem
show whatever error message to the client
have all this stuff done in one place, not repeated for every query
to do this, you have to set up an exception handler:
set_exception_handler('myExceptionHandler');
function myExceptionHandler($e)
{
header('HTTP/1.1 500 Internal Server Error', TRUE, 500);
error_log($e->getMessage().". Trace: ".$e->getTraceAsString());
echo "ERROR";
exit;
}
put this code in your bootstrap/config file and quit wrapping every query into try-catch.
No, it is not necessary in php. When your php process finished, the connection will be closed too.

Loggin' try-catch transactions

My code is
try{
$this->_db->beginTransaction();
$stmt = $this->_db->prepare("...");
$stmt->execute(array($var1, $var2));
...
} catch (Exception $e) {
$stmt->rollBack();
}
I want to log this action to my log file with a function
as you see this one meant to save errors in transaction. Another one should also save the succeeded attempts. BUT if I put them inside of try{} and catch{} they not working for some reason. outside it does work good but I'm not sure what exactly should I check here for true/false to see the result outside of try/catch.
Thanks for your answers. I'm just learning so my questions might be stupid. Sorry for this. =)
Update.
What I've tried to do is:
try{...
} catch (Exception $e) {
$stmt->rollBack();
file_put_contents(LOG_CONST, date("r")." UderID: ".$id." Error: ".$e->getMessage()."\n", FILE_APPEND);
}
And it didn't put anything.
Update 2
Not sure if I have to add a new details here or I should answer to myself... Anyway. Right now I'm trying this code
try{
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_db->beginTransaction();
$stmt = $this->_db->prepare
..................
$stmt->execute(array($var));
file_put_contents(DATACHANGE_LOG, date("r")." ".n307." UderID: ".$id."\n", FILE_APPEND);
$this->_db->commit();
} catch (Exception $e) {
file_put_contents(DATACHANGE_LOG, date("r")." Hello! \n", FILE_APPEND);
$stmt->rollBack();
}
I have a same result with valid and not valid data at my log file. It's the first row from try{} which means that rollback is not affective at file_put_contents. However if the data at queries not valid rollback working agains them and there is no changes at DB. But the row before rollback never works.
Errors are enabled but it doesn't show anything... I just can't give up I have to understand it...
Update 3
What is invalid data?
I've tried MySQL errors/table,row errors.
Why do I need this at all?
I'm learning and doing a lot of things that I don't need actually just to understand how it works. As I see now it throwing errors in MySQL itself so really not useful logger in this particular case. Anyway I've got my errors and here is it.
Working code:
try{
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_db->beginTransaction();
$stmt = $this->_db->prepare
QUERIES
$stmt->execute(array($var));
file_put_contents(DATACHANGE_LOG, date("r")." ".n307." UserID: ".$id."\n", FILE_APPEND);
$this->_db->commit();
}catch(PDOException $e){
file_put_contents(DATACHANGE_LOG, date("r")."Error". $e->getMessage()." UserID: ".$id."\n", FILE_APPEND);
if($this->_db->rollback())
header("Location: http://link");
}
header("Location: http://anotherlink");
There is nothing essentially different inside try..catch blocks. And your file writing code should be working the same way as outside, no difference.
The only issue I can think of is irrelevant to try..catch but to exceptions in general: a thrown exception terminates further code execution. Say, if there is an error in $stmt->rollBack(); - no code below will be executed. So, it's better to move a logger at the top of the block.

PDO error handling and storing errors in database

How would I go about getting PDO statements to generate a safe error message? I don't want the user to see the error message. I want them to get directed to a page that says a clean message, "Whoops something unexpected happened!". I would also like to log the errors in a database to review and catch errors others are generating.
I'm using PHP and MySQL.
I found that when you make your connection you can set your error handling like this.
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Anyone do anything like this before?
So this is just a suggestion as I have never tried this but after thinking about it a bit I think it would be an interesting option to explore. As I am fairly new to PHP & PDO I'm sure there are other and better ways.
Perhaps you could try using the try function of PHP and then instead of echo'ing (if failed) the PDOException you could run another function that prints it to a text file. Something like.
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
foreach($dbh->query('SELECT * from FOO') as $row) {
print_r($row);
}
$dbh = null;
} catch (PDOException $e) {
$strFileName = 'whatever.txt';
if(!is_writable($strFileName))
die('Change permisions to ' . $strFileName);
$handle = fopen($strFileName, 'a+');
fwrite($handle, "\r" . $e->getMessage() . "\r");
fclose($handle);
}
?>
This way you would avoid a DB connection (which is the problem I guess) but still save the error.
You would perhaps want to omit the echo'd text after die within the if statement.
I think it is better to write your logs to a file, instead of a database. Especially since you want to log PDO errors, which indicate something is wrong with your database connection.
You can show the user a nice error page by catching your errors. You can redirect your users to your error page then, in case something went wrong.
You have to understand that PDO do not generate a "safe" or "unsafe" error message. It does generate an error message. That's all. The rest is is the responsibility of site-wide PHP settings.
PDO is not the only source of errors. Why care of PDO errors only? Why not to handle ALL errors the same way?
Want errors logged? It's a matter of one PHP ini setting.
Want errors not to be displayed? It's a matter of one PHP ini setting.
Want generic error page to be shown? It's a matter of simple function that will handle all errors at once.
Everything can be done proper and straight way, without wrapping every statement into try catch. Without writing into log manually. Without even single additional line of code.
You need to set up PHP error handling, not PDO.
And of course, it makes absolutely no sense in trying to store a database error in the same database that failed you right now. Errors have to go into error log on a live server and on screen - on a local development PC.
Anyone do anything like this before?
Sure. Every single one of 1000000s sites in the world. The way described above.

PDO update error not showing

I'm fairly new to PDO. I have a try and catch which catches and displays errors when something doesnt exist i.e a table.
However, how can i show the error message/cause for sql failed commands.
For example below i was trying to insert the word "enabled" into a tiny int column - however, only showed me a blank screen - had to debug myself. How can i show SQL failed error messages?
$db = new PDO('mysql:host='.$dateBaseHost.';dbname='.$dateBaseName, $dateBaseUsername, $dateBasePassword);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// set/get variables
$id = (isset($_GET['id']) === true) ? $_GET['id'] : die("ID not set") ; // ? : shorthand if else
$action = (isset($_GET['action']) === true) ? $_GET['action'] : die("Action not set") ; // ? : shorthand if else
// query
$query = $db->prepare(" UPDATE `telephoneCountries` SET `enabled`= :action WHERE `id` = :id ");
// bind parameters - avoids SQL injection
$query->bindValue(':id', $id);
$query->bindValue(':action', $action);
// try... if not catch exception
try {
// run the query
$query->execute();
}
catch (PDOException $e){
//sendErrorMail($e->getMessage(), $e->getFile(), $e->getLine());
echo $e->getMessage();
echo $e->getFile();
echo $e->getLine();
}
i was trying to insert the word "enabled" into a tiny int column
it's fairly OK to mysql. 0 will be inserted.
how can i show the error message/cause for sql failed commands.
for the real errors you have to just setup PHP to display them
ini_set('display_errors',1);
so - you'll be able to see every uncaught exception.
Also, if you are only going to display an error message, but not handle the error itself, just don't use try..catch at all. PHP will do all the job already. That's the point.
Most people do confuse error reporting with error handling. The latter shouldn't be used for the former. When dealing with error messages, your only goal is to make PHP to raise them, and to set up the proper destination:
on a development server an error message have to be show on-screen
on a live sever it shouldn't be shown, but logged instead.
without all these try-catch blocks you'll be able to control error messages (including non-exceptions) by means of a couple ini settings or single error handler function (which I mentioned to you in the other answer).
use try..catch only if you are going to handle the error itself - say, to connect to another server for example.
So, to answer your question more verbosely:
Set PDO in exception mode. Done already.
Remove all try..catch blocks that deals with error messages only.
Setup PHP to show errors on a development server using ini directive above.
On a live server it is strongly recommended to log errors instead of emailing them. But if you still want it this way - use single custom exception handler function to send emails instead of hundreds try..catch blocks

Categories