异常后将PHP恢复到执行脚本

时间:2012-12-19 15:17:44

标签: php try-catch

我有一个php脚本让我们说在执行过程中脚本会引发异常。我希望我的PHP从它停止的地方恢复(抛出异常的地方)。

我应该将相同的执行代码放在代码的“catch”部分吗?

例如,假设连接到mySQL失败,连接超时

   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();
   }
   try {
        someCode();
        }   
    } catch (PDOException $e) {  
        //re-execute same code as within the try clause?
        someCode();
    }

4 个答案:

答案 0 :(得分:25)

首先,应该明确一个异常只有在未被捕获时才会致命。捕获异常会暂停脚本执行。它只是停止try块中的堆栈帧并将控制转移到catch块。从那里你的脚本将继续正常执行。

通过捕获异常,我们仍然会在捕获到异常后恢复正常的脚本执行...

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...";

使用exception handler还有另一种处理未捕获异常的方法。但是,如果不使用try和catch语句,则仍将暂停执行流程。这是例外的本质:

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");

编辑:在澄清您的问题后,我认为我应该说明您想要的不是异常处理程序,但实际上您根本不想使用异常。你要做的事情根本不需要抛出异常。如果您打算做的只是处理这样的错误,请不要将PDO置于异常模式。异常仅应用于处理异常错误。一个例外的重点是确保你遵守诺言。例如,如果您的函数承诺它将始终返回PDOStatement对象,并且存在无法执行此操作的情况,那么抛出异常是有意义的。这让来电者知道我们已经达到了不能信守承诺的程度。

你想要的是基本的错误处理......

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 */
}

答案 1 :(得分:3)

使用php 4/5 register_shutdown_function。

Doc在这里:http://php.net/manual/en/function.register-shutdown-function.php

答案 2 :(得分:3)

我将假设你无法处理它被抛出的函数中的异常。如果要恢复抛出异常的位置,则需要在那里处理异常。其他任何东西都是糟糕的编码,导致您或其他任何从事该项目的人感到困惑。我们让异常上升,因为由于范围问题我们无法在自己的函数中处理它们。

关于我将扩展的例子。你说操作无法继续,因为连接不会发生。实际上我们不想公然重试这个功能,因为我们实际上会创建一个连续尝试连接的挂点,所以我们在树的上方使用一个catch块,我们可以通知用户让他们决定我们想做什么。这样,我们可以在正确的位置使用catch块来保存数据,这样我们就可以恢复数据并在以后执行它。实际上,我们希望在try块之前的某个点结束。

这将为您提供更清晰的执行路径。有时你必须重新考虑一个函数/方法,以便它能正确地完成一件事和一件事。

简单坦率地回答你的问题。不,在catch块中调用try(ed)函数是一个坏主意,原因很简单,你不会有一个try块来捕获异常。异常带来更有意义的错误处理,然后只传递true和false作为返回。但是,它确实意味着您必须绕过整个循环来处理它们。

现在换一个例子......假设我们有多个服务器可以连接到你想运行的思想列表你将把try / catch放在一个循环中,catch会检查那个异常并做任何在执行下一个循环之前清理。如果发生任何其他异常,我们将(重新)抛出异常。实现你想要的东西的正确方法就是这样。

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
}

答案 3 :(得分:0)

如果在执行过程中不会出现异常,您可以使用try catch的finally部分。

try {
  // some crashing code
} catch (Exception $e) {
  //some catch code
} finally {
  //code that will run anyways.
}
相关问题