php: catch exception and continue execution, is it possible?
PhpPhp Problem Overview
Is it possible to catch exception and continue execution of script?
Php Solutions
Solution 1 - Php
Yes but it depends what you want to execute:
E.g.
try {
a();
b();
}
catch(Exception $ignored){
}
c();
c()
will always be executed. But if a()
throws an exception, b()
is not executed.
Only put the stuff in to the try
block that is depended on each other. E.g. b
depends on some result of a
it makes no sense to put b
after the try-catch
block.
Solution 2 - Php
Sure, just catch the exception where you want to continue execution...
try
{
SomeOperation();
}
catch (SomeException $ignored)
{
// do nothing... php will ignore and continue
// but maybe use "ignored" as name to silence IDE warnings.
}
Of course this has the problem of silently dropping what could be a very important error. SomeOperation() may fail causing other subtle, difficult to figure out problems, but you would never know if you silently drop the exception.
Solution 3 - Php
Sure:
try {
throw new Exception('Something bad');
} catch (Exception $e) {
// Do nothing
}
You might want to go have a read of the PHP documentation on Exceptions.
Solution 4 - Php
php > 7
use the new interface Throwable
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Handle exception
}
echo "Script is still running..."; // this script will be executed.
Solution 5 - Php
Yes.
try {
Somecode();
catch (Exception $e) {
// handle or ignore exception here.
}
however note that php also has error codes separate from exceptions, a legacy holdover from before php had oop primitives. Most library builtins still raise error codes, not exceptions. To ignore an error code call the function prefixed with @:
@myfunction();
Solution 6 - Php
For PHP 8+ we can omit the variable name for a caught exception.
> catch
>
> As of PHP 8.0.0, the variable name for a caught exception is optional. If not specified, the catch block will still execute but will not have access to the thrown object.
And thus we can do it like this:
try {
throw new Exception("An error");
}
catch (Exception) {}
Solution 7 - Php
Another angle on this is returning an Exception, NOT throwing one, from the processing code.
I needed to do this with a templating framework I'm writing. If the user attempts to access a property that doesn't exist on the data, I return the error from deep within the processing function, rather than throwing it.
Then, in the calling code, I can decide whether to throw this returned error, causing the try() to catch(), or just continue:
// process the template
try
{
// this function will pass back a value, or a TemplateExecption if invalid
$result = $this->process($value);
// if the result is an error, choose what to do with it
if($result instanceof TemplateExecption)
{
if(DEBUGGING == TRUE)
{
throw($result); // throw the original error
}
else
{
$result = NULL; // ignore the error
}
}
}
// catch TemplateExceptions
catch(TemplateException $e)
{
// handle template exceptions
}
// catch normal PHP Exceptions
catch(Exception $e)
{
// handle normal exceptions
}
// if we get here, $result was valid, or ignored
return $result;
The result of this is I still get the context of the original error, even though it was thrown at the top.
Another option might be to return a custom NullObject or a UnknownProperty object and compare against that before deciding to trip the catch(), but as you can re-throw errors anyway, and if you're fully in control of the overall structure, I think this is a neat way round the issue of not being able to continue try/catches.
Solution 8 - Php
An old question, but one I had in the past when coming away from VBA scipts to php, where you could us "GoTo" to re-enter a loop "On Error" with a "Resume" and away it went still processing the function.
In php, after a bit of trial and error, I now use nested try{} catch{} for critical versus non critical processes, or even for interdependent class calls so I can trace my way back to the start of the error.
e.g. if function b is dependant on function a, but function c is a nice to have but should not stop the process, and I still want to know the outcomes of all 3 regardless, here's what I do:
//set up array to capture output of all 3 functions
$resultArr = array(array(), array(), array());
// Loop through the primary array and run the functions
foreach($x as $key => $val)
{
try
{
$resultArr[$key][0][] = a($key);
$resultArr[$key][1][] = b($val);
try
{ // If successful, output of c() is captured
$resultArr[$key][2][] = c($key, $val);
}
catch(Exception $ex)
{ // If an error, capture why c() failed
$resultArr[$key][2][] = $ex->getMessage();
}
}
catch(Exception $ex)
{ // If critical functions a() or b() fail, we catch the reason why
$criticalError = $ex->getMessage();
}
}
Now I can loop through my result array for each key and assess the outcomes.
If there is a critical failure for a() or b().
I still have a point of reference on how far it got before a critical failure occurred within the $resultArr and if the exception handler is set correctly, I know if it was a() or b() that failed.
If c() fails, loop keeps going. If c() failed at various points, with a bit of extra post loop logic I can even find out if c() worked or had an error on each iteration by interrogating $resultArr[$key][2].