src/EventSubscriber/DbKeepAliveSubscriber.php line 28

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\EventSubscriber;
  4. use Doctrine\DBAL\Connection;
  5. use Doctrine\Persistence\ManagerRegistry;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. use Symfony\Component\HttpKernel\Event\RequestEvent;
  8. use Symfony\Component\HttpKernel\KernelEvents;
  9. final class DbKeepAliveSubscriber implements EventSubscriberInterface
  10. {
  11.     private ManagerRegistry $doctrine;
  12.     public function __construct(ManagerRegistry $doctrine)
  13.     {
  14.         $this->doctrine $doctrine;
  15.     }
  16.     public static function getSubscribedEvents(): array
  17.     {
  18.         // Très tôt pour précéder les accès DB (ChannelResolver, etc.)
  19.         return [KernelEvents::REQUEST => ['onKernelRequest'2048]];
  20.     }
  21.     public function onKernelRequest(RequestEvent $event): void
  22.     {
  23.         // Symfony >=5.3
  24.         if (method_exists($event'isMainRequest') && !$event->isMainRequest()) {
  25.             return;
  26.         }
  27.         // Compat <5.3
  28.         if (method_exists($event'isMasterRequest') && !$event->isMasterRequest()) {
  29.             return;
  30.         }
  31.         foreach ($this->doctrine->getConnections() as $connection) {
  32.             $this->pingOrReconnect($connection);
  33.             // (optionnel) poser quelques paramètres de session utiles :
  34.             $this->initMysqlSession($connection);
  35.         }
  36.     }
  37.     private function pingOrReconnect(Connection $conn): void
  38.     {
  39.         try {
  40.             if (method_exists($conn'ping')) {
  41.                 if (!$conn->ping()) {
  42.                     $conn->close();
  43.                     $conn->connect();
  44.                 }
  45.             } else {
  46.                 // fallback vieux DBAL
  47.                 $conn->executeQuery('SELECT 1');
  48.             }
  49.         } catch (\Throwable $e) {
  50.             $conn->close();
  51.             $conn->connect();
  52.         }
  53.     }
  54.     private function initMysqlSession(Connection $conn): void
  55.     {
  56.         try {
  57.             // Sécurisé: commandes simples et indépendantes
  58.             $conn->executeStatement("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'");
  59.             // Si autorisé côté serveur, augmente les timeouts session
  60.             $conn->executeStatement("SET SESSION wait_timeout = 28800");
  61.             $conn->executeStatement("SET SESSION interactive_timeout = 28800");
  62.         } catch (\Throwable $e) {
  63.             // ignorer si non supporté par l'hébergeur
  64.         }
  65.     }
  66. }