How to gracefully die? - php

So I've just read Why to never use 'or die'.
I am more confused then ever. I am validating a complicated form and I go though many nested levels of if statements and what not and I am passing a variable to the form which is called $status which can only be 'new' or 'edit'. Then when the user submits the form to be validated again the form passes along the $status value as a hidden field ($_POST). I want to make sure that the user cannot accidentally change this so I want to catch the error should something other than 'new' or 'edit' pass though. (Although I would like to completely eliminate the possibility of the user affecting this variable in an ideal world.)
So I figured that I would use DIE() in an if statement
<nested ifs>
Select ($status){
Case 'edit':
break;
Case 'new':
break;
default:
//using example from article
trigger_error("An error that should not occur has occurred", E_USER_ERROR);
break;
}
</nested ifs>
I don't really understand how this is cleaner than die()? Essentially I would like to call another function which displays the user some options of what they can do at this juncture to fix the error, but I want the code to absolutely stop running as I don't want an if statement further down to continue parsing anything and generating an error when it finds something other than 'new' or 'edit'.
I'm not sure how clear I am so please feel free to ask me to elaborate on any unclear points.
(or better yet, can a hidden user field get hacked? How to prevent? :P)

trigger_error() triggers an error which is handled by an error handler.
With trigger_error() you can gracefully handle errors, for example:
set_error_handler('ErrorHandler');
function ErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
print '<pre style="line-height: 2em;">';
printf("==> Error in `%s' line %s: %s\n\n", $filename, $linenum, $errmsg);
debug_print_backtrace();
print '</pre>';
exit($errno);
}
This is a simple example, but our company website displays a friendly error page and sends me an email that I'm an idiot and messed up somewhere :-)
The advantage over die() or exit() should be clear :-)
exit() can still be used when you need to exit. For example when you generate a template, output that, and want code execution to stop. Or when you send a header('Location: ...'); header and want to make sure the execution stops ... Just don't use it for handling unexpected situations (i.e. errors).
trigger_error() also gives you a better degree of control. You can send E_USER_NOTICE when you want execution to stop but display a notice, and E_USER_ERROR when you want execution to stop.
In addition, you can write more complex error handler functions where some IP's see a error, and the rest do not ... Kindda useful for development.
Be a but careful with overly complicated error handlers though, what happens is an error occurs inside an error handler ... ? You may have seen Inception :)

The article you linked to explains why you shouldn't use or die, as in:
$result = mysql_query($query) or die('A MySQL query occurred: ' . mysql_error());
Obviously this is a bad idea, as it could output sensitive information about your MySQL structure to a malicious user.
However, I think there is nothing wrong (and I think the writer of the article would agree with me) to use die in the way you are using it, although presenting the user with a list of options would, indeed, be the preferred way to handle this.

Related

Uncalled function throws 'mysqli_stmt object is not fully initialized' uncaught error [duplicate]

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.

SOAP empty envelope. How to handle empty responses

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;
}

custom error handling system efficiency

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

How to propery finish a PHP page after an exception is thrown and caught?

I am working on my first major PHP/MySQL application. I use the Exception handling mechanism to handle possible DB errors. On some pages, I use several queries to obtain the relevant data from the database. The part of the page issuesn those queries is within one try-catch block and I write a customized error message in the catch block.
My problem: the queries are within different blocks on my page, and when a DB exception is thrown, processing immediately goes to the catch block and makes it not really possible to render the page in valid XHTML because in the catch block it is not known which XHTML tags should be closed.
I was thinking about redirecting to a custom error page showing the error mesage but this appears to be discouraged by some people. I think this should be a pretty trivial issue but wonder what is the recommended practice.
Hope for some hints!
1) Change the default error handler. Log them in a database
2) use output buffering
3) last line of your Catch{} block, have it do a header("location: error.html") redirect to a generic error handler.
You should use ob_start() to start buffering the output, and then you have finished to render all the HTML, use ob_flush() to send the HTML code back to the user.
If an error occured, you can generate a special page by calling ob_clean() to clean the buffer and then display your error page.
Exemple :
ob_start();
echo "My title";
try{
$myDB = Database::getInstance();
$userName = $myDB->query("SELECT name FROM user"); // send an exception
echo "Welcome ".$userName;
} catch (Exception $e) {
ob_clean();
echo "Error, please try again";
}
ob_flush();
I'm shure that DB query error is mostly debug enviroment issue or code error. I also prefer to validate and escape values in DB query before running it and show validation result, when it failed.
So, if DB exception even appeared, i log it (using simple error_log, including full request data, get, post, url, referrer) and show 500 error page without any redirect. I think, that redirect is a bad practice - you can't refresh page and repeat error, visitors and QA can't send you invalid page link.
I used the ob_Start(), ob_flush() and ob_clean() method and it does what I excepted so I keep using this.
I will wonder whether this is considered as good practice, IMHO generating invalid XHTML should always be avoided.
Of course an error in the query is a bug and one can argue whether this should be handled in the production code. But my guess is that in the future a lot of maintenance will be done and errors will be inevitable. And they should be presented as nice as possible and surely not in the form of a white blank screen...

php OOP Exceptions or die()?

I am developing some project. And I want to control different errors. I know that in all popular frameworks and php projects there are different Exceptions. But I think that is not required work. If the error is occured we can make die() with our message.
1. What are the main pluses of Exceptions?
2. Can I control my errors with die()?
Thank you.
Well, you could use die(). But that makes all errors fatal. Meaning that you cannot try to recover from the error at all. In some cases that's fine to do.
But in most cases, you may want the ability to "clean up" after the error, or to try another method. This is where exceptions come in handy... They let you chose where and if you want to handle the error. They let you try to gracefully recover from the errors.
For example, let's say you have a method which downloads a file from a remote server: downloadFromRemoteServer($address);
If you use die(), if the download fails, the script terminates. End of story.
But if you use exceptions, you could try another server or even try a different method (HTTP vs FTP, etc):
try {
$file = downloadFromRemoteServer('http://example.com/foo');
} catch (DownloadFailedException $e) {
try {
$file = downloadFromRemoteServer('http://secondtry.example.com/foo');
} catch (DownloadFailedException $e2) {
die('Could not download file');
}
}
return $file;
But remember that Exceptions are useful only for exceptional circumstances. They are not meant to be used for any possible error. For example, if a user doesn't verify their email address correctly, that's not exceptional. But if you can't connect to the database server, or have a conflict in the DB, that would be an exception circumstance...
Alexander,
die() and Exceptions accomplish different things.
the "die" language construct just halts the execution of a script and possibly outputs the parameters if it has been called like a function.
On the other hand, exceptions are more advanced structures that are used in OOP contexts to give the developer more flexibility as to whether a script needs to be stopped and if so, in what manner, what output to be shown to the user etc.
Exceptions are a little bit more complex than this so you should perhaps document yourself with some OOP first or for that matter read about zend framework and you'll get a grasp of what Exceptions are.
For simple stuff though, you can always use exit (or die, which is the same thing).
I hope this helps,
Slavic
1 What are the main pluses of Exceptions?
The main advantages are:
failing functions don't have to pollute their return with error conditions
typed exceptions can be handled at appropriate levels in the code, you decide which portion of the code can handle which errors
you can store a lot more information about the error condition in the exception itself, making handling it, and possibly recovering from it, easier.
2 Can I control my errors with die()?
I'd hardly call it control, I'd call it giving up on actually handling an error. At no point in my projects is a die() actually user-friendly, and all those die('...some error condition...'); examples of PHP code are IMHO only suited for projects in development. In production, you'll want your users to be able to continue their tasks / programs in the easiest way possible, so a 'try again' (if error condition is not likely to be met again), 'sorry that doesn't work' / other kinds of messages, forms / pages are all more desirable then die().

Categories