diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index b7aaa6a29e65a..842ef19070128 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -79,6 +79,7 @@ class Application implements ResetInterface private string $version; private ?CommandLoaderInterface $commandLoader = null; private bool $catchExceptions = true; + private bool $catchErrors = false; private bool $autoExit = true; private InputDefinition $definition; private HelperSet $helperSet; @@ -172,8 +173,11 @@ public function run(InputInterface $input = null, OutputInterface $output = null try { $exitCode = $this->doRun($input, $output); - } catch (\Exception $e) { - if (!$this->catchExceptions) { + } catch (\Throwable $e) { + if ($e instanceof \Exception && !$this->catchExceptions) { + throw $e; + } + if (!$e instanceof \Exception && !$this->catchErrors) { throw $e; } @@ -427,6 +431,14 @@ public function setCatchExceptions(bool $boolean) $this->catchExceptions = $boolean; } + /** + * Sets whether to catch errors or not during commands execution. + */ + public function setCatchErrors(bool $catchErrors = true): void + { + $this->catchErrors = $catchErrors; + } + /** * Gets whether to automatically exit after a command execution or not. */ diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 48b8f5a707c51..7132a052c8ec0 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Add `SignalMap` to map signal value to its name * Multi-line text in vertical tables is aligned properly + * The application can also catch errors with `Application::setCatchErrors(true)` 6.3 --- diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 229297c654c00..e59942ac8cc01 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -771,10 +771,15 @@ public function testFindAmbiguousCommandsIfAllAlternativesAreHidden() $this->assertInstanceOf(\FooCommand::class, $application->find('foo:')); } - public function testSetCatchExceptions() + /** + * @testWith [true] + * [false] + */ + public function testSetCatchExceptions(bool $catchErrors) { $application = new Application(); $application->setAutoExit(false); + $application->setCatchErrors($catchErrors); putenv('COLUMNS=120'); $tester = new ApplicationTester($application); @@ -798,6 +803,33 @@ public function testSetCatchExceptions() } } + /** + * @testWith [true] + * [false] + */ + public function testSetCatchErrors(bool $catchExceptions) + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions($catchExceptions); + $application->add((new Command('boom'))->setCode(fn () => throw new \Error('This is an error.'))); + + putenv('COLUMNS=120'); + $tester = new ApplicationTester($application); + + try { + $tester->run(['command' => 'boom']); + $this->fail('The exception is not catched.'); + } catch (\Throwable $e) { + $this->assertInstanceOf(\Error::class, $e); + $this->assertSame('This is an error.', $e->getMessage()); + } + + $application->setCatchErrors(true); + $tester->run(['command' => 'boom']); + $this->assertStringContainsString(' This is an error.', $tester->getDisplay(true)); + } + public function testAutoExitSetting() { $application = new Application();
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: