我想要一种更简洁的方法来获取以下功能,以便在一个块中捕获AError
和BError
:
try
{
/* something */
}
catch( AError, BError $e )
{
handler1( $e )
}
catch( Exception $e )
{
handler2( $e )
}
有没有办法做到这一点?或者我必须单独抓住它们?
AError
和Berror
有一个共享的基类,但是它们也与我想要传递给handler2
的其他类型共享它,所以我不能只抓住它基类。
答案 0 :(得分:260)
从PHP 7.1开始,这是可用的。
语法为:
try
{
// Some code...
}
catch(AError | BError $e)
{
// Handle exceptions
}
catch(Exception $e)
{
// Handle the general case
}
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 {}
然后:
catch(LetterError $e){
//voodoo
}
正如您可以看到here和here,即使SPL
默认例外也有您可以利用的层次结构。另外,如PHP Manual中所述:
抛出异常时,语句后面的代码不会 已执行, PHP将尝试查找第一个匹配的catch块。
这意味着你也可以
class CError extends LetterError {}
您需要处理的方式与AError
或BError
不同,因此您的catch语句将如下所示:
catch(CError $e){
//voodoo
}
catch(LetterError $e){
//voodoo
}
如果你遇到了二十个或更多合法属于同一个超类的异常的情况,并且你需要以一种方式处理五个(或任何大型组)其他方式,那么你仍然可以这样做。
interface Group1 {}
class AError extends LetterError implements Group1 {}
class BError extends LetterError implements Group1 {}
然后:
catch (Group1 $e) {}
在异常方面使用OOP非常强大。使用诸如get_class
或instanceof
之类的东西是黑客攻击,如果可能应该避免使用。
我想补充的另一个解决方案是将异常处理功能放在自己的方法中。
你可以
function handleExceptionMethod1(Exception $e)
{
//voodoo
}
function handleExceptionMethod2(Exception $e)
{
//voodoo
}
假设您无法控制异常类层次结构或接口(并且几乎总是将成为一种方式),您可以执行以下操作:
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);
}
通过这种方式,如果您的异常处理机制需要更改,并且您正在OOP的常规构造中工作,那么您仍然只需要修改一个代码位置。
答案 1 :(得分:221)
在PHP> = 7.1中,这是可能的。请参阅下面的answer。
如果您可以修改例外,use this answer。
如果你不能,你可以尝试使用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;
}
}
但是 use multiple catch blocks as described in aforementioned answer可能会更好。
try
{
/* something */
}
catch( AError $e )
{
handler1( $e );
}
catch ( BError $b )
{
handler2( $e );
}
答案 2 :(得分:88)
进入PHP 7.1是捕捉多种类型的能力。
这样:
<?php
try {
/* ... */
} catch (FirstException $ex) {
$this->manageException($ex);
} catch (SecondException $ex) {
$this->manageException($ex);
}
?>
和
<?php
try {
} catch (FirstException | SecondException $ex) {
$this->manageException($ex);
}
?>
功能相同。
答案 3 :(得分:42)
自PHP 7.1起,
catch( AError | BError $e )
{
handler1( $e )
}
有趣的是,你也可以:
catch( AError | BError $e )
{
handler1( $e )
} catch (CError $e){
handler2($e);
} catch(Exception $e){
handler3($e);
}
以及早期版本的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
}
}
答案 4 :(得分: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
}
}
处理多个例外
非常简单 - 每个可抛出的异常类型都有一个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
}
如果抛出的异常没有被任何其他catch语句处理,它将由catch(Exception $ e)块处理。它不一定是最后一个。
答案 5 :(得分: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;
}
}
答案 6 :(得分:5)
如果您无法控制定义异常,那么这是一个合理的替代方案。使用异常变量的名称可以在捕获异常时对异常进行分类。然后在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);
}
如果catch块实现之间存在大量重复,这种有点奇怪的方法可能是值得的。
答案 7 :(得分:3)
除了堕落之外,还可以使用转到来跳过。 如果你想看到世界燃烧,这是非常有用的。
@Component({
selector: 'dropdown',
template: `
<div>Test</div>
`
})
export class DropdownComponent {
constructor(public data:RouteParams) {
}
}
答案 8 :(得分:1)
一个好方法是使用.evenspecificerer {
color:black !important;
}
。
警告!!!使用PHP 7,您可能会因致命错误而死亡。例如,如果您在非对象上调用方法,通常会获得set_exception_handler
,如果启用了错误报告,您可能会看到此内容。
上述错误不会被Fatal error: Call to a member function your_method() on null
捕获。
上述错误不会触发catch(Exception $e)
设置的任何自定义错误处理程序。
您必须使用set_error_handler
来捕获PHP7中的错误。 。
这可能会有所帮助:
catch(Error $e){ }
答案 9 :(得分:0)
此处未列出的另一个选项是使用异常的code
属性,因此您可以执行以下操作:
try {
if (1 === $foo) {
throw new Exception(sprintf('Invalid foo: %s', serialize($foo)), 1);
}
if (2 === $bar) {
throw new Exception(sprintf('Invalid bar: %s', serialize($foo)), 2);
}
} catch (Exception $e) {
switch ($e->getCode()) {
case 1:
// Special handling for case 1
break;
case 2:
// Special handling for case 2
break;
default:
// Special handling for all other cases
}
}
答案 10 :(得分:0)
对于那些不想捕获所有异常并且无法建立通用接口的人来说,这是另一个简单的:
<?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!
}
?>
答案 11 :(得分:0)
从PHP 8.0开始,您可以使用更简洁的方法来捕获异常。但是,您必须将默认Exception
替换为Throwable
。
try {
/* something */
} catch (AError | BError) {
handler1($e)
} catch (Throwable) {
handler2($e)
}