php 在一个 catch 块中捕获多种异常类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8439581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Catching multiple exception types in one catch block
提问by Dominic Gurto
I'd like a cleaner way to obtain the following functionality, to catch AError
and BError
in one block:
我想要一种更简洁的方法来获得以下功能,以捕获AError
并BError
在一个块中:
try
{
/* something */
}
catch( AError, BError $e )
{
handler1( $e )
}
catch( Exception $e )
{
handler2( $e )
}
Is there any way to do this? Or do I have to catch them separately?
有没有办法做到这一点?还是我必须分别抓住它们?
AError
and Berror
have a shared base class, but they also share it with other types that I'd like to fall through to handler2
, so I can't just catch the base class.
AError
并且Berror
有一个共享的基类,但它们也与我想要落入的其他类型共享它handler2
,所以我不能只抓住基类。
回答by MirroredFate
Update:
更新:
As of PHP 7.1, this is available.
从 PHP 7.1 开始,这是可用的。
The syntax is:
语法是:
try
{
// Some code...
}
catch(AError | BError $e)
{
// Handle exceptions
}
catch(Exception $e)
{
// Handle the general case
}
Docs: https://www.php.net/manual/en/language.exceptions.php#example-287
文档:https: //www.php.net/manual/en/language.exceptions.php#example-287
RFC: https://wiki.php.net/rfc/multiple-catch
RFC:https: //wiki.php.net/rfc/multiple-catch
Commit: https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a
提交:https: //github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a
For PHP before 7.1:
对于 7.1 之前的 PHP:
Despite what these other answers say, you can catch AError
and BError
in the same block (it is somewhat easier if you are the one defining the exceptions). Even given that there are exceptions you want to "fall through", you should still be able to define a hierarchy to match your needs.
不管这些其他答案怎么说,你可以在同一个块中捕获AError
和BError
(如果你是定义异常的人,这会更容易一些)。即使考虑到您想要“通过”的例外情况,您仍然应该能够定义一个层次结构来满足您的需求。
abstract class MyExceptions extends Exception {}
abstract class LetterError extends MyExceptions {}
class AError extends LetterError {}
class BError extends LetterError {}
Then:
然后:
catch(LetterError $e){
//voodoo
}
As you can see hereand here, even the SPL
default exceptions have a hierarchy you can leverage. Additionally, as stated in the PHP Manual:
正如您在此处和此处所看到的,即使是SPL
默认异常也有您可以利用的层次结构。此外,如PHP 手册所述:
When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block.
当抛出异常时,语句后面的代码不会被执行,PHP 会尝试找到第一个匹配的 catch 块。
This means you could also have
这意味着你也可以拥有
class CError extends LetterError {}
which you need to handle differently than AError
or BError
, so your catch statement would look like this:
您需要以不同于AError
or 的方式处理它BError
,因此您的 catch 语句将如下所示:
catch(CError $e){
//voodoo
}
catch(LetterError $e){
//voodoo
}
If you had the case where there were twenty or more exceptions that legitimately belonged under the same superclass, and you needed to handle five (or whatever large-ish group) of them one way and the rest the other, you can STILL do this.
如果您遇到这样的情况,即有 20 个或更多异常合法地属于同一个超类,并且您需要以一种方式处理其中的 5 个(或任何大型组),其余的则以另一种方式处理,您仍然可以这样做。
interface Group1 {}
class AError extends LetterError implements Group1 {}
class BError extends LetterError implements Group1 {}
And then:
进而:
catch (Group1 $e) {}
Using OOP when it comes to exceptions is very powerful. Using things like get_class
or instanceof
are hacks, and should be avoided if possible.
在处理异常时使用 OOP 非常强大。使用像get_class
或instanceof
are hacks 之类的东西,如果可能的话应该避免。
Another solution I would like to add is putting the exception handling functionality in its own method.
我想添加的另一个解决方案是将异常处理功能放在自己的方法中。
You could have
你可以有
function handleExceptionMethod1(Exception $e)
{
//voodoo
}
function handleExceptionMethod2(Exception $e)
{
//voodoo
}
Assuming there is absolutely no way you can control exception class hierarchies or interfaces (and there almost always willbe a way), you can do the following:
假设是绝对没有办法,你可以控制的异常类层次结构或接口(也有几乎总是将是一个方法),你可以做到以下几点:
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);
}
In this way, you are still have a only single code location you have to modify if your exception handling mechanism needs to change, and you are working within the general constructs of OOP.
这样,如果您的异常处理机制需要更改,您仍然只有一个代码位置必须修改,并且您正在 OOP 的一般结构中工作。
回答by alex
In PHP >= 7.1 this is possible. See the answerbelow.
在 PHP >= 7.1 中这是可能的。请参阅下面的答案。
If you can modify the exceptions, use this answer.
如果您可以修改例外,请使用此答案。
If you can't, you could try catching all with Exception
and then check which exception was thrown with instanceof
.
如果你不能,你可以尝试捕获所有,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;
}
}
Butit would probably be better to use multiple catch blocks as described in aforementioned answer.
但是,如上述答案中所述,使用多个 catch 块可能会更好。
try
{
/* something */
}
catch( AError $e )
{
handler1( $e );
}
catch ( BError $b )
{
handler2( $e );
}
回答by Joe Watkins
Coming in PHP 7.1is the ability to catch multiple types.
即将在PHP 7.1是捕获多种类型的能力。
So that this:
所以这个:
<?php
try {
/* ... */
} catch (FirstException $ex) {
$this->manageException($ex);
} catch (SecondException $ex) {
$this->manageException($ex);
}
?>
and
和
<?php
try {
} catch (FirstException | SecondException $ex) {
$this->manageException($ex);
}
?>
are functionally equivalent.
在功能上是等效的。
回答by hanshenrik
As of PHP 7.1,
从 PHP 7.1 开始,
catch( AError | BError $e )
{
handler1( $e )
}
interestingly, you can also:
有趣的是,您还可以:
catch( AError | BError $e )
{
handler1( $e )
} catch (CError $e){
handler2($e);
} catch(Exception $e){
handler3($e);
}
and in earlier versions of PHP:
在早期版本的 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
}
}
回答by user1983902
This article covers the question electrictoolbox.com/php-catch-multiple-exception-types. Content of the post copied directly from the article:
本文涵盖了electrictoolbox.com/php-catch-multiple-exception-types的问题。直接从文章复制的帖子内容:
Example exceptions
示例异常
Here's some example exceptions that have been defined for the purposes of this example:
以下是为本示例目的而定义的一些示例异常:
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
}
}
Handling multiple exceptions
处理多个异常
It's very simple - there can be a catch block for each exception type that can be thrown:
这非常简单 - 每个可以抛出的异常类型都有一个 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
}
If an exception is thrown that is not handled by any of the other catch statements it will be handled by the catch(Exception $e) block. It does not necessarily have to be the last one.
如果抛出的异常未被任何其他 catch 语句处理,它将由 catch(Exception $e) 块处理。它不一定是最后一个。
回答by smix96
As an extension to the accepted answer, you could switch the type of Exception resulting in a pattern that is somewhat like the original example:
作为已接受答案的扩展,您可以切换 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;
}
}
回答by dellsala
Here's a reasonable alternative if you don't have control over defining the exceptions. Use the name of the exception variable to categorize the exceptions when they are caught. Then check for the exception variable after the try/catch block.
如果您无法控制定义异常,这是一个合理的选择。使用异常变量的名称对捕获的异常进行分类。然后在 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);
}
This somewhat odd looking approach is probably only worth it if there is a lot of duplication between catch block implementations.
这种看起来有些奇怪的方法可能只有在 catch 块实现之间存在大量重复时才值得。
回答by ml_
Besides fall-through, it's also possible to step over by using goto. It's very useful if you want to see the world burn.
除了失败,还可以使用goto跳过。如果你想看到世界燃烧,这非常有用。
<?php
class A_Error extends Exception {}
class B_Error extends Exception {}
class C_Error extends Exception {}
try {
throw new A_Error();
}
catch (A_Error $e) { goto abc; }
catch (B_Error $e) { goto abc; }
catch (C_Error $e) {
abc:
var_dump(get_class($e));
echo "Gotta Catch 'Em All\n";
}
回答by Frank Forte
A great way is to use set_exception_handler
.
一个很好的方法是使用set_exception_handler
.
Warning!!! with PHP 7, you might get a white screen of death for fatal errors. For example, if you call a method on a non-object you would normally get Fatal error: Call to a member function your_method() on null
and you would expect to see this if error reporting is on.
警告!!!使用 PHP 7,您可能会因致命错误而出现白屏死机。例如,如果你在一个非对象上调用一个方法,你通常会得到Fatal error: Call to a member function your_method() on null
,如果错误报告打开,你会期望看到这个。
The above error will NOT be caught with catch(Exception $e)
.
The above error will NOT trigger any custom error handler set by set_error_handler
.
上面的错误不会被 catch(Exception $e)
. 上述错误不会触发由set_error_handler
.
You must use catch(Error $e){ }
to catch errors in PHP7. .
This could help:
您必须使用catch(Error $e){ }
来捕获 PHP7 中的错误。. 这可以帮助:
class ErrorHandler{
public static function excep_handler($e)
{
print_r($e);
}
}
set_exception_handler(array('ErrorHandler','excep_handler'));
回答by GT.
Hmm, there are many solution written for php version lower than 7.1.
嗯,针对7.1以下的php版本写了很多解决方案。
Here is an other simple one for those who doesn't want catch all exception and can't make common interfaces:
对于那些不想捕获所有异常并且无法制作通用接口的人来说,这是另一个简单的方法:
<?php
$ex = NULL
try {
/* ... */
} catch (FirstException $ex) {
// just do nothing here
} catch (SecondException $ex) {
// just do nothing here
}
if ($ex !== NULL) {
// handle those exceptions here!
}
?>