I would like a cleaner way to get the following functionality to catch AError
and BError
in one block:
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 capture them individually?
AError
and Berror
have a shared base class, but they are also shared with other types that I want to fall into handler2
, so I can't just capture the base kind.
P粉7774587872023-10-15 15:07:15
This is possible in PHP >= 7.1. See this answer.
If you can modify the exception, please use this answer .
If not, you can try to catch all exceptions using Exception
and then use 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; } }
But it is better to use multiple catch blocks as mentioned in the answer above .
try { /* something */ } catch( AError $e ) { handler1( $e ); } catch ( BError $b ) { handler2( $e ); }
P粉6114563092023-10-15 00:46:51
This feature is available starting with PHP 7.1.
The syntax is:
try { // Some code... } catch(AError | BError $e) { // Handle exceptions } catch(Exception $e) { // Handle the general case }
Documentation: https://www.php.net/manual/en/language.exceptions.php#example-334
RFC: https://wiki.php.net/rfc/multiple-catch
Commit:https://github.com/php/php-src/commit/ 0aed2cc2a440e7be17552cc669d71fdd24d1204a
Despite what these other answers say, you can catch both AError
and BError
in the same block (it's easier if you're the one defining the exception). Even if there are exceptions that you wish to "exclude", you should still be able to define the hierarchy to suit your needs.
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 here and here, even the SPL
default exception has a hierarchy that can be exploited. Additionally, as stated in the PHP Manual:
This means you can also have
class CError extends LetterError {}
You need to handle it differently than AError
or BError
, so your catch statement will look like this:
catch(CError $e){ //voodoo } catch(LetterError $e){ //voodoo }
If you have a situation where there are twenty or more exceptions that legitimately belong to the same superclass, and you need to handle five of them (or any large group) in one way, and the rest in Another way to handle it, you can still do it.
interface Group1 {} class AError extends LetterError implements Group1 {} class BError extends LetterError implements Group1 {}
Then:
catch (Group1 $e) {}
Using OOP is very powerful when handling exceptions. Using things like get_class
or instanceof
is a hack and should be avoided if possible.
Another solution I'd like to add is to put the exception handling functionality into its own method.
You can have
function handleExceptionMethod1(Exception $e) { //voodoo } function handleExceptionMethod2(Exception $e) { //voodoo }
Assuming that you have absolutely no way to control the exception class hierarchy or interface (and almost always there will be 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); }
This way, if your exception handling mechanism needs to change, you still only have one code location that must be modified, and you are working within the general construct of OOP.