Is it possible to catch exception and continue execution of script?
Is it possible to catch exception and continue execution of script?
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.
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.
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.
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.
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();
For PHP 8+ we can omit the variable name for a caught exception.
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) {}
You can, but I will warn: many consider this method quite evil.
// https://stackoverflow.com/a/66377817/578023
function is_same(&$a, &$b): bool {
$_ = [ &$a, &$b ];
return
\ReflectionReference::fromArrayElement($_, 0)->getId() ===
\ReflectionReference::fromArrayElement($_, 1)->getId();
}
function attempt_risky_action($collection){
$cursor=NULL;
$resuming = false;
resume:
try{
foreach($collection as $item){
if($resuming && !is_same($cursor,$item) ){
continue; // some things have better ways to skip ahead, especially an array index
}
else {
$resuming = false;
$cursor=&$item; // main concept is to remember where you are in the iteration
} // in some situation you may have to use references, &item
// your normal loop here
.
.
.
}
} catch( Exception $e){
$resuming = repair_something($e, $collection); // returns false if your repair ran out of ideas
if($resuming)
goto resume;
}
unset($cursor);
}
Ideally it would be best to wrap the unset($cursor); call in a finally{} block, but frankly I'm not sure how that plays with goto off hand.
If it executes because goto broke the flow then you will need some conditional logic, so the cursor still exists. If you have a return statement inside the loop you must use a finally block for call to unset($cursor) -- or cause a memory leak.
Then again, while less exciting, you can do this same trick by just nesting your whole loop in do{ try/catch } while($resuming). While that is not LITERALLY reversing your execution, it does exactly the same effect without risking a goto.
is_same() from https://stackoverflow.com/a/66377817/578023
function attempt_risky_action($collection){
$cursor=NULL;
$resuming = false;
do{
try{
foreach($collection as $item){
if($resuming && !is_same($cursor,$item) ){
continue;
}
else {
$resuming = false;
$cursor=&$item;
}
// your loop here
}
} catch( Exception $e){
$resuming = repair_something($e, $collection); // returns false if your repair ran out of ideas
}
finally{
if(!$resuming){
unset($cursor);
}
}
} while($resuming);
}
A last method, not pictured; you can use PHP's
reset(), prev(), current(), next(), end() faculties
These will allow you instead to simply have your try/catch block inside a code block that iterates as a loop would -- then use prev() in the catch to try again.