From 4cd7002b91d701b3d265ea29d5245f12d2d4f4b9 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Fri, 23 May 2025 09:37:30 +0200 Subject: [PATCH] Ignore errors while loading ObjectManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's possible to configure a `objectManagerLoader` that returns an instance to your configured Doctrine manager. This works great, and it gives PHPStan super capabilities. In most cases, you would fetch this object manager from the container from your framework (e.g. Symfony). But that requires the Symfony container to be compiled and booted. All good, unless you make a typo in one of your service configurations. You're left with an internal error when running PHPStan: ``` Internal error: You have requested a non-existent service "some_service". while analysing file /Volumes/CS/www/src/SomeFile.php Run PHPStan with -v option and post the stack trace to: https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml Found 1 error ⚠️ Result is incomplete because of severe errors. ⚠️ Fix these errors first and then re-run PHPStan to get all reported errors. `` Making mistakes is a common thing we do, so having PHPStan crash like this is counter productive. Even worse, when using the PHPStan integration in PHPStorm, you get error popups every time that this happened. Since the `objectManagerLoader` is already optional, we can improve things by catching Throwable's that occur while including the `objectManagerLoader` file and then we return `null`. To make it easier to debug this problem later, in the diagnostic extension, we show the last error that occurred. --- src/Doctrine/DoctrineDiagnoseExtension.php | 12 +++++++++++- src/Type/Doctrine/ObjectMetadataResolver.php | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Doctrine/DoctrineDiagnoseExtension.php b/src/Doctrine/DoctrineDiagnoseExtension.php index 0502c736..7e9b91cc 100644 --- a/src/Doctrine/DoctrineDiagnoseExtension.php +++ b/src/Doctrine/DoctrineDiagnoseExtension.php @@ -30,12 +30,22 @@ public function __construct( public function print(Output $output): void { + $objectManager = $this->objectMetadataResolver->getObjectManager(); + $output->writeLineFormatted(sprintf( 'Doctrine\'s objectManagerLoader: %s', $this->objectMetadataResolver->hasObjectManagerLoader() ? 'In use' : 'No', )); - $objectManager = $this->objectMetadataResolver->getObjectManager(); + if ($this->objectMetadataResolver->getLastError() !== null) { + $output->writeLineFormatted(sprintf( + 'Doctrine\'s objectManagerLoader error: %s', + $this->objectMetadataResolver->getLastError()->getMessage(), + )); + + $output->writeLineFormatted(''); + } + if ($objectManager instanceof EntityManagerInterface) { $connection = $objectManager->getConnection(); $driver = $this->driverDetector->detect($connection); diff --git a/src/Type/Doctrine/ObjectMetadataResolver.php b/src/Type/Doctrine/ObjectMetadataResolver.php index 054e9a57..5408b548 100644 --- a/src/Type/Doctrine/ObjectMetadataResolver.php +++ b/src/Type/Doctrine/ObjectMetadataResolver.php @@ -9,6 +9,7 @@ use PHPStan\Doctrine\Mapping\ClassMetadataFactory; use PHPStan\ShouldNotHappenException; use ReflectionException; +use Throwable; use function class_exists; use function is_file; use function is_readable; @@ -26,6 +27,8 @@ final class ObjectMetadataResolver private string $tmpDir; + private ?Throwable $lastError = null; + public function __construct( ?string $objectManagerLoader, string $tmpDir @@ -89,6 +92,11 @@ public function isTransient(string $className): bool } } + public function getLastError(): ?Throwable + { + return $this->lastError; + } + private function getMetadataFactory(): ?ClassMetadataFactory { if ($this->metadataFactory !== null) { @@ -160,7 +168,13 @@ private function loadObjectManager(string $objectManagerLoader): ?ObjectManager )); } - return require $objectManagerLoader; + try { + return require $objectManagerLoader; + } catch (Throwable $error) { + $this->lastError = $error; + + return null; + } } }