I would like a cleaner way to get the following functionality to catchAErrorandBErrorin 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?
AErrorandBerrorhave a shared base class, but they are also shared with other types that I want to fall intohandler2, so I can't just capture the base kind.
This is possible in PHP >= 7.1. See thisanswer.
If you can modify the exception, pleaseuse this answer.
If not, you can try to catch all exceptions using
Exceptionand then useinstanceof.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 is betterto use multiple catch blocks as mentioned in the answer above.
try { /* something */ } catch( AError $e ) { handler1( $e ); } catch ( BError $b ) { handler2( $e ); }renew:
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
For versions prior to PHP 7.1:
Despite what these other answers say, you can catch both
AErrorandBErrorin 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 seehereandhere, even the
SPLdefault exception has a hierarchy that can be exploited. Additionally, as stated in thePHP Manual:This means you can also have
class CError extends LetterError {}You need to handle it differently than
AErrororBError, 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_classorinstanceofis 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 alwaysthere will be away), 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.