diff --git a/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php b/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php index 280efaa87158..29cb0257f255 100644 --- a/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php +++ b/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php @@ -2,10 +2,14 @@ namespace Illuminate\Foundation\Bootstrap; +use const E_DEPRECATED; +use const E_USER_DEPRECATED; use ErrorException; use Exception; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Foundation\Application; +use function in_array; +use Psr\Log\LoggerInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\ErrorHandler\Error\FatalError; use Throwable; @@ -38,7 +42,9 @@ public function bootstrap(Application $app) $this->app = $app; - error_reporting(-1); + if (! $app->environment('production')) { + error_reporting(-1); + } set_error_handler([$this, 'handleError']); @@ -65,8 +71,19 @@ public function bootstrap(Application $app) */ public function handleError($level, $message, $file = '', $line = 0, $context = []) { + $e = new ErrorException($message, 0, $level, $file, $line); + + if ($level === E_USER_DEPRECATED || $level === E_DEPRECATED) { + $this->app->make(LoggerInterface::class)->warning( + $e->getMessage(), + ['exception' => $e] + ); + + return; + } + if (error_reporting() & $level) { - throw new ErrorException($message, 0, $level, $file, $line); + throw $e; } } diff --git a/tests/Foundation/Bootstrap/HandleExceptionsTest.php b/tests/Foundation/Bootstrap/HandleExceptionsTest.php new file mode 100644 index 000000000000..ecf215150ed3 --- /dev/null +++ b/tests/Foundation/Bootstrap/HandleExceptionsTest.php @@ -0,0 +1,72 @@ +app = m::mock(Application::class); + $this->app->allows()->environment('testing')->andReturns(false); + } + + /** @test */ + public function errorReportingShouldNotBeAffectedOnProduction(): void + { + error_reporting(E_ALL); + + $this->app->allows()->environment('production')->andReturns(true); + + (new HandleExceptions())->bootstrap($this->app); + + self::assertSame(E_ALL, error_reporting()); + } + + /** @test */ + public function errorReportingShouldBeOverriddenForOtherEnvironmentSoPeopleCanFindBugsEarlier(): void + { + error_reporting(E_ALL); + + $this->app->allows()->environment('production')->andReturns(false); + + (new HandleExceptions())->bootstrap($this->app); + + self::assertSame(-1, error_reporting()); + } + + /** @test */ + public function deprecationMessagesShouldJustBeLogged(): void + { + $logger = m::mock(LoggerInterface::class); + + $this->app->allows()->environment('production')->andReturns(false); + $this->app->allows()->make(LoggerInterface::class)->andReturns($logger); + + (new HandleExceptions())->bootstrap($this->app); + + $logger->shouldReceive('warning')->withArgs(['Deprecation one', m::hasKey('exception')])->once(); + $logger->shouldReceive('warning')->withArgs(['Deprecation two', m::hasKey('exception')])->once(); + + trigger_error('Deprecation one', E_USER_DEPRECATED); + @trigger_error('Deprecation two', E_USER_DEPRECATED); + } +}