diff --git a/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php b/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php index 225ae66dc6c4..6341e88091b3 100644 --- a/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php +++ b/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php @@ -68,7 +68,7 @@ public function bootstrap(Application $app) public function handleError($level, $message, $file = '', $line = 0, $context = []) { if ($this->isDeprecation($level)) { - return $this->handleDeprecation($message, $file, $line); + return $this->handleDeprecationError($message, $file, $line, $level); } if (error_reporting() & $level) { @@ -83,8 +83,24 @@ public function handleError($level, $message, $file = '', $line = 0, $context = * @param string $file * @param int $line * @return void + * + * @deprecated Use handleDeprecationError instead. */ public function handleDeprecation($message, $file, $line) + { + $this->handleDeprecationError($message, $file, $line); + } + + /** + * Reports a deprecation to the "deprecations" logger. + * + * @param string $message + * @param string $file + * @param int $line + * @param int $level + * @return void + */ + public function handleDeprecationError($message, $file, $line, $level = E_DEPRECATED) { if (! class_exists(LogManager::class) || ! static::$app->hasBeenBootstrapped() @@ -101,8 +117,16 @@ public function handleDeprecation($message, $file, $line) $this->ensureDeprecationLoggerIsConfigured(); - with($logger->channel('deprecations'), function ($log) use ($message, $file, $line) { - $log->warning((string) new ErrorException($message, 0, E_DEPRECATED, $file, $line)); + $options = static::$app['config']->get('logging.deprecations') ?? []; + + with($logger->channel('deprecations'), function ($log) use ($message, $file, $line, $level, $options) { + if ($options['trace'] ?? false) { + $log->warning((string) new ErrorException($message, 0, $level, $file, $line)); + } else { + $log->warning(sprintf('%s in %s on line %s', + $message, $file, $line + )); + } }); } @@ -120,7 +144,9 @@ protected function ensureDeprecationLoggerIsConfigured() $this->ensureNullLogDriverIsConfigured(); - $driver = $config->get('logging.deprecations') ?? 'null'; + $options = $config->get('logging.deprecations'); + + $driver = is_array($options) ? $options['channel'] : ($options ?? 'null'); $config->set('logging.channels.deprecations', $config->get("logging.channels.{$driver}")); }); diff --git a/tests/Foundation/Bootstrap/HandleExceptionsTest.php b/tests/Foundation/Bootstrap/HandleExceptionsTest.php index 0b9cb7068a8e..08af8b1dffd3 100644 --- a/tests/Foundation/Bootstrap/HandleExceptionsTest.php +++ b/tests/Foundation/Bootstrap/HandleExceptionsTest.php @@ -49,6 +49,31 @@ public function testPhpDeprecations() $logger = m::mock(LogManager::class); $this->app->instance(LogManager::class, $logger); + $logger->shouldReceive('channel')->with('deprecations')->andReturnSelf(); + $logger->shouldReceive('warning')->with(sprintf('%s in %s on line %s', + 'str_contains(): Passing null to parameter #2 ($needle) of type string is deprecated', + '/home/user/laravel/routes/web.php', + 17 + )); + + $this->handleExceptions->handleError( + E_DEPRECATED, + 'str_contains(): Passing null to parameter #2 ($needle) of type string is deprecated', + '/home/user/laravel/routes/web.php', + 17 + ); + } + + public function testPhpDeprecationsWithStackTraces() + { + $logger = m::mock(LogManager::class); + $this->app->instance(LogManager::class, $logger); + + $this->config->set('logging.deprecations', [ + 'channel' => 'null', + 'trace' => true, + ]); + $logger->shouldReceive('channel')->with('deprecations')->andReturnSelf(); $logger->shouldReceive('warning')->with( m::on(fn (string $message) => (bool) preg_match( @@ -78,6 +103,31 @@ public function testUserDeprecations() $logger = m::mock(LogManager::class); $this->app->instance(LogManager::class, $logger); + $logger->shouldReceive('channel')->with('deprecations')->andReturnSelf(); + $logger->shouldReceive('warning')->with(sprintf('%s in %s on line %s', + 'str_contains(): Passing null to parameter #2 ($needle) of type string is deprecated', + '/home/user/laravel/routes/web.php', + 17 + )); + + $this->handleExceptions->handleError( + E_USER_DEPRECATED, + 'str_contains(): Passing null to parameter #2 ($needle) of type string is deprecated', + '/home/user/laravel/routes/web.php', + 17 + ); + } + + public function testUserDeprecationsWithStackTraces() + { + $logger = m::mock(LogManager::class); + $this->app->instance(LogManager::class, $logger); + + $this->config->set('logging.deprecations', [ + 'channel' => 'null', + 'trace' => true, + ]); + $logger->shouldReceive('channel')->with('deprecations')->andReturnSelf(); $logger->shouldReceive('warning')->with( m::on(fn (string $message) => (bool) preg_match(