Good Programming Practice regarding Exception Handling - php

Consider a function hierarchy, Function Four() Calls Three() which calls Two() Which again calls One() to do the job:
Function One($x) {
if(!is_int($x)) {
throw Exception("X must be integer");
}
// .......... Do the Job ................
}
Function Two($x) {
if(!is_int($x)) {
throw Exception("X must be integer");
} else {
One($x);
}
}
Function Three($x) {
if(!is_int($x)) {
throw Exception("X must be integer");
} else {
Two($x);
}
}
Function Four($x) {
if(!is_int($x)) {
throw Exception("X must be integer");
} else {
Three($x);
}
}
If I call four with a String value it will cause an Exception to occure.
Now consider following code with Exception in parent function only.
Function One($x) {
if(!is_int($x)) {
throw Exception("X must be integer");
}
// .......... Do the Job ................
}
Function Two($x) {
One($x);
}
Function Three($x) {
Two($x);
}
Function Four($x) {
Three($x);
}
Here, I call Four() and pass a string, it will also cause an Exception to occure.
So which one is the best practice and why?
When I start writing code I end up writing a lot of exception handling, plz help.

If the functionality in function one needs $x and that is the only function that uses $x you can throw the exception only in function one. I assume function two, three and four will also do other things (otherwise they are useless). In that case you should check the value also in those functions. If they do not already use $x they may do in the future. In that case it is easy to forget to check the $x value and a bug is born.

IME it's good practice to fail as close to the problem as possible. That being said, I think option 1 is the way to go. This makes it so that when the exception occurs, you have confidence that it was the call to Four that was the problem and you can debug from there. Option 2 is easy but you don't know if the problem lies in Four, Three, Two or One. As your software grows in complexity so will your time debugging.

an alternative, i would know the trace and you can use as
Function One($x) {
if(!is_int($x)) {
throw Exception("X must be integer");
}
// .......... Do the Job ................
}
Function Two($x) {
try
{
One($x);
}
catch(Exception $e)
{
throw $e;
}
}
Function Three($x) {
try
{
Two($x);
}
catch(Exception $e)
{
throw $e;
}
}
Function Four($x) {
try
{
Three($x);
}
catch(Exception $e)
{
throw $e;
}
}
in this case you can know where is the error start, and only 1 is_int check.

I think it depends largely on what the functions are meant to do.
If the value of x is critical to the function, then the exception should be handled in that function. If it is just used for passing parameters, then you can let it slip through to the last function.
I am not sure of how the engine evaluates the function processing, but mostly it will push its contents onto the stack and then make the necessary jump, which in turn causes delay, so better to incorporate the exception handling then and there, when the values are generated, rather than letting it flow uselessly till it is being used just to save useless processing time.
Generally an exception means you have wasteful computation. So model 1 will make sure you don't do so.
Server Processing is precious to all... :)

go here and you may find the answer:

Related

PHP: Exit Function by a Function Called Within The Function to be Exited

I'm looking for a smarter/shorter way of doing the following:
function main() {
if (!otherfunction()) {
return; // exit main function
}
doMoreStuff();
...
}
Instead, I want the exit in the "main" function to be determined by a function called within the "main" function, like this:
function main() {
otherfunction(); // exit main function depending on what's going on in otherfunction()
doMoreStuff();
...
}
Oh-dear-oh-dear-oh-dear-oh-dear - pardon my $#x! here. I hope, you understand what I mean. If so, feel free to propose a better way to describe it.
You can't return out of a function from the inner one. You have to capture some of the control flow in some manner within main(). You have a few options for doing this.
First, you could use an if statement as you've outlined above:
function main() {
if(!otherFunction()) {
return;
}
doMoreStuff();
}
This approach is perfectly acceptable and is very readable. I use this simple approach frequently in my own production code.
Second, you could use exceptions and try/catch control:
function main() {
try {
otherFunction(); // May throw an exception if you want to exit early.
doMoreStuff();
} catch(Exception $e) {
// Do nothing; just catch the exception and allow the rest of main() to finish.
}
}
// Alternatively
function main() {
otherFunction();
doMoreStuff();
}
try {
main();
} catch(Exception $e) {
// Do nothing; silently fail.
}
This isn't particularly recommended, but is a valid option available to you.
Lastly, you can use short-circuit evaluation of conditional expressions:
function main() {
otherFunction() && doMoreStuff(); // if otherFunction() returns a non-"truthy" value, then doMoreStuff() won't execute.
}
This is also a perfectly valid approach that you'll frequently see in shell scripting for one-liners.
My personal recommendation is to keep the simple early-return pattern using the if statement as your intentions are clear and it's easy to add additional functionality. The other options will work, but your intentions won't be as clear and it may become more difficult to add functionality to your program. Ultimately the decision is yours to make, however.
You can use exit on otherFunction() based on an if statement, if you are willing to end the execution of the entire PHP script, like so:
function doMoreStuff()
{
echo 'Test';
}
function otherfunction()
{
if(some condition) {
exit;
}
}
function main() {
otherfunction();
doMoreStuff();
}
In that case, if the condition returns true it will terminate the current script, or else it will echo 'Test', which is the output of doMoreStuff() function.
Is this what you want to achieve?

all purpose try/catch block method

In the PHP project I'm working on there are several methods that make use of individual try/catch blocks. Here is one example:
public function getListData()
{
$clauses['filter'] = '';
$clauses['sort'] = 'CAST(propertyID AS INT) DESC';
try
{
return $this->getModel()->getListData($clauses);
}
catch (Exception $e)
{
// create an Error() object, send $e->getMessage() to it
}
}
Now, keeping in mind there are several similar methods, it would seem more efficient to write a method in the Model class that would look like this:
public function run($method)
{
try
{
return $this->$method;
}
catch (Exception $e)
{
//create an Error() object, send $e->getMessage() to it
}
}
The problem is calling it. This does not work:
public function getListData()
{
return $this->getModel()->run('getListData($clauses)');
}
The error is:
Undefined property:
classes\utility\Model::$getListData($clauses).
Is there a way to get this to work?
I'm going to assume that the first and second getListData() methods are in separate classes, otherwise you are calling a loop, since getListData would call getListData...which would call, you get it.
However, the way you are calling the method is incorrect in the run() method. It should be called using call_user_func. It is a callback to the method, not a call to the property, of the class.
You could call it statically using
public function run($method, $data)
{
try
{
return call_user_func(array($this, $method), $data);
}
catch (Exception $e)
{
//create an Error() object, send $e->getMessage() to it
}
}
public function getListData()
{
return $this->getModel()->run('getListData', $clauses);
}
There are several problems with this approach:
It prevents you from listening for custom exceptions
You can throw exceptions other than Exception, but this type of wrapper will make it much more difficult to do so.
It is difficult to follow the execution flow
When you pass method names and parameters around as strings, it becomes much harder for humans, IDEs and code analysis tools to understand what the program will do at runtime.
Try/catch blocks are cheap
The code required to catch exceptions is very simple and easy to use. This wrapper adds more complexity and more cost (an extra function call).
Consider just using try/catch blocks where needed instead of using the wrapper. If you have fifty similar methods as described in your comment above, you may gain more efficiency by eliminating the duplicate business logic and combining those methods.
You could simply convert errors to exceptions using this code:
set_error_handler(function ($errno, $errstr, $errfile, $errline)
{
if ((error_reporting() & $errno) === $errno)
throw new \Exception("$errstr ($errfile: $errline)", (int) $errno);
}, -1);
After it any error would be converted to exception.

Standard PHP error function with __LINE__ __FILE__etc?

so, instead of lots of instances of
if (odbc_exec($sql))
{
}
else
{
myErrorHandlingFunction();
}
I wrap that in a function
function myOdbxExec($sql)
{
if (odbc_exec($sql))
{
}
else
{
myErrorHandlingFunction();
}
}
BUT I would like myErrorHandlingFunction() to report things like __LINE__ __FILE__ etc
Which looks like I have to pass thoses infos to every call of helper functions, e.g. myOdbxExec($sql, __FILE__, __LINE__) which makes my code look messy.
function myErrorHandlingFunction($errorTExt, $fiel, $line)
{
// error reporting code goes here
}
function myOdbxExec($sql, $file, $line)
{
if (odbc_exec($sql))
{
}
else
{
myErrorHandlingFunction();
}
}
$sql = 'select * from ... blah, blah, blah...';
myOdbxExec($sql, __FILE__, __LINE__); // <==== this is *ugly*
In C I would hide it all behind a #define, e.g. #define MY_OFBC_EXEC(sql) myOdbxExec(sql, __FILE__, __LINE__)
1) (how) can I do that in PHP
2) what else is worth outoputting? e.g. error_get_last()? but that has no meaning if odbc_exec() fails ...
To rephrase the question - what's the generic approach to PHP error handling? (especially when set_error_handler() doesn't really apply?
Edit: just to be clear - I do want to handle exceptions, programming errors, etc, but, as my example shows, I also want to handle soemthings the teh PHP interpreter might noit consider to be an error, like odbc_exec() returning false().
Both the above answers mentioning debug_backtrace are answering your _______LINE_____ / _______FILE___ question with the debug_backtrace() function. I've wanted this answer too in the past, so have put together a quick function to handle it.
function myErrorHandlingFunction($message, $type=E_USER_NOTICE) {
$backtrace = debug_backtrace();
foreach($backtrace as $entry) {
if ($entry['function'] == __FUNCTION__) {
trigger_error($entry['file'] . '#' . $entry['line'] . ' ' . $message, $type);
return true;
}
}
return false;
}
You can then call, for instance, myErrorHandlingFunction('my error message');
or myErrorHandlingFunction('my fatal error message', E_USER_ERROR);
or try { ... } catch (Exception $e) { myErrorHandlingFunction($e->getMessage()); }
First off, you might want to consider using exception handling.
If for some reason, that doesn't appeal to you, you can use debug_backtrace inside your generic error handler to figure out where the handler was called from.
EDIT In response to OP's comment:
Exceptions don't have to come from PHP built-ins. You can throw your own. Since an ODBC error generally is an exceptional condition, just throw an exception when you detect one. (And catch it at some higher level).
<?PHP
if (! odbc_exec($sql) )
throw new DatabaseException('odbc_exec returned false, that bastard!');
Use debug_backtrace to figure out where a function was called from in your error handler. Whether you invoke this error handler by manually calling it, by throwing and catching exceptions, PHPs error_handler or any other method is up to the application design and doesn't really differ that much from other languages.

How can I get around the lack of a finally block in PHP?

PHP prior to version 5.5 has no finally block - i.e., whereas in most sensible languages, you can do:
try {
//do something
} catch(Exception ex) {
//handle an error
} finally {
//clean up after yourself
}
PHP has no notion of a finally block.
Anyone have experience of solutions to this rather irritating hole in the language?
Solution, no. Irritating cumbersome workaround, yes:
$stored_exc = null;
try {
// Do stuff
} catch (Exception $exc) {
$stored_exc = $exc;
// Handle an error
}
// "Finally" here, clean up after yourself
if ($stored_exc) {
throw($stored_exc);
}
Yucky, but should work.
Please note: PHP 5.5 finally (ahem, sorry) added a finally block: https://wiki.php.net/rfc/finally (and it only took a few years... available in the 5.5 RC almost four years to the date since I posted this answer...)
The RAII idiom offers a code-level stand-in for a finally block. Create a class that holds callable(s). In the destuctor, call the callable(s).
class Finally {
# could instead hold a single block
public $blocks = array();
function __construct($block) {
if (is_callable($block)) {
$this->blocks = func_get_args();
} elseif (is_array($block)) {
$this->blocks = $block;
} else {
# TODO: handle type error
}
}
function __destruct() {
foreach ($this->blocks as $block) {
if (is_callable($block)) {
call_user_func($block);
} else {
# TODO: handle type error.
}
}
}
}
Coordination
Note that PHP doesn't have block scope for variables, so Finally won't kick in until the function exits or (in global scope) the shutdown sequence. For example, the following:
try {
echo "Creating global Finally.\n";
$finally = new Finally(function () {
echo "Global Finally finally run.\n";
});
throw new Exception;
} catch (Exception $exc) {}
class Foo {
function useTry() {
try {
$finally = new Finally(function () {
echo "Finally for method run.\n";
});
throw new Exception;
} catch (Exception $exc) {}
echo __METHOD__, " done.\n";
}
}
$foo = new Foo;
$foo->useTry();
echo "A whole bunch more work done by the script.\n";
will result in the output:
Creating global Finally.
Foo::useTry done.
Finally for method run.
A whole bunch more work done by the script.
Global Finally finally run.
$this
PHP 5.3 closures can't access $this (fixed in 5.4), so you'll need an extra variable to access instance members within some finally-blocks.
class Foo {
function useThis() {
$self = $this;
$finally = new Finally(
# if $self is used by reference, it can be set after creating the closure
function () use ($self) {
$self->frob();
},
# $this not used in a closure, so no need for $self
array($this, 'wibble')
);
/*...*/
}
function frob() {/*...*/}
function wibble() {/*...*/}
}
Private and Protected Fields
Arguably the biggest problem with this approach in PHP 5.3 is the finally-closure can't access private and protected fields of an object. Like accessing $this, this issue is resolved in PHP 5.4. For now, private and protected properties can be accessed using references, as Artefacto shows in his answer to a question on this very topic elsewhere on this site.
class Foo {
private $_property='valid';
public function method() {
$this->_property = 'invalid';
$_property =& $this->_property;
$finally = new Finally(function () use (&$_property) {
$_property = 'valid';
});
/* ... */
}
public function reportState() {
return $this->_property;
}
}
$f = new Foo;
$f->method();
echo $f->reportState(), "\n";
Private and protected methods can be accessed using reflection. You can actually use the same technique to access non-public properties, but references are simpler and more lightweight. In a comment on the PHP manual page for anonymous functions, Martin Partel gives an example of a FullAccessWrapper class that opens up non-public fields to public access. I won't reproduce it here (see the two previous links for that), but here is how you'd use it:
class Foo {
private $_property='valid';
public function method() {
$this->_property = 'invalid';
$self = new FullAccessWrapper($this);
$finally = new Finally(function () use (&$self) {
$self->_fixState();
});
/* ... */
}
public function reportState() {
return $this->_property;
}
protected function _fixState() {
$this->_property = 'valid';
}
}
$f = new Foo;
$f->method();
echo $f->reportState(), "\n";
try/finally
try blocks require at least one catch. If you only want try/finally, add a catch block that catches a non-Exception (PHP code can't throw anything not derived from Exception) or re-throw the caught exception. In the former case, I suggest catching StdClass as an idiom meaning "don't catch anything". In methods, catching the current class could also be used to mean "don't catch anything", but using StdClass is simpler and easier to find when searching files.
try {
$finally = new Finally(/*...*/);
/* ... */
} catch (StdClass $exc) {}
try {
$finally = new Finally(/*...*/);
/* ... */
} catch (RuntimeError $exc) {
throw $exc
}
Here is my solution to the lack of finally block. It not only provides a work around for the finally block, it also extends the try/catch to catch PHP errors (and fatal errors too). My solution looks like this (PHP 5.3):
_try(
//some piece of code that will be our try block
function() {
//this code is expected to throw exception or produce php error
},
//some (optional) piece of code that will be our catch block
function($exception) {
//the exception will be caught here
//php errors too will come here as ErrorException
},
//some (optional) piece of code that will be our finally block
function() {
//this code will execute after the catch block and even after fatal errors
}
);
You can download the solution with documentation and examples from git hub -
https://github.com/Perennials/travelsdk-core-php/tree/master/src/sys
As this is a language construct, you won't find an easy solution for this.
You can write a function and call it as the last line of your try block and last line before rethrowing the excepion in the try block.
Good books argues against using finally blocks for any other than freeing resource as you can not be sure it will execute if something nasty happens. Calling it an irritating hole is quite an overstatement.
Believe me, a hell lot of exceptionally good code is written in languages without finally block. :)
The point of finally is to execute no matter if the try block was successfull or not.
function _try(callable $try, callable $catch, callable $finally = null)
{
if (is_null($finally))
{
$finally = $catch;
$catch = null;
}
try
{
$return = $try();
}
catch (Exception $rethrow)
{
if (isset($catch))
{
try
{
$catch($rethrow);
$rethrow = null;
}
catch (Exception $rethrow) { }
}
}
$finally();
if (isset($rethrow))
{
throw $rethrow;
}
return $return;
}
Call using closures. Second parameter, $catch, is optional. Examples:
_try(function ()
{
// try
}, function ($ex)
{
// catch ($ex)
}, function ()
{
// finally
});
_try(function ()
{
// try
}, function ()
{
// finally
});
Properly handles exceptions everywhere:
$try: Exception will be passed to $catch. $catch will run first, then $finally. If there is no $catch, exception will be rethrown after running $finally.
$catch: $finally will execute immediately. Exception will be rethrown after $finally completes.
$finally: Exception will break down the call stack unimpeded. Any other exceptions scheduled for rethrow will be discarded.
None: Return value from $try will be returned.
If anyone is still keeping track of this question, you might be interested in checking out the (brand new) RFC for a finally language feature in the PHP wiki. The author already seems to have working patches, and I'm sure the proposal would benefit from other developers' feedback.
I just finished writing a more elegant Try Catch Finally class which may be of use to you. There are some drawbacks but they can be worked around.
https://gist.github.com/Zeronights/5518445

correct way of using a throw try catch error handling

I have come accross to this function below and I am wondering wether this is the right way of using the error handling of try/catch.
public function execute()
{
$lbReturn = false;
$lsQuery = $this->msLastQuery;
try
{
$lrResource = mysql_query($lsQuery);
if(!$lrResource)
{
throw new MysqlException("Unable to execute query: ".$lsQuery);
}
else
{
$this->mrQueryResource = $lrResource;
$lbReturn = true;
}
}
catch(MysqlException $errorMsg)
{
ErrorHandler::handleException($errorMsg);
}
return $lbReturn;
}
Codewise it is correct/works, However the power of try-catch is that when an Exception is thrown from deep down in one of the functions you're calling.
Because of the "stop execution mid-function and jump all the way back to the catch block".
In this case there are no deep-down exceptions therefore I would write it like this:
(Assuming there is a function "handleErrorMessage" in the ErrorHandler.)
public function execute() {
$lsQuery = $this->msLastQuery;
$lrResource = mysql_query($lsQuery);
if(!$lrResource) {
ErrorHandler::handleErrorMessage("Unable to execute query: ".$lsQuery);
return false;
}
$this->mrQueryResource = $lrResource;
return true;
}
Which I find more readable.
No. Throwing an exception in this case is simply a GOTO, but with a (slightly) prettier face.
Why have a call to ErrorHandler::handleException here anyway?
Just throw the exception, but never catch it. Then in the global initialization code for your app have a function with the following signature:
function catchAllExceptions(Exception $e)
Then call:
set_exception_handler('catchAllExceptions');
This will cause all uncaught excpetions to be passed as an argument to catchAllExceptions(). Handling all uncaught exceptions in one place like this is good, as you reduce code replication.
Well it is not really a good implementation since you throw the exception and you look for that exception in catch. So the answer of Visage is true.
You should use a global error handler instead of a tr-catch usage like in your code.
If you are not sure of the type of the error and occurance but want to continue the execution of the code although an exception had occured, then a try-catch block will help.

Categories