在类中为特定异常子类

时间:2016-02-03 16:13:45

标签: php php-5.4

我在PHP项目中有一个简单的类,它在构造函数中使用类似下面的内容:

    @set_exception_handler(array($this, 'exception_handler'));

问题是,它在全球范围内捕获异常,例如:完全与类完全无关的异常。

是否可以限制此类的例外范围,这些范围仅由此类的实例和/或特定的异常子类抛出,例如:MyClassException

2 个答案:

答案 0 :(得分:2)

您不能仅为自己的异常设置异常处理程序。所有处理程序都在全球范围内工作。但是,您可以创建自己的异常处理程序链并控制所有异常。

<?php

interface ExceptionHandlerInterface
{
    public function supports(\Exception $e);
    public function handle(\Exception $e);
}

class ExceptionHandler implements ExceptionHandlerInterface
{
    public function supports(\Exception $e)
    {
        return $e instanceof \Exception;
    }

    public function handle(\Exception $e)
    {
        throw $e;
    }
}

class MyExceptionHandler implements ExceptionHandlerInterface
{
    public function supports(\Exception $e)
    {
        return $e instanceof MyException;
    }

    public function handle(\Exception $e)
    {
        exit("Oops, this is a my exception.\n");
    }
}

class ExceptionHandlerChain
{
    private $handlers;

    public function addHandler(ExceptionHandlerInterface $handler, $priority)
    {
        // you should sort all handlers with priority
        $this->handlers[] = $handler;
    }

    public function handle(\Exception $e)
    {
        foreach ($this->handlers as $handler) {
            if ($handler->supports($e)) {
                $handler->handle($e);
            }
        }
    }
}


class MyException extends \Exception
{
}

$chain = new ExceptionHandlerChain();
$chain->addHandler(new MyExceptionHandler(), 0);
$chain->addHandler(new ExceptionHandler(), 1024);

set_exception_handler([$chain, 'handle']);

//throw new RuntimeException();
throw new MyException();

答案 1 :(得分:0)

正如我在上面的评论中所说,你不能以某种方式将全局异常处理程序限制为特定的异常类型或事件。

但是,您可以使用phps魔法__call()方法来实现类似的功能,而无需在所有类方法中使用普通try...catch块。考虑这个简单的例子:

<?php

class myException extends Exception {}

class myClass
{
  public function __call($funcName, $funcArgs)
  {
    try {
      if (method_exists($this, '_'.$funcName)) {
          $this->_myFunction($funcArgs);
      }
    } catch (myException $e) {
      var_dump($e->getMessage());
    }
  }

  public function _myFunction($args)
  {
      throw new myException('Ooops');
  }
}

$myObj = new myClass;
$myObj->myFunction();

这里的输出显然是:

string(5) "Ooops"

这里有三点需要指出:

  1. “普通”方法(例如_myFunction() }必须实施try...catch
  2. 捕获的异常可以限于某些类型,并且可以在对象范围内处理
  3. 未注册全局异常处理程序,因此不会捕获全局异常。
  4. 然而,这种设置的一个巨大缺点是,IDE无法支持此类方法链,因此您无法自动完成并且没有对象方法的签名帮助。