Dom*_*rto 225 php exception-handling
我想一个更清洁的方式来获得以下功能,捕捉AError和BError在一个块:
try
{
/* something */
}
catch( AError, BError $e )
{
handler1( $e )
}
catch( Exception $e )
{
handler2( $e )
}
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?或者我必须单独抓住它们?
AError并且Berror有一个共享的基类,但是它们也与我想要的其他类型共享它handler2,所以我不能只捕获基类.
Mir*_*ate 304
从PHP 7.1开始,这是可用的.
语法是:
try
{
// Some code...
}
catch(AError | BError $e)
{
// Handle exceptions
}
catch(Exception $e)
{
// Handle the general case
}
Run Code Online (Sandbox Code Playgroud)
https://wiki.php.net/rfc/multiple-catch
https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a
尽管这些什么其他的答案说,你可以赶上AError并BError在同一个块(这是比较容易,如果你是一个定义例外).即使你有想要"落伍"的例外情况,你仍然可以定义一个符合你需求的层次结构.
abstract class MyExceptions extends Exception {}
abstract class LetterError extends MyExceptions {}
class AError extends LetterError {}
class BError extends LetterError {}
Run Code Online (Sandbox Code Playgroud)
然后:
catch(LetterError $e){
//voodoo
}
Run Code Online (Sandbox Code Playgroud)
正如您在此处和此处所看到的,即使是SPL默认异常也可以使用您可以利用的层次结构.另外,如PHP手册中所述:
抛出异常时,不会执行语句后面的代码,PHP将尝试查找第一个匹配的catch块.
这意味着你也可以拥有
class CError extends LetterError {}
Run Code Online (Sandbox Code Playgroud)
你需要处理不同于AError或者BError,让你的catch语句应该是这样的:
catch(CError $e){
//voodoo
}
catch(LetterError $e){
//voodoo
}
Run Code Online (Sandbox Code Playgroud)
如果你遇到了二十个或更多合法属于同一个超类的异常的情况,并且你需要以一种方式处理五个(或任何大型组),而另一个则处理其余的,你仍然可以这样做.
interface Group1 {}
class AError extends LetterError implements Group1 {}
class BError extends LetterError implements Group1 {}
Run Code Online (Sandbox Code Playgroud)
然后:
catch (Group1 $e) {}
Run Code Online (Sandbox Code Playgroud)
在涉及异常时使用OOP非常强大.使用像get_class或者instanceof是黑客的东西,如果可能的话应该避免使用.
我想添加的另一个解决方案是将异常处理功能放在自己的方法中.
你可以有
function handleExceptionMethod1(Exception $e)
{
//voodoo
}
function handleExceptionMethod2(Exception $e)
{
//voodoo
}
Run Code Online (Sandbox Code Playgroud)
假设是绝对没有办法,你可以控制的异常类层次结构或接口(也有几乎总是将是一个方法),你可以做到以下几点:
try
{
stuff()
}
catch(ExceptionA $e)
{
$this->handleExceptionMethod1($e);
}
catch(ExceptionB $e)
{
$this->handleExceptionMethod1($e);
}
catch(ExceptionC $e)
{
$this->handleExceptionMethod1($e);
}
catch(Exception $e)
{
$this->handleExceptionMethod2($e);
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,如果您的异常处理机制需要更改,并且您正在OOP的常规构造中工作,那么您仍然只需要修改一个代码位置.
ale*_*lex 228
在PHP的最新版本中,这是可能的.请参阅以下答案.
如果您可以修改例外,请使用此答案.
如果你不能,你可以尝试捕获所有,Exception然后检查抛出了哪个异常instanceof.
try
{
/* something */
}
catch( Exception $e )
{
if ($e instanceof AError OR $e instanceof BError) {
// It's either an A or B exception.
} else {
// Keep throwing it.
throw $e;
}
}
Run Code Online (Sandbox Code Playgroud)
但是如前面的答案所述,使用多个catch块可能会更好.
try
{
/* something */
}
catch( AError $e )
{
handler1( $e );
}
catch ( BError $b )
{
handler2( $e );
}
Run Code Online (Sandbox Code Playgroud)
Joe*_*ins 88
即将在PHP 7.1是捕获多种类型的能力.
这样:
<?php
try {
/* ... */
} catch (FirstException $ex) {
$this->manageException($ex);
} catch (SecondException $ex) {
$this->manageException($ex);
}
?>
Run Code Online (Sandbox Code Playgroud)
和
<?php
try {
} catch (FirstException | SecondException $ex) {
$this->manageException($ex);
}
?>
Run Code Online (Sandbox Code Playgroud)
功能相同.
han*_*rik 42
从PHP 7.1开始,
catch( AError | BError $e )
{
handler1( $e )
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,您还可以:
catch( AError | BError $e )
{
handler1( $e )
} catch (CError $e){
handler2($e);
} catch(Exception $e){
handler3($e);
}
Run Code Online (Sandbox Code Playgroud)
在早期版本的PHP中:
catch(Exception $ex){
if($ex instanceof AError){
//handle a AError
} elseif($ex instanceof BError){
//handle a BError
} else {
throw $ex;//an unknown exception occured, throw it further
}
}
Run Code Online (Sandbox Code Playgroud)
小智 25
本文讨论的问题是electrictoolbox.com/php-catch-multiple-exception-types.直接从文章中复制的帖子内容:
例外情况
以下是为此示例定义的一些示例异常:
class FooException extends Exception
{
public function __construct($message = null, $code = 0)
{
// do something
}
}
class BarException extends Exception
{
public function __construct($message = null, $code = 0)
{
// do something
}
}
class BazException extends Exception
{
public function __construct($message = null, $code = 0)
{
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
处理多个异常
它非常简单 - 可以抛出每个异常类型的catch块:
try
{
// some code that might trigger a Foo/Bar/Baz/Exception
}
catch(FooException $e)
{
// we caught a foo exception
}
catch(BarException $e)
{
// we caught a bar exception
}
catch(BazException $e)
{
// we caught a baz exception
}
catch(Exception $e)
{
// we caught a normal exception
// or an exception that wasn't handled by any of the above
}
Run Code Online (Sandbox Code Playgroud)
如果抛出的异常没有被任何其他catch语句处理,它将由catch(Exception $ e)块处理.它不一定是最后一个.
smi*_*x96 21
作为已接受答案的扩展,您可以切换Exception的类型,从而产生与原始示例有点相似的模式:
try {
// Try something
} catch (Exception $e) {
switch (get_class($e)) {
case 'AError':
case 'BError':
// Handle A or B
break;
case 'CError':
// Handle C
break;
case default:
// Rethrow the Exception
throw $e;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您无法控制定义异常,那么这是一个合理的替代方案.使用异常变量的名称可以在捕获异常时对异常进行分类.然后在try/catch块之后检查异常变量.
$ABError = null;
try {
// something
} catch (AError $ABError) { // let the exception fall through
} catch (BError $ABError) { // let the exception fall through
} catch (Exception $e) {
handler2($e);
}
if ($ABError) {
handler1($ABError);
}
Run Code Online (Sandbox Code Playgroud)
如果catch块实现之间存在大量重复,那么这种有点奇怪的方法可能是值得的.
从 PHP 8.0 开始,当您不需要输出错误内容(来自变量$e)时,您可以使用更干净的方式来捕获异常。但是您必须将默认值替换Exception为Throwable.
try {
/* something */
} catch (AError | BError) {
handler1()
} catch (Throwable) {
handler2()
}
Run Code Online (Sandbox Code Playgroud)