【问题标题】:Handle exception and continue executing处理异常并继续执行
【发布时间】:2017-04-18 06:29:33
【问题描述】:

[编辑 - 免责声明:这是一个非常糟糕的主意,请参阅实际解决方案的公认答案。]

我使用 set_exception_handler() 函数定义了我自己的异常处理程序。处理程序执行后,我需要脚本继续。有什么办法吗?

免责声明:我知道 try-catch 块,但我需要动态处理异常。每次调用 Clazz::foo() 都会指定自己的异常,这些异常应该被我的处理程序捕获。这就是我不能使用它的原因。

例子:

class Clazz {

    private static $exceptions;

    public static function foo(array $exceptions) {
        set_exception_handler(array(__CLASS__, "exception_handler"));
        self::$exceptions = $exceptions;
        throw new RandomException;
        echo "I need this to be printed!";
    }

    public static function exception_handler($exception) {
        // process the exception in my way...
        // if $exception in self::$exceptions than 1, else 2, fi
        restore_exception_handler();
        // continue in some way, like it has never happenned
    }

}

【问题讨论】:

  • 我不明白,你能说明你的需求吗?
  • 这看起来你根本不懂异常。这只是个坏主意......
  • 可以设置事件中介对象,将其注入自定义异常处理程序类,注册自定义异常处理程序类的可调用对象set_exception_handler 并拥有一个完整的侦听器链来侦听未捕获的异常事件。虽然我不确定这会是一个多么好的主意......
  • 你苦苦挣扎的原因是这不是异常的工作方式,因为这不是异常的意思。停止尝试以这种方式使用它们。只需调用一些函数即可。
  • 我很乐意毫无例外地处理它。但是, foo() 函数应该启动自定义代码(来自库),它会抛出异常,我无法更改它。

标签: php exception-handling callback


【解决方案1】:

在你的启动文件中做这样的事情

/**
 * Set the default exception handler.
 *
 * @param Exception $exception The exception to handle
 */
$handler = function(Exception $exception)
{
    //print $exception;
};

set_exception_handler($handler);

/**
 * Register the PHP error handler. All PHP errors will fall into this
 * handler, which will convert the error into an ErrorException object
 * and pass the exception into the common exception handler.
 *
 * After all, there should never be any errors in our application. If
 * there are then we need to know about them and fix them - not ignore
 * them.
 *
 * Notice, this function will ignore the error if it is less than the
 * current error reporting level.
 */
set_error_handler(function($code, $error, $file, $line) use ($handler)
{
    if((error_reporting() & $code) === 0) return TRUE;

    $handler(new ErrorException($error, $code, 0, $file, $line));
});

/**
 * Register the PHP shutdown handler. This function will be called
 * at the end of the PHP script or on a fatal PHP error. If an error
 * has occured, we will convert it to an ErrorException and pass it
 * to the common exception handler for the framework.
 */
register_shutdown_function(function() use ($handler)
{
    if($error = error_get_last())
    {
        extract($error, EXTR_SKIP);
        $handler(new ErrorException($message, $type, 0, $file, $line));
    }
});


/**
 * Setting the PHP error reporting level to -1 essentially forces PHP to
 * report every error, and is guranteed to show every error on future
 * versions of PHP. This will insure that our handlers above are
 * notified about everything.
 */
error_reporting(-1);

/**
 * At the same time we want to disable PHP's default error display since
 * we are now using our own.
 */
ini_set('display_errors', 'Off');

【讨论】:

    【解决方案2】:

    这只是个坏主意。我只是希望您不了解Exceptions 的工作原理,并且您不是在问这个问题。

    首先,设置异常处理程序...Exception handler 在异常传播到主脚本(实际上是在其中)时调用,因此您的脚本已完成:

    如果在 try/catch 块中未捕获到异常,则设置默认异常处理程序。 在调用 exception_handler 后将停止执行

    您应该使用Xeoncross suggesting,但我认为您对抛出异常的调用函数/方法有问题,因此您可以这样做:

    class Clazz {
    
        private static $exceptions;
    
        public static function foo(array $exceptions) {
            set_exception_handler(array(__CLASS__, "exception_handler"));
            self::$exceptions = $exceptions;
            try {
                throw new RandomException;
            } catch( Exception $e){
                self::exception_handler( $exception);
            }
            echo "I need this to be printed!";
        }
    
        public static function exception_handler(Exception $exception) {
        }
    }
    

    【讨论】:

    • 感谢您的回答。这要简单得多,我还有一个愚蠢的想法……这解决了我的问题,因为我可以捕获所有异常,然后在需要时再次抛出其中一些异常。
    • @PavelS。异常处理程序的问题是......它应该什么时候采取行动?函数何时结束?父函数何时完成?主脚本何时完成?它认为依赖异常处理程序只是不好的做法......无论如何,如果你想用更少的代码,你可以这样做:1)在所有方法名称前加上_,2)用:@实现方法__call($name,$args) 987654328@
    【解决方案3】:

    不。 幸运的是没有办法做到这一点

    【讨论】:

    • '幸运'?当您必须使用引发异常的第 3 方库时,请再说一遍。即使你有一个成熟的、庞大的应用程序可以处理第 3 方库遇到的任何问题,你的整个应用程序仍然会停止运行。
    • @unity100:是的,幸运的是。我对此没有任何问题。 (包括巨大的应用程序)。我更喜欢我的代码正常工作,而不是抛出异常而是继续执行 broken data(这可能是你更喜欢的)
    • 是的,您希望您的代码能够正常工作。现在将 google 的 php 客户端库推到您的应用程序中以执行某些操作。然后你会看到异常是多么令人恼火。当谷歌返回任何错误时,他们的代码会引发异常 - 即使您可以尝试将用户发送到另一个登录名,地狱,甚至尝试使用谷歌重新授权,也会导致您的代码消失。不好。
    • @unity100:“当谷歌返回任何错误时,他们的代码会引发异常”——这正是我真正期望的。如果发生了一些错误 - 我不希望错误传播,我希望库抛出异常并让我的代码能够处理它。
    • 错误“传播”是什么意思?当他们的库抛出异常时,您的整个应用程序就会死在您的面前。他们不给你的代码处理它的能力——执行就停在那里,在你(或用户)的脸上有一个丑陋的异常消息。您所能做的就是创建一个通用的异常处理函数并美化消息,或者修改关闭处理函数以将它们重定向到其他地方。这就是你能做的。
    【解决方案4】:

    一般来说,这是一个坏主意,因为抛出异常的代码期望后面的任何代码都不会执行,我猜这就是它没有在 php 中实现的原因。

    但也许这可能有助于做你想做的事:

    function try_throw($exception) {
        if (!Clazz::exception_handler($exception))
            throw($exception);
    
    }
    
    class Clazz {
    
        private static $exceptions;
    
        public static function foo(array $exceptions) {
            set_exception_handler(array(__CLASS__, "exception_handler"));
            self::$exceptions = $exceptions;
            try_throw(new RandomException);
            echo "I need this to be printed!";
        }
    
        public static function exception_handler($exception) {
            // process the exception in my way...
            // if $exception in self::$exceptions than 1, else 2, fi
            return true;
            // continue in some way, like it has never happenned
            // to instead throw the exception the normal way
            return false;
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-07-26
      • 2019-09-05
      • 2015-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多