diff --git a/src/Illuminate/Foundation/Configuration/Exceptions.php b/src/Illuminate/Foundation/Configuration/Exceptions.php index 1072a1431196..847c2d499b01 100644 --- a/src/Illuminate/Foundation/Configuration/Exceptions.php +++ b/src/Illuminate/Foundation/Configuration/Exceptions.php @@ -150,6 +150,19 @@ public function dontReport(array|string $class) return $this; } + /** + * Register a callback to determine if an exception should not be reported. + * + * @param callable $using + * @return $this + */ + public function dontReportWhen(Closure $dontReportWhen) + { + $this->handler->dontReportWhen($dontReportWhen); + + return $this; + } + /** * Do not report duplicate exceptions. * diff --git a/src/Illuminate/Foundation/Exceptions/Handler.php b/src/Illuminate/Foundation/Exceptions/Handler.php index 00a69266dcc7..b7b9d3e6c839 100644 --- a/src/Illuminate/Foundation/Exceptions/Handler.php +++ b/src/Illuminate/Foundation/Exceptions/Handler.php @@ -72,6 +72,14 @@ class Handler implements ExceptionHandlerContract */ protected $dontReport = []; + + /** + * The callbacks that inspect exceptions to determine if they should be reported. + * + * @var array + */ + protected $dontReportCallbacks = []; + /** * The callbacks that should be used during reporting. * @@ -279,6 +287,23 @@ public function dontReport(array|string $exceptions) return $this->ignore($exceptions); } + /** + * Register a callback to determine if an exception should not be reported. + * + * @param callable $dontReportWhen + * @return $this + */ + public function dontReportWhen(callable $dontReportWhen) + { + if (! $dontReportWhen instanceof Closure) { + $dontReportWhen = Closure::fromCallable($dontReportWhen); + } + + $this->dontReportCallbacks[] = $dontReportWhen; + + return $this; + } + /** * Indicate that the given exception type should not be reported. * @@ -413,6 +438,12 @@ protected function shouldntReport(Throwable $e) return true; } + foreach ($this->dontReportCallbacks as $dontReportCallback) { + if ($dontReportCallback($e) === true) { + return true; + } + } + return rescue(fn () => with($this->throttle($e), function ($throttle) use ($e) { if ($throttle instanceof Unlimited || $throttle === null) { return false; diff --git a/tests/Foundation/FoundationExceptionsHandlerTest.php b/tests/Foundation/FoundationExceptionsHandlerTest.php index 98af2559a578..3797cf246037 100644 --- a/tests/Foundation/FoundationExceptionsHandlerTest.php +++ b/tests/Foundation/FoundationExceptionsHandlerTest.php @@ -635,6 +635,29 @@ public function testItCanDedupeExceptions() $this->assertSame($reported, [$one, $two]); } + public function testItCanSkipExceptionReportingUsingCallback() + { + $reported = []; + $e1 = new RuntimeException('foo'); + $e2 = new RuntimeException('bar'); + + $this->handler->reportable(function (\Throwable $e) use (&$reported) { + $reported[] = $e; + + return false; + }); + + $this->handler->dontReportWhen(function (\Throwable $e) { + return $e->getMessage() === 'foo'; + }); + + $this->handler->report($e1); + $this->handler->report($e2); + $this->handler->report($e1); + + $this->assertSame($reported, [$e2]); + } + public function testItDoesNotThrottleExceptionsByDefault() { $reported = [];