From d4c897fd897366953d16ba32f66015fa99aeede1 Mon Sep 17 00:00:00 2001 From: Serreau Jovann Date: Thu, 26 Mar 2026 12:15:06 +0100 Subject: [PATCH] Fix PostgreSQL SUBSTRING on timestamp: use CAST AS DATE with native SQL SUBSTRING does not work on timestamp in PostgreSQL. Use native SQL with CAST(created_at AS DATE) for daily chart aggregation. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/Controller/AdminController.php | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php index 4cb0201..057b166 100644 --- a/src/Controller/AdminController.php +++ b/src/Controller/AdminController.php @@ -768,25 +768,17 @@ class AdminController extends AbstractController ->getArrayResult(); // Daily chart data - $visitorsPerDay = $em->createQueryBuilder() - ->select("SUBSTRING(v.createdAt, 1, 10) AS day, COUNT(v.id) AS cnt") - ->from(AnalyticsUniqId::class, 'v') - ->where('v.createdAt >= :since') - ->setParameter('since', $since) - ->groupBy('day') - ->orderBy('day', 'ASC') - ->getQuery() - ->getArrayResult(); + $conn = $em->getConnection(); - $pageviewsPerDay = $em->createQueryBuilder() - ->select("SUBSTRING(e.createdAt, 1, 10) AS day, COUNT(e.id) AS cnt") - ->from(AnalyticsEvent::class, 'e') - ->where('e.createdAt >= :since') - ->setParameter('since', $since) - ->groupBy('day') - ->orderBy('day', 'ASC') - ->getQuery() - ->getArrayResult(); + $visitorsPerDay = $conn->executeQuery( + 'SELECT CAST(created_at AS DATE) AS day, COUNT(*) AS cnt FROM analytics_uniq_id WHERE created_at >= :since GROUP BY day ORDER BY day ASC', + ['since' => $since->format('Y-m-d H:i:s')], + )->fetchAllAssociative(); + + $pageviewsPerDay = $conn->executeQuery( + 'SELECT CAST(created_at AS DATE) AS day, COUNT(*) AS cnt FROM analytics_event WHERE created_at >= :since GROUP BY day ORDER BY day ASC', + ['since' => $since->format('Y-m-d H:i:s')], + )->fetchAllAssociative(); // Merge into aligned arrays $allDays = []; @@ -794,8 +786,16 @@ class AdminController extends AbstractController foreach ($pageviewsPerDay as $r) { $allDays[$r['day']] = true; } ksort($allDays); - $visitorsMap = array_column($visitorsPerDay, 'cnt', 'day'); - $pageviewsMap = array_column($pageviewsPerDay, 'cnt', 'day'); + $visitorsMap = []; + foreach ($visitorsPerDay as $r) { + $d = $r['day'] instanceof \DateTimeInterface ? $r['day']->format('Y-m-d') : (string) $r['day']; + $visitorsMap[$d] = (int) $r['cnt']; + } + $pageviewsMap = []; + foreach ($pageviewsPerDay as $r) { + $d = $r['day'] instanceof \DateTimeInterface ? $r['day']->format('Y-m-d') : (string) $r['day']; + $pageviewsMap[$d] = (int) $r['cnt']; + } $chartLabels = array_keys($allDays); $chartVisitors = array_map(fn ($d) => (int) ($visitorsMap[$d] ?? 0), $chartLabels);