Php, PDO, Sql, Try Catch ,Connection - php

When i am using try catch block for example:
try{
require_once('../php/connect.php');
$dbh = db::getInstance();
// What i am trying to understand should i close the connection here before the header?
header("Location: x.php");
}
} catch(PDOException $e){
require_once('err.php');
}
$dbh = null; // Or should i close the connection here?
Is the "interpreter" even get after line "5", Thank you all and have a nice day.

Since you are not using exit after header() (which is recommended), your code will continue to execute.
As such, it does not matter if you put in on line 4 or 10. Furthermore, as pointed out by prodigitalson, you do no need to explicitly close the database connection.

You dont need to close the connection at all. It will be closed when php exits. However, you arent calling exit after header...
Your code doesnt make sesne though, If the db connection is successful why would you redirect without doing anything???? If using header at all i would think you would call it to redirect to an error page (ie. in your catch block).

Related

Is it safe to put MySQL queries outside try{ }

I have to include database connection in some PHP scripts. So I require() first and then put my queries after. If viewed as a single script, it amounts to something like this:
Try {
$connect = new PDO("mysql:host={$DB_host};dbname={$DB_name}; charset=utf8mb4",$DB_user,$DB_pass);
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
Catch(PDOException $e) {
echo $e->getMessage();
}
// Then I put the queries here
It works, but my question is: is this safe? I've seen in most tutorials that they put all the queries within Try { } curly brackets. And what is the difference between putting the queries within Try { } and putting it after ?
If for whatever reason your query fails the program will crash at the line of code that was executing the query. There may be justification to do this if this a behavior that you desire in your code, for whatever reason.
Without the error handling your program will just break whenever an error is thrown. So unless you specifically need to have the query outside of the try catch (I couldn't guess what for), then you will just be creating trouble for yourself in the future.
If an exception occurs during your query (For instance, if it can't execute the query properly because of a missing quote), the error will not be caught and the execution of your script will halt.
Error handling is usually always preferred when possible. If there is a problem fetching data, inserting data, or simply a typo in your query, you should always have a way to notify a user that an error has occurred (And also, log it for further investigation for yourself.)

PDO MySQL Connection close - unset vs null

I've read in PDO manual that to close connection you should use the following:
$connection = null;
However, Some people suggested that since PHP 5.3 has a new GC, the following should be used:
unset($connection);
I need to know once and for all, which one is preferred, or are they the same?
They do the same thing. Unsetting the $pdo handle and setting it null both close the connection.
You can test this for yourself. Run the following script in one window, and in a second window open the MySQL client and run SHOW PROCESSLIST every couple of seconds to see when the connection disappears.
<?php
$pdo = new PDO(..);
sleep(10);
unset($pdo);
echo "pdo unset!\n";
sleep(10);
Then change unset($pdo) to $pdo=null; and run the test again.
<?php
$pdo = new PDO(..);
sleep(10);
$pdo = null;
echo "pdo set null!\n";
sleep(10);
The extra sleep() at the end is there to give you a moment to see that the connection has dropped, before the PHP script terminates (which would drop the connection anyway).
I stumbled with this. I have a PDO object that spans setup and teardown, and I can't find where there must be a remaining reference, as setting $pdo to null did not resolve the problem.
User Contributed Notes in http://php.net/manual/en/pdo.connections.php discusses the problem of delayed closure. Here they suggest killing the current connection:
$pdo->query('SELECT pg_terminate_backend(pg_backend_pid());');
$pdo = null;
This is for postgres. For mysql I have used:
$pdo->query('KILL CONNECTION CONNECTION_ID();');
using
$pdo = null; //is an assignment to null; the variable still declared in the memory.
but
unset($pdo); // will call the function to distroy also the adress "#" pointed by the variable.
so using unset is prefered.
Just don't bother with closing at all. PHP will close it for you all right.
Note that of course your application have to be sanely designed, without the need of reconnecting to different databases at a rate of machine-gun. And even in latter case, the method you are using to close would be the least problem. You are barking wrongest tree ever. Work the number of connections, not the way you are closing them.

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.

Categories