diff --git a/src/DependencyInjection/DoctrineExtension.php b/src/DependencyInjection/DoctrineExtension.php index 8a7880361..5c7611e9c 100644 --- a/src/DependencyInjection/DoctrineExtension.php +++ b/src/DependencyInjection/DoctrineExtension.php @@ -1450,11 +1450,6 @@ private function registerDbalMiddlewares( $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../../config')); $loader->load('middlewares.php'); - $loggingMiddlewareAbstractDef = $container->getDefinition('doctrine.dbal.logging_middleware'); - foreach ($connWithLogging as $connName) { - $loggingMiddlewareAbstractDef->addTag('doctrine.middleware', ['connection' => $connName, 'priority' => 10]); - } - $container->getDefinition('doctrine.debug_data_holder')->replaceArgument(0, $connWithBacktrace); $debugMiddlewareAbstractDef = $container->getDefinition('doctrine.dbal.debug_middleware'); foreach ($connWithProfiling as $connName) { @@ -1467,5 +1462,22 @@ private function registerDbalMiddlewares( $idleConnectionMiddlewareAbstractDef ->addTag('doctrine.middleware', ['connection' => $connName, 'priority' => 10]); } + + $loggingMiddlewareAbstractDef = $container->getDefinition('doctrine.dbal.logging_middleware'); + + foreach ($connWithLogging as $connName) { + // Preserve legacy behavior: also tag the abstract definition per-connection + $loggingMiddlewareAbstractDef->addTag('doctrine.middleware', ['connection' => $connName, 'priority' => 10]); + + // Register logging middlewares only when a logger service is available + if (! $container->has('logger')) { + continue; + } + + // Create a child service for the connection + $child = new ChildDefinition('doctrine.dbal.logging_middleware'); + $child->addTag('doctrine.middleware', ['connection' => $connName, 'priority' => 10]); + $container->setDefinition(sprintf('doctrine.dbal.logging_middleware.%s', $connName), $child); + } } } diff --git a/tests/DependencyInjection/DoctrineExtensionTest.php b/tests/DependencyInjection/DoctrineExtensionTest.php index 99db8fb1b..e25c68ee3 100644 --- a/tests/DependencyInjection/DoctrineExtensionTest.php +++ b/tests/DependencyInjection/DoctrineExtensionTest.php @@ -1064,6 +1064,8 @@ public function testAsDoctrineListenerAttribute(): void public function testRegistrationsWithMiddlewaresAndSfDebugMiddleware(): void { $container = $this->getContainer(); + // Register a dummy logger service to enable logging middleware registration + $container->setDefinition('logger', (new Definition('\stdClass'))->setPublic(true)); $extension = new DoctrineExtension(); $config = BundleConfigurationBuilder::createBuilder() @@ -1133,6 +1135,8 @@ public function testRegistrationsWithMiddlewaresAndSfDebugMiddleware(): void public function testDefinitionsToLogAndProfile(): void { $container = $this->getContainer(); + // Register a dummy logger service to enable logging middleware registration + $container->setDefinition('logger', (new Definition('\stdClass'))->setPublic(true)); $extension = new DoctrineExtension(); $config = BundleConfigurationBuilder::createBuilder() @@ -1206,6 +1210,84 @@ public function testDefinitionsToLogQueriesLoggingFalse(): void $this->assertArrayNotHasKey('doctrine.middleware', $abstractMiddlewareDefTags); } + public function testLoggingMiddlewarePerConnectionWithLoggerPresent(): void + { + $container = $this->getContainer(); + // Register a dummy logger service to enable logging middleware registration + $container->setDefinition('logger', (new Definition('\stdClass'))->setPublic(true)); + + $extension = new DoctrineExtension(); + + $config = BundleConfigurationBuilder::createBuilder() + ->addConnection([ + 'connections' => [ + 'conn1' => [ + 'password' => 'foo', + 'logging' => true, + 'profiling' => false, + ], + 'conn2' => [ + 'password' => 'bar', + 'logging' => true, + 'profiling' => false, + ], + ], + ]) + ->build(); + + $extension->load([$config], $container); + + // Abstract definition should be present and tagged per connection + $this->assertTrue($container->hasDefinition('doctrine.dbal.logging_middleware')); + $abstractTags = $container->getDefinition('doctrine.dbal.logging_middleware')->getTags(); + $this->assertArrayHasKey('doctrine.middleware', $abstractTags); + $this->assertContains(['connection' => 'conn1', 'priority' => 10], $abstractTags['doctrine.middleware']); + $this->assertContains(['connection' => 'conn2', 'priority' => 10], $abstractTags['doctrine.middleware']); + + // Child services should be created per connection with proper tags + $this->assertTrue($container->hasDefinition('doctrine.dbal.logging_middleware.conn1')); + $this->assertTrue($container->hasDefinition('doctrine.dbal.logging_middleware.conn2')); + + $child1Tags = $container->getDefinition('doctrine.dbal.logging_middleware.conn1')->getTags(); + $child2Tags = $container->getDefinition('doctrine.dbal.logging_middleware.conn2')->getTags(); + + $this->assertArrayHasKey('doctrine.middleware', $child1Tags); + $this->assertContains(['connection' => 'conn1', 'priority' => 10], $child1Tags['doctrine.middleware']); + $this->assertArrayNotHasKey('monolog.logger', $child1Tags); + + $this->assertArrayHasKey('doctrine.middleware', $child2Tags); + $this->assertContains(['connection' => 'conn2', 'priority' => 10], $child2Tags['doctrine.middleware']); + $this->assertArrayNotHasKey('monolog.logger', $child2Tags); + } + + public function testLoggingMiddlewareNotRegisteredWithoutLogger(): void + { + $container = $this->getContainer(); + // No logger service defined here + + $extension = new DoctrineExtension(); + + $config = BundleConfigurationBuilder::createBuilder() + ->addConnection([ + 'connections' => [ + 'conn1' => [ + 'password' => 'foo', + 'logging' => true, + 'profiling' => false, + ], + ], + ]) + ->build(); + + $extension->load([$config], $container); + + // Abstract definition exists by default, and is tagged for legacy behavior, but no child definitions exist + $this->assertTrue($container->hasDefinition('doctrine.dbal.logging_middleware')); + $abstractTags = $container->getDefinition('doctrine.dbal.logging_middleware')->getTags(); + $this->assertArrayHasKey('doctrine.middleware', $abstractTags); + $this->assertFalse($container->hasDefinition('doctrine.dbal.logging_middleware.conn1')); + } + #[RequiresMethod(Driver::class, '__construct')] public function testDefinitionsIdleConnection(): void {