Resume PHP to execution script after exception

First of all one should make clear that an exception is only fatal if it is not caught. Catching an exception does not halt script execution. It merely stops the stack frame in the try block and transfers control to the catch block. From there your script will continue to execute as normal.

By catching the exception here we still resume normal script execution after the exception is caught...

try {
  echo "Try...\n";
  throw new Exception("This is an exception");
} catch(Exception $e) {
  echo "Exception caught with message: " . $e->getMessage() . "\n";
}

echo "Script is still running...";

There's another way to handle uncaught exceptions, using an exception handler. However if you don't use a try and catch statement, execution flow will still be halted. This is the nature of exceptions:

function myExceptionHandler($e) {
  echo "Uncaught exception with message: " , $e->getMessage(), "\n";
}

set_exception_handler('myExceptionHandler'); // Registers the exception handler

throw new Exception("This is Exception 1");
echo "Execution never gets past this point";
throw new Exception("This is Exception 2");
throw new Exception("This is Exception 3");

Edit: After clarifying your question I think that I should state what you want is not an exception handler, but you actually don't want to use Exceptions at all. What you're trying to do does not require throwing Exceptions at all. Don't put PDO into exception mode if what you intend to do is just handle the error like that. Exception should only be used to handle exceptional errors. The whole point of an exception is to make sure you keep your promise. For example, if your function makes the promise that it will always return a PDOStatement object and there is a case where it can not possibly do that, then it makes sense to throw an Exception. This lets the caller know that we have reached a point where we can not keep our promise.

What you want is basic error handling...

function someCode(){
        $pdostmt = $this->prepare($this->sql);
        if($pdostmt->execute($this->bind) !== false) {
            if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql))
                return $pdostmt->fetchAll($this->fetchOption);
            elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql))
                return $pdostmt->rowCount();
        } else {
           return false;
        }
}

while (someCode() === false) {
  /* Call someCode() until you get what you want */
}

Use php 4/5 register_shutdown_function.

Doc here: http://php.net/manual/en/function.register-shutdown-function.php


I am going to assume that you are unable to handle the exception in the function it is being thrown. If you want to resume where your exception was thrown you need to handle the exception there. Anything else is bad coding resulting in confusion for you or anyone else working on the project. We let exception go up the tree because we can't handle them in the function it self because of scope issues.

As to your example which I will expand upon. You say operation can't continue because connection cannot happen. In reality we don't want to blatantly retry the function because we will essentially create a hang point of continuously trying the connection so we use a catch block higher up the tree where we can notify the user and have them decide what we want to do. In so doing we can use catch blocks in the right places to save data so we can restore the data and execute it at a later time. In reality we want to wind-up at a point before the try block.

This will give you a much clearer execution path. Sometimes you have to rethink a function/method so that it does one thing and one thing correctly.

To put the answer to your question simply and bluntly. No, Its a bad idea to call the try(ed) function in the catch block and the simple reason is this you no long have a try block to catch an exception there. Exceptions bring more meaningful error handling then just passing true and false as a return. However, it does mean that you have to go around the full circle in handling them.

Now for an alternate example... Say we have multiple servers that we can connect to and you wanted to run thought the list you would put the try/catch inside a loop and the catch will check for that exception and do any clean up before executing the next loop. If any other exception occurs we will (re)throw the exception. The right way to achieve what your looking for would be like this.

function someCode() {
    $pdostmt = $this->prepare($this->sql);

    while($status == false) {
        try {
            $status = $pdostmt->execute($this->bind)

        } catch (PDOException $e) {
            if($e->getMessage("What ever the error message is") {
                //Fix it here
            } else {
                throw $e;
            }
        }
    }
    //Do other stuff
    return $data; //or true/false
}

Tags:

Php

Try Catch