php:捕获异常并继续执行,有可能吗?

新手上路,请多包涵

是否可以捕获异常并继续执行脚本?

原文由 Kirzilla 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 623
2 个回答

当然,只需捕获要继续执行的异常…

 try
{
    SomeOperation();
}
catch (SomeException $ignored)
{
    // do nothing... php will ignore and continue
    // but maybe use "ignored" as name to silence IDE warnings.
}

当然,这有一个问题是默默地丢弃可能是一个非常重要的错误。 SomeOperation() 可能会失败,从而导致其他微妙的、难以解决的问题,但你永远不会知道你是否默默地放弃了异常。

原文由 Doug T. 发布,翻译遵循 CC BY-SA 4.0 许可协议

你可以,但我会警告:许多人认为这种方法非常邪恶。

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

}

理想情况下,最好将 unset($cursor); 调用包装在 --- finally{} 块中,但坦率地说,我不确定如何使用 goto 副手。

如果它执行是因为 goto 中断了流程,那么您将需要一些条件逻辑,因此游标仍然存在。如果循环中有 return 语句,则 必须 使用 finally 块来调用 unset($cursor) 或导致内存泄漏。

再说一次,虽然不那么令人兴奋,但您可以通过将整个循环嵌套在 do{ try/catch } while($resuming) 中来实现同样的技巧。虽然这并没有从字面上扭转您的执行,但它的效果完全相同,而且不会冒 goto 的风险。

is_same() 来自 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);
}

最后一种方法,未图示; you can use PHP’s reset() , prev() , current() , next() , end() faculties

这些将允许您简单地将您的 try/catch 块放在一个代码块中,该代码块作为循环进行迭代 - 然后在 catch 中使用 prev() 再次尝试。

原文由 That Realty Programmer Guy 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏