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.
Related
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.)
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.
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.
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).
What is the "proper" way to deal with errors when manipulating a sql database with php?
What Im currently doing looks like this:
$connection = new mysqli('hostname', 'user', 'pass', 'database');
if ($connection->connect_errno) {
reportError("DB_CONNECTION_ERROR", $connection->connect_errno, $connection->connect_error);
displayError("DB_CONNECTION_ERROR");
}
$stmt = $connection->stmt_init();
$q = "query";
$stmt->prepare($q);
$stmt->bind_param('s', $username);
$stmt->execute();
reportError() is part of an error handling file I wrote and logs the error in a database
displayError() is part of the same file and tells the page what to display (as opposed to displaying the actual error).
However Im not sure of how to check for other errors, such as whether a statement was successfully prepared or whether a query was successful. Any recommendations appreciated!
Don't you find it quite odd to write database connection errors... into database?
I see also no point in having custom displayError() function. It should be generic _503() function, sending corresponding header along with general excuses.
I see no point in having custom logError() function either. PHP quite capable to log errors itself. trigger_error() serves me best.
Im not sure of how to check for other errors, such as whether a statement was successfully prepared
Ah, this one. Exceptions.
Mysqli should throw an exception if something went wrong. See mysqli_sql_exception for more details.
In your client code, you can then wrap your code in try/catch blocks:
try {
} catch (Exception $e) {
}
Sometimes, there are exceptions that can't be solved within a try/catch block, for example, the database server is down, and a site that is heavily reliant on the database would not be able to function anyway.
For those very critical problems, you can allow the exception to bubble upwards. You should then set an exception handler at the beginning of your script to catch those exceptions, notify the administrator and do some logging, then display an 500 error page to the user.