rfc:suppressed_exceptions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:suppressed_exceptions [2019/04/04 16:49] – Initial version danackrfc:suppressed_exceptions [2019/04/04 17:43] (current) danack
Line 8: Line 8:
 ===== Introduction ===== ===== Introduction =====
  
-In some scenarios it is possible for exception information to be lost, particularly when multiple exceptions occur in block of code. For example when retrying network requests.+Currently in PHP there are some scenarios where information about exceptions can be lost, particularly when multiple exceptions occur in block of code. For example when retrying network requests.
  
 <code php> <code php>
 function fetchDataOverNetwork() { function fetchDataOverNetwork() {
- 
-  $networkExceptions = []; 
  
   for ($i = 0; $i < MAX_ATTEMPTS; $i++) {   for ($i = 0; $i < MAX_ATTEMPTS; $i++) {
     try {     try {
-    // Some operation that may throw  +      // Some operation that may throw  
-   return foo(); +      return foo();  
 +    } 
 +    catch (NetworkException $networkException) { 
 +      // can't do anything with $networkException here
     }     }
- catch (NetworkException $ne) { 
- $networkExceptions[] = $ne; 
- } 
   }   }
      
Line 39: Line 37:
 } }
 catch (FooException $fooException) { catch (FooException $fooException) {
-    try { +  try { 
-        // try to release resource cleanly +    // try to release resource cleanly 
-        $resource->close(); +    $resource->close(); 
-        throw $fooException; +    throw $fooException; 
-    +  
-    catch (ResourceException $resourceException) { +  catch (ResourceException $resourceException) { 
-        // The information about $resourceException is lost. +    // The information about $resourceException is lost. 
-        throw $fooException; +    throw $fooException; 
-    }+  }
 } }
  
Line 65: Line 63:
  
 <code php> <code php>
-public void addSuppressed(Throwable exception)+public void addSuppressed(Throwable exception);
  
 public getSuppressed(): Throwable[]; public getSuppressed(): Throwable[];
Line 86: Line 84:
   for ($i = 0; $i < MAX_ATTEMPTS; $i++) {   for ($i = 0; $i < MAX_ATTEMPTS; $i++) {
     try {     try {
-    // Some operation that may throw  +      // Some operation that may throw  
-   return foo(); +      return foo();  
 +    } 
 +    catch (NetworkException $ne) { 
 +      $networkExceptions[] = $ne;
     }     }
- catch (NetworkException $ne) { 
- $networkExceptions[] = $ne; 
- } 
   }   }
  
Line 97: Line 95:
      
   foreach ($networkExceptions as $networkException) {   foreach ($networkExceptions as $networkException) {
-   $fdException->addSuppressed($networkException);+    $fdException->addSuppressed($networkException);
   }   }
      
Line 113: Line 111:
 } }
 catch (FooException $fooException) { catch (FooException $fooException) {
-    try { +  try { 
-        // try to release resource cleanly +    // try to release resource cleanly 
-        $resource->close(); +    $resource->close(); 
-        throw $fe; +    throw $fe; 
-    +  
-    catch (ResourceException $resourceException) { +  catch (ResourceException $resourceException) { 
-        $fe->addSuppressed($resourceException);         +    $fe->addSuppressed($resourceException);         
-        throw $fooException; +    throw $fooException; 
-    }+  }
 } }
 </code> </code>
Line 129: Line 127:
  
 As per the resource exception sometimes it is necessary to add suppressed exception to an exception that has been caught and is going to be re-thrown.  As per the resource exception sometimes it is necessary to add suppressed exception to an exception that has been caught and is going to be re-thrown. 
 +
 +
 +===== Why not just use the 'previous' exception =====
 +
 +The constructor for Exceptions allows a 'previous' exception to be set in the constructor. This is typically used for catching generic exceptions and throw a more specific exception:
 +
 +<code php>
 +function foo() 
 +{
 + try {
 + bar();
 + }
 + // LogicException is part of core
 + catch (LogicException $le) {
 + throw new FooException(
 +   "Failed calling bar:",
 +   0,
 +   $le
 + )
 + }
 +}
 +</code>
 +
 +In this example, only one thing has gone wrong unexpectedly and so the FooException and LogicException are representing a single unexpected error. As it is a single error, this exception only needs to be logged once.
 +
 +In the resource exception example, the fact that there was an exception calling 'foo' and the fact that there was an exception releasing the resource are two separate errors, that should be logged separately.
 +
 +
 +
 +
 +Additionally, the 'previous' exception can only be set in the constructor, but users may want to re-throw the initial exception, rather than create a new exception. 
 +
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
rfc/suppressed_exceptions.1554396577.txt.gz · Last modified: 2019/04/04 16:49 by danack