Cheking and error on a PHP function - php

There is a way to check with a "IF" if a function fails in php?
Ex.
If (getimagesize($image) returns and error) {
echo 'Error: function dont work';
}
else
{
// do something
}
Thanks!

I 'm assuming you are interested specifically in a function like getimagesize, which does not return any error codes and makes it hard on us. But not impossible.
The documentation for getimagesize states:
If accessing the filename image is impossible, or if it isn't a valid picture, getimagesize() will generate an error of level E_WARNING. On read error, getimagesize() will generate an error of level E_NOTICE.
Therefore, you need to do two things:
Get notified of the error and act upon it somehow
Have the error not be displayed or otherwise affect the execution of your program at all (after all, your are going to be taking care of any errors with error-handling code yourself)
You can achieve the first one using set_error_handler() and restore_error_handler(). You can achieve the second with the error-control operator #.
So, the code must go something like this:
// Set our own error handler; we will restore the default one afterwards.
// Our new error handler need only handle E_WARNING and E_NOTICE, as per
// the documentation of getimagesize().
set_error_handler("my_error_handler", E_WARNING | E_NOTICE);
// No error has occured yet; it is the responsibility of my_error_handler
// to set $error_occurred to true if an error occurs.
$error_occurred = false;
// Call getimagesize; use operator # to have errors not be generated
// However, your error handler WILL STILL BE CALLED, as the documentation
// for set_error_handler() states.
$size = #getimagesize(...);
// At this point, my_error_handler will have run if an error occurred, and
// $error_occurred will be true. Before doing anything with it, restore the
// previous error handler
restore_error_handler();
if($error_occurred) {
// whatever
}
else {
// no error; $size holds information we can use
}
function my_error_handler($errno, $errstr, $file, $line) {
global $error_occurred;
// If the code is written as above, then we KNOW that an error
// here was caused by getimagesize(). We also know what error it was:
switch($errno) {
case E_WARNING: // Access to image impossible, or not a valid picture
case E_NOTICE: // Read error
}
// We could also check what $file is and maybe do something based on that,
// if this error handler is used from multiple places. However, I would not
// recommend that. If you need more functionality, just package all of this
// into a class and use the objects of that class to store more state.
$error_occurred = true;
return true; // Do not let PHP's default error handler handle this after us
}
Of course, this is not very maintainable (you have a global variable $error_occurred there, and this is not a good practice). So for a solution which not only works but is also nicely engineered, you would package all this in a class. That class would define:
A method which implements the error handler (my_error_handler in the above example). To set an object method as an error handler instead of a global function, you need to call set_error_handler with a suitable first parameter; see the documentation for callback.
A method which lets the class set the error handler, execute some code of your choice, save the "error happened while executing your code" flag, and restore the error handler. This method could e.g. take a callback provided by your calling code and an array of parameters and use call_user_func_array to execute it. If, during execution, the error handler set from #1 above is called, mark this in a variable in your object. Your method would return the return value of call_user_func_array to the calling code.
A method or variable which the calling code can use to access the result from #2 above.
So then, if that class is called ErrorWatcher, your calling code would be something like:
$watcher = new ErrorWatcher;
$size = $watcher->watch("getimagesize",
array( /* params for getimagesize here */ ));
// $size holds your result, if an error did not occur;
// check for errors and we 're done!
switch($watcher->report_last_error()) {
// error handling logic here
}
...which is nice and neat and does not mess with global variables. I hope I explained this well enough to enable you to write class ErrorWatcher yourself. :-)

Take a look at exceptions. You'll have to throw them in your function though.
Edit: By the way, if your function is not supposed to return a boolean, you can always have it return false if something goes wrong and check like:
$result = getimagesize($image);
if ($result === false)
{
//
}

Whatever the condition is on an "if" statement (what's inside the parenthesis) will return "true" or "false".
If the condition returns "true", the first statement will be executed, otherwise the second statement will get executed.
You can put this, error_reporting(E_ALL); at the very top of your script, right after your opening php tag, to see what error you get.
Hope it helps.
Maybe something like this:
<?php
error_reporting(E_ALL);
more stuff here ...
if(your condition here){
echo "condition is true, do something";
}else{
echo "condition is not true, do something else";
}
if the function or statement you run inside the "if" or "else" fails, at least you know which one was it based on the result, and the error_reporting might tell you why it failed.

Related

How to count concurrent instances of a running function using PHP and MySQL? [duplicate]

Once i initiated a function i am setting a flag on DB to TRUE.
and i need to set it FALSE on the end of the function.
Ex:
Class Preprocessor extends Machine{
function process(){
$this->db->setValue(TRUE); //Setting DB flag to TRUE
//OTHER CODES
$this->close_db_value(); // Setting DB flag to FALSE
}
function close_db_value(){
$this->db->setValue(FALSE); //Setting DB flag to FALSE
}
}
As you can see that it will work in normal cases, But if some error encountered in //OTHER CODES section then it will not execute the rest of codes.
The function mainly work in background (But not as a command line,its just closing the connection and start executing on background).
How can i ensure that the close_db_value() function executed upon script termination ?
Some of possibilities
Some critical errors that which leads the script to termination
exit called somewhere on the //OTHER CODE section
PHP max_execution_time exceeded
A Force Kill
Please help.
Use the set_error_handler() function in PHP. Place the name of the callback function you want called in case of error as the first parameter. Put the level of error (optional) that you want as the trigger as the second parameter.
If you are looking to handle every other type of error (except SIGKILLs or force quits), you can also try using register_shutdown_function() with a error_get_last() and a switch-case statement with the various types of errors you wish to handle (E_NOTICE, E_DEPRECATED, etc.).
For example,
register_shutdown_function('shutdown_callback');
function shutdown_callback(){
$error_type = error_get_last();
switch($error_type){
case E_ERROR: break;
case E_WARNING: break;
}
}
The __destruct(); magic function will also execute every time the script ends, or an object is unloaded.

Function that checks if function executes successfully, otherwise exception. Possible in PHP?

I need some function that will accept a function as the parameter and will run it in try {} catch (Exception $e) {}. If it runs successfully, do nothing, otherwise, throw new Exception. That's something like function-checker, which checks functions if they ran successfully. Anybody can help me or give advice?
Thanks for any replies.
The function should work like that:
function itwillfail () {
echo 10 / 0;
}
check("itwillfail");
Output: Caught exception: Custom exception text here, because it has been thrown as custom.
("check" is that function I need)
What I tried:
function check($func) {
try {
call_user_func($func);
} catch (Exception $e) {
throw new Exception("Custom text here.");
}
}
EDIT: More explained: I need to create function, which do the same as "try" and a lot of different "catch"es for different types of exceptions.
Summarizing your question:
You want a way to call a custom function from a string variable (which you have already figured out that would be via call_user_func($var);.
You then want that function to throw a custom exception error
Confused
What is not clear is the reason you would opt to not define your error handler using the set_error_handler function which would effectively do what your asking and set a switch statement to output different messages based on the error generated.
Example
The following example is not using a call_user_func but it effectively allows you to write how the error will be handled
<?php
function myerror($error_no, $error_msg) {
echo "Error: [$error_no] $error_msg ";
echo "\n Now Script will end";
die();
}
// Setting set_error_handler
set_error_handler("myerror");
$a = 10;
$b = 0;
// Force the error
echo($a / $b);
?>
Not every function throws an exception when they fail. Many functions, especially ones that have been around for a long time, simply trigger PHP errors rather than exceptions.
To handle those, you would use a custom error handler:
https://www.php.net/manual/en/function.set-error-handler.php
So you could set up a custom error handler that would intercept those kinds of failures and throw them as exceptions. The whole point of that function is to do what you're trying to do - handle errors in a custom way.

Execute a function on error php

Once i initiated a function i am setting a flag on DB to TRUE.
and i need to set it FALSE on the end of the function.
Ex:
Class Preprocessor extends Machine{
function process(){
$this->db->setValue(TRUE); //Setting DB flag to TRUE
//OTHER CODES
$this->close_db_value(); // Setting DB flag to FALSE
}
function close_db_value(){
$this->db->setValue(FALSE); //Setting DB flag to FALSE
}
}
As you can see that it will work in normal cases, But if some error encountered in //OTHER CODES section then it will not execute the rest of codes.
The function mainly work in background (But not as a command line,its just closing the connection and start executing on background).
How can i ensure that the close_db_value() function executed upon script termination ?
Some of possibilities
Some critical errors that which leads the script to termination
exit called somewhere on the //OTHER CODE section
PHP max_execution_time exceeded
A Force Kill
Please help.
Use the set_error_handler() function in PHP. Place the name of the callback function you want called in case of error as the first parameter. Put the level of error (optional) that you want as the trigger as the second parameter.
If you are looking to handle every other type of error (except SIGKILLs or force quits), you can also try using register_shutdown_function() with a error_get_last() and a switch-case statement with the various types of errors you wish to handle (E_NOTICE, E_DEPRECATED, etc.).
For example,
register_shutdown_function('shutdown_callback');
function shutdown_callback(){
$error_type = error_get_last();
switch($error_type){
case E_ERROR: break;
case E_WARNING: break;
}
}
The __destruct(); magic function will also execute every time the script ends, or an object is unloaded.

Proper way to error handle

This is more of a architectural question. I like to know what people's opinion on how to properly handle errors in a fully Object Oriented PHP environment.
For example I have a class that retrieves all user data from the database. So I would use it in this way:
$userData = new UserDataConnection();
$userData->openDatabase();
$userData->retrieveData();
$userData->showData();
$userData->closeDatabase();
At each of these steps, an error could have potentially occurred. So would I return a boolean from each step stating whether the function has successfully executed (hence the error checking is within each function), or do I do a try-catch exception handling around the whole thing? or is there a better way?
Is it also better to always go to some kind of error page when some kind of error occur?
<?php
$ERROR = false;
try {
$userData = new UserDataConnection();
$userData->openDatabase();
$userData->retrieveData();
$DETAILS = $userData->showData();
$userData->closeDatabase();
} catch( Exception $e ) {
$ERROR = $e->getMessage(); // exit;
}
if( $ERROR ) {
$DETAILS = array();
}
?>
If you are using PDO you can throw a PDOException.
It typically boils down to a simple question:
May this function "legitimately" fail or is any failure a sign of something being really wrong?
If a function expects a certain kind of input and should never ever be called with a different kind of input, any failure to supply the correct input is an InvalidArgumentException. This is especially true for functions which do not directly handle user input. This works even better with type hinting.
If a function should always produce a certain result given the correct input, any failure of the function to produce that result is a RuntimeException or LogicException or some other kind of exception.
If a function may or may not produce some kind of result, false is a legitimate return value. Functions which deal with user input and therefore get very arbitrary input values are often fine with returning false.
Some examples:
getDatabaseConnection() is perfectly correct in throwing a RuntimeException or similar if it cannot establish a connection to the database. This is an exceptional circumstance in which case no work can continue.
transformFooIntoBar(Foo $foo) is correct in throwing some form of exception if it cannot return a Bar instance, for whatever reason that may be. The function has a clear purpose and a type checked input value. If it cannot do its job under such clear conditions, something is clearly wrong and must be fixed. Ergo, an exception.
checkIfUserExists($id) may well return false, because its job is to return a thumbs up or thumbs down. A user not existing is not an exceptional circumstance given this job description.
Where to catch a thrown exception depends on where you want to deal with it. Database connection errors should probably be caught at the very top of the call stack, since you probably cannot do anything if the database is down.
On the other hand, if some module is calling some submodule and half expects that submodule to fail and/or has a contingency plan in case it does fail, the module may catch the exception of the submodule and continue on doing its job. For instance getRSSUpdates() makes a call to a HTTP::fetchContents($url). If the URL returns a 404, the HTTP module may throw an exception, since it cannot return contents under these circumstances. The getRSSUpdates() function is prepared for this though and handles this case as "no updates at this time".

Why does PHP's "trigger_error" return true?

I use the error handling for my custom functions, and notice all three user error types (NOTICE, WARNING and ERROR) all return true.
I used the trigger_error function to escape a function when it has been incorrectly processed (eg. invalid data inserted). I thought the best way to escape the function is to use:
return trigger_error('Error notice here');
The problem is, errors return true. Although not all my functions return true upon success, it seems to me like this could be used in the future (hence, false would represent an error).
Is there a reason why this function would return true, or am I following bad practice in exiting invalid functions?
I know a solution for this could be:
trigger_error('Error notice here');
return false;
But I thought there would be a more elegant method. Hopefully there is, if not, some insight into best practices.
It returns TRUE because the operation of triggering the error was successful. It would be FALSE if you specified an invalid error type to the second argument.
If you want to return TRUE and trigger an error (which, by the way, makes no sense the way I see it) in one line you can do this:
return !trigger_error('Error notice here');
Incidentally, if you trigger an E_USER_ERROR I doubt the code that evaluates the return value would ever be reached, because the error would be fatal unless you have registered an error handler to catch it.
If you want to exit a function with an error message that you can handle in your code, you should use an Exception. Although whether these make sense in the context of a procedural function is highly debatable.
You asked about more elegant solutions than trigger_error().
I would suggest that a more elegant method might be to throw an exception instead of triggering an error.

Categories