I thought all the pg_* functions return false on error and it is your job to check it. However, as indicated below, my server is outputting an error message to the PHP log. How can I prevent this from happening because I obviously don't want these messages polluting the log as I deal with these kind of exceptions by checking the query result object's error code.
Warning: pg_query_params(): Query failed: ERROR: duplicate key value violates unique constraint "email" DETAIL: Key (email)=(email#example.com) already exists. in /xxx.php on line 100
From the point of view of PHP, there are at least two ways to avoid the error message, one that is "quick and dirty", and the other one more complicated but clean.
Solution #1: add a # sign before the call to mute any error message
#pg_query_params($db, $query, $params);
The drawback is that there'll be no log whatever the reason of the failure.
Solution #2: use pg_send_query_params(), process the error code, check that it is an expected error and ignore it only in this case, otherwise raise the error. Sample code:
if (pg_send_query_params($db, $query, $params)) {
$res=pg_get_result($db);
if ($res) {
$state = pg_result_error_field($res, PGSQL_DIAG_SQLSTATE);
if ($state==0) {
// success
}
else {
// an error happened
if ($state=="23505") { // unique_violation
// process or ignore expected error
}
else {
// process other errors
trigger_error (pg_last_error(), E_USER_ERROR);
}
}
}
}
else {
trigger_error ("pg_send_query_params failed:".pg_last_error(), E_USER_ERROR);
}
In both cases, there will be a trace of the error in the PostgreSQL error log unless you've muted it there too, but that's a separate problem that is generally solved by using a server-side INSERT with error trapping in procedural code rather than client-side.
Related
If I use a bit of code like this:
$update_result = mysqli_query( $link , $sql_update_login ) or die ('Unable to execute query. '. mysqli_error($link));
Does it have to die or can you put a different query afterwards? Like a predetermined function that writes a log of the error to another table? Such as:
$update_result = mysqli_query( $link , $sql_update_login ) or function('$query, $error);
What are the other options after 'or'? I haven't found it in the documentation, any clues are appreciated.
Does it have to die
Quite contrary, it shouldn't or die() ever.
PHP is a language of bad heredity. Very bad heredity. And or die() with error message is one of the worst rudiments:
die throws the error message out, revealing some system internals to the potential attacker
such error message confuses casual users, because they don't understand what does it mean
Besides, die kills the script in the middle, leaving users without familiar interface to work with, so they'd likely just drop out
it kills the script irrecoverably. While exceptions can be caught and gracefully handled
die() gives you no hint of where the error has been occurred. And in a relatively big application it will be quite a pain to find.
So, never use die() with MySQL errors, even for the temporary debugging: there are better ways.
Instead of manually checking for the error, just configure mysqli to throw exceptions on error, by adding the following line to your connection code
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
and after that just write every mysqli command as is, without any or die or anything else:
$result = mysqli_query($link, $sql);
This code will throw an exception in case of error and thus you will always be informed of every problem without a single line of extra code.
A more detailed explanation on how to make your error reporting production ready, uniform and overall sensible while making your code much cleaner, you can find in my article on PHP error reporting.
or is just an operator (very similar to ||).
The or die() syntax works because or short-circuits, which means that if the first statement is true, True or X will always be true, so X isn't evaluated and your script doesn't die.
Yes, you can provide a different function after the (or).
I have tested the following:
mysqli_query($sel_db,'what!') or some_func(mysqli_error($sel_db));
function some_func($str) {
die("ERROR: ".$str);
}
It doesn't have to be die() specifically, but it needs to be something that'll make the script halt by calling exit() or die(), or something that throws an exception. Otherwise, the script will continue with the return value of that function (which is probably either null or some sort of junk) in $update_result, which will almost certainly cause problems.
I am working for a while now with the SOAP API (self teached during work projects). But one thing always bothers me, is that I can't figure out how to handle an empty response.
For instance: I call the service to get some articles from an ERP system. The input parameter is the article number or the GTIN.
Here is some sample code: https://codeshare.io/5e3EYr
If for instance no GTIN is set (just for understanding) the response is not an array anymore (single or multidimensional). The return would be a soap error like "Fatal error: Cannot use string offset as an array" Because the return is the error message.
I hope you understand my problem. I already tried to check if it is_array and even tried to catch the string. But I always get the "Fatal error: Cannot use string offset..." message.
Something like ( as an example for my comment )
function handleShutdown(){
$lasterror = error_get_last();
if (is_null($lasterror)) {
//normal shutdown
return false;
}
//return error to client as XML, JSON etc.
// $lasterror['message']
// $lasterror['type']
// $lasterror['file']
// $lasterror['line']
}
register_shutdown_function('handleShutdown');
I will leave it up to you on how you want to format the error message. The shutdown handler can even catch out of memory errors ... :)
Obviously, you cant catch anything before it's registered so do it early in execution.
php.net/manual/en/function.register-shutdown-function.php
You may also want to look at
set_error_handler
set_exception_handler
Then you can have the trifecta of error handling.
You could use set_error_handler to catch these but you would want to filter out errors of certain verities (in the error handler), an example would be Deprecated or Notice level errors. You can do this with checking the Severity against the error_reporting level you have (bitwise) like this
if($severity & error_reporting())
//report on these errors.
Notice the single & is a bitwise comparison and differs from the normal AND (&&)
Now if you want to prevent the error altogether, I would need to see the code (including the line - marked somehow) where it is produced. Otherwise it's just wild guessing.
In any case when building some kind of service that lacks the normal GUI, it never hurts to have shutdown recovery to send feedback to the client, just make sure to sanitize any output information you share with clients. That way you don't "leak" information that may give away any information that could be used to compromise your application.
cheers.
Finally I figured out, which part to check for an array. If it is not an array, nothing happens. And if, everything is fine.
if(is_array(['getSomeArticleResult']['SqlRowSet']['diffgram']['SqlRowSet1'])){
$aSuppl = $aSuppl['getSomeArticleResult']['SqlRowSet']['diffgram']['SqlRowSet1']['row'];
return $aSuppl;
}
I have had a few nerve racking days trying to get a good error handling system in place within my site.
My error handling system is only focusing on unexpected errors e.g. mysqli errors
My site runs many mysqli queries meaning there is potential for errors to occur.
There is 3 parts to my system, and every one I am unsure on its place in best practices as well as efficiency.
Step 1 : catching the error
$query = "
SELECT * FROM `users_account_activations` WHERE `user_ip` =?
";
$statement = $databaseHandler->mysqli->prepare($query);
$statement->bind_param('s', $userIp);
$statement->execute();
$statement->store_result();
//record error, if any
$databaseHandler->mysqli->error ? error = true : error = false;
Is this a good way of catching the presents of an error somewhere in a prepared statement?
Will looking for errors at the end of the query not catch a error say in the prepare stage? or when the prepare stage fails all other fails (like falling dominoes)
Step 2 : recording the error
error_log("Could not process query...", 3, 'log/default.log');
Is this a suitible way of recording a error? as aposed to the systems that opens a file steam?
Step 3 : handling the after math
Now that there is a error I need to decide on how to move forward, my system intails exiting the script and going to a standard error page saying "opps! something went wrong".
header('location: errorpage.php'); exit();
is changing the header a good way of doing this? I am aware of the limitation of header regarding when you can use it.
Is there a better way for handing errors, this system is intended for unexpected errors. Expected errors are took care of and displayed to the users a different way.
Yes, you are right with your doubts - all the three steps are wrong.
First, for some very strange reason you are not recording the error message itself. How it is supposed to fix the error without error message? What's the use of logging something like "Could not process query..."?
Next, you have to check the result of every operation - so, prepare have to be checked too.
Next, it will be hard to spot the error without knowing where it happened. Some debug backtrace have to be included in the error message.
Next, there shouldn't be a Location header but just Status:500. So, instead of redirecting to error page, just include it.
Finally, all the aforementioned tasks have to be performed in a single place, namely - in the function registered as a custom error handler
So, the scenario have to be like this
in your bootstrap file create a code like this
set_error_handler("myErrorHandler");
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
error_log("$errstr in $errfile:$errline");
header('HTTP/1.1 500 Internal Server Error', TRUE, 500);
readfile("500.html");
exit;
}
then, make your mysqli code like this
$stmt = $mysqli->prepare("qwefq") or trigger_error($mysqli->error);
and have all your errors logged
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
This question already has answers here:
PHP Error handling: die() Vs trigger_error() Vs throw Exception
(2 answers)
Closed 2 months ago.
For example, my usage would be:
$check = 'no';
if($check == 'yes') {
//do stuff
} else {
die('Error found');
}
Many developer's what i seen use:
if($check == 'yes') {
//do stuff
} else {
throw new Exception('Error found.');
}
Which one method is 'better' ?
Any benefit's throwing an exception instead of stoping executing script ?
Which one method is 'better' ?
This depends on your needs. It can't be said which one is better (and there are other ways of error handling as well you should put into consideration when you actually want to discuss error handling which this site is probably not the right place for).
Any benefit's throwing an exception instead of stoping executing script ?
An exception can be caught, a die can't be caught. If you want to test your code for example, dies are often a show-stopper.
Next to that an exception can carry more information and carry it more precisely. The message for example is more accessible with an exception than it is with a die. An exception keeps the file and line where it was thrown. For debugging there are stack traces and so on.
Exceptions are better (in design of large sites), because:
They don't stop script immediately (you've got a chance to inform user in nice 5xx page about internal server error)
If you decide to handle error differently in the future you can do so without modifying original code
Exceptions provide backtrace and ease up debugging
I'm not sure, but destructors shouldn't be called when die is used (exceptions provide option to execute them)
You may create lot of Exceptions types, each for different kind of error and handle them easily later
You should use die probably only in smaller scripts and pages where you don't need to style error for use or in case of fatal error (cannot include main library into index or something like that).
You can use both, throw new Exception if some exceptional situation occurs (database connection or query, page or file not found...), and then catch it where that suits you. Then maybe log error to file, send mail to administrator and then use die("Some textual message to user.");. If you don't want to use die() you can show user some 404 not found or 500 internal error page.