Diese interaktive Demo zeigt die Möglichkeiten von JsonSQL zur Analyse strukturierter JSON-Daten – ganz ohne klassische Datenbank.
Über das komfortable Filtermenü kannst du gezielt Produkte und Händler auswählen. Anschließend werden dir automatisch alle relevanten Statistiken wie Summe, Durchschnitt, Median, Minimum, Maximum, Spannweite, Varianz und Standardabweichung für numerische Felder wie Preis, Lagerbestand und Bewertung angezeigt – jeweils vor und nach dem Filter.
Zusätzlich kannst du Testdaten generieren und optional den Transaktionsmodus aktivieren, um Datenänderungen gesammelt zu speichern.
id | product | rating | price | vendor | stock | date |
---|---|---|---|---|---|---|
1 | Kaffeemaschine | 84.69 | Otto | 1340 | 2025-01-18 | |
2 | Kaffeemaschine | 76.04 | Otto | 2008 | 2025-01-14 | |
3 | Kaffeemaschine | 101.65 | Amazon | 4897 | 2025-03-31 | |
4 | Kaffeemaschine | 101.35 | MediaMarkt | 4875 | 2024-11-05 | |
5 | Kaffeemaschine | 76.51 | Real | 276 | 2024-11-15 | |
6 | Kaffeemaschine | 90.98 | Amazon | 4920 | 2025-01-31 | |
7 | Kaffeemaschine | 82.24 | Real | 2848 | 2025-03-07 | |
8 | Kaffeemaschine | 89.69 | Real | 1494 | 2025-01-26 | |
9 | Kaffeemaschine | 79.04 | Real | 2103 | 2025-03-23 | |
10 | Kaffeemaschine | 85.55 | Saturn | 4453 | 2025-02-26 | |
11 | Kaffeemaschine | 82.85 | Saturn | 1542 | 2025-03-27 | |
12 | Kaffeemaschine | 103.38 | eBay | 1711 | 2024-12-01 | |
13 | Kaffeemaschine | 90.5 | Real | 3868 | 2025-01-21 | |
14 | Kaffeemaschine | 95.33 | eBay | 1054 | 2025-01-23 | |
15 | Kaffeemaschine | 85.85 | Aldi | 594 | 2025-02-12 | |
16 | Kaffeemaschine | 103.74 | Lidl | 487 | 2025-03-04 | |
17 | Kaffeemaschine | 83.07 | Otto | 1332 | 2025-03-28 | |
18 | Kaffeemaschine | 80.98 | Real | 4343 | 2024-12-07 | |
19 | Kaffeemaschine | 100.37 | eBay | 3091 | 2024-11-15 | |
20 | Kaffeemaschine | 86.54 | eBay | 2530 | 2025-01-19 | |
21 | Kaffeemaschine | 105.37 | Otto | 2558 | 2024-12-21 | |
22 | Kaffeemaschine | 77.9 | Real | 496 | 2025-02-03 | |
23 | Kaffeemaschine | 101.41 | Lidl | 3207 | 2025-01-11 | |
24 | Kaffeemaschine | 77.78 | eBay | 71 | 2025-03-01 | |
25 | Kaffeemaschine | 77.69 | MediaMarkt | 3147 | 2025-01-07 | |
26 | Kaffeemaschine | 81.67 | Real | 2656 | 2025-03-24 | |
27 | Kaffeemaschine | 76.57 | MediaMarkt | 1545 | 2025-02-02 | |
28 | Kaffeemaschine | 82.53 | Lidl | 2874 | 2025-02-12 | |
29 | Kaffeemaschine | 94.08 | Saturn | 1297 | 2024-11-11 | |
30 | Kaffeemaschine | 99.88 | Amazon | 3819 | 2024-12-21 | |
31 | Kaffeemaschine | 97.46 | Lidl | 2543 | 2024-12-25 | |
32 | Kaffeemaschine | 100.57 | Amazon | 1117 | 2025-01-23 | |
33 | Kaffeemaschine | 96.96 | Amazon | 4485 | 2024-12-28 | |
34 | Kaffeemaschine | 76.8 | Amazon | 4131 | 2025-03-07 | |
35 | Kaffeemaschine | 95.95 | MediaMarkt | 557 | 2025-02-22 | |
36 | Kaffeemaschine | 105.28 | Amazon | 1625 | 2025-01-09 | |
37 | Kaffeemaschine | 84.2 | Lidl | 3697 | 2025-02-22 | |
38 | Kaffeemaschine | 92.62 | Real | 3676 | 2024-12-02 | |
39 | Kaffeemaschine | 100.18 | Lidl | 1046 | 2024-11-26 | |
40 | Kaffeemaschine | 96.79 | Real | 62 | 2025-02-08 | |
41 | Kaffeemaschine | 104.71 | Otto | 968 | 2025-03-31 | |
42 | Kaffeemaschine | 90.48 | Lidl | 762 | 2025-03-21 | |
43 | Kaffeemaschine | 87.54 | Amazon | 4996 | 2025-03-31 | |
44 | Kaffeemaschine | 100.55 | MediaMarkt | 3472 | 2024-11-25 | |
45 | Kaffeemaschine | 94.78 | Amazon | 2107 | 2025-03-13 | |
46 | Kaffeemaschine | 77.74 | eBay | 4131 | 2024-12-21 | |
47 | Kaffeemaschine | 99.21 | Real | 1561 | 2025-01-11 | |
48 | Kaffeemaschine | 91.97 | eBay | 2539 | 2024-11-12 | |
49 | Kaffeemaschine | 75.31 | eBay | 3100 | 2024-12-01 | |
50 | Kaffeemaschine | 76.67 | Aldi | 3522 | 2024-11-17 | |
51 | Wasserkocher | 39.95 | Amazon | 4599 | 2024-12-23 | |
52 | Wasserkocher | 53.49 | eBay | 4909 | 2025-02-18 | |
53 | Wasserkocher | 36.1 | Aldi | 4693 | 2024-12-17 | |
54 | Wasserkocher | 45.12 | Otto | 3655 | 2025-03-26 | |
55 | Wasserkocher | 35.84 | Real | 3503 | 2025-01-18 | |
56 | Wasserkocher | 46.33 | Aldi | 4712 | 2025-03-30 | |
57 | Wasserkocher | 44.09 | MediaMarkt | 3564 | 2025-03-17 | |
58 | Wasserkocher | 55.99 | Saturn | 3776 | 2024-11-10 | |
59 | Wasserkocher | 39.88 | Lidl | 1549 | 2025-02-16 | |
60 | Wasserkocher | 37.46 | Lidl | 4287 | 2024-12-24 | |
61 | Wasserkocher | 47.96 | Otto | 3608 | 2025-02-15 | |
62 | Wasserkocher | 51.09 | Aldi | 1683 | 2025-01-10 | |
63 | Wasserkocher | 36.79 | Real | 2246 | 2025-01-23 | |
64 | Wasserkocher | 40.09 | MediaMarkt | 2903 | 2024-12-19 | |
65 | Wasserkocher | 42.45 | Aldi | 1000 | 2025-03-09 | |
66 | Wasserkocher | 42.27 | Aldi | 3426 | 2025-01-07 | |
67 | Wasserkocher | 43.75 | Lidl | 263 | 2025-03-18 | |
68 | Wasserkocher | 43.09 | Otto | 29 | 2025-02-07 | |
69 | Wasserkocher | 48.12 | Saturn | 2233 | 2024-11-10 | |
70 | Wasserkocher | 36.04 | MediaMarkt | 826 | 2025-03-27 | |
71 | Wasserkocher | 41.47 | Amazon | 3280 | 2024-12-05 | |
72 | Wasserkocher | 40.32 | Lidl | 1933 | 2025-03-07 | |
73 | Wasserkocher | 55.18 | MediaMarkt | 4426 | 2025-01-07 | |
74 | Wasserkocher | 44.12 | Amazon | 4624 | 2024-12-05 | |
75 | Wasserkocher | 36.92 | Real | 3441 | 2025-01-29 | |
76 | Wasserkocher | 36.11 | Lidl | 2670 | 2024-11-10 | |
77 | Wasserkocher | 53.79 | Lidl | 1664 | 2025-01-22 | |
78 | Wasserkocher | 48.12 | Otto | 134 | 2025-03-21 | |
79 | Wasserkocher | 38.01 | Real | 2096 | 2024-11-11 | |
80 | Wasserkocher | 55.59 | Real | 994 | 2024-12-31 | |
81 | Wasserkocher | 55.32 | eBay | 4441 | 2025-03-08 | |
82 | Wasserkocher | 46.72 | Lidl | 4384 | 2024-11-02 | |
83 | Wasserkocher | 35.86 | Lidl | 4425 | 2025-02-05 | |
84 | Wasserkocher | 45.84 | Amazon | 1455 | 2025-02-21 | |
85 | Wasserkocher | 42.26 | Otto | 3379 | 2025-02-06 | |
86 | Wasserkocher | 50.44 | Saturn | 2558 | 2025-01-17 | |
87 | Wasserkocher | 43.05 | Real | 3786 | 2025-02-05 | |
88 | Wasserkocher | 47.8 | eBay | 544 | 2024-11-01 | |
89 | Wasserkocher | 48.12 | Saturn | 814 | 2025-03-09 | |
90 | Wasserkocher | 40.94 | MediaMarkt | 636 | 2025-01-09 | |
91 | Wasserkocher | 50.97 | Amazon | 730 | 2025-01-06 | |
92 | Wasserkocher | 47.34 | Saturn | 4022 | 2025-02-10 | |
93 | Wasserkocher | 39.18 | Saturn | 67 | 2024-12-28 | |
94 | Wasserkocher | 53.31 | Otto | 1565 | 2024-12-09 | |
95 | Wasserkocher | 50.34 | Amazon | 1935 | 2024-11-03 | |
96 | Wasserkocher | 37.86 | MediaMarkt | 1551 | 2024-12-29 | |
97 | Wasserkocher | 40.15 | eBay | 3397 | 2024-12-28 | |
98 | Wasserkocher | 35.31 | Amazon | 4836 | 2024-12-09 | |
99 | Wasserkocher | 51.2 | MediaMarkt | 2660 | 2025-03-25 | |
100 | Wasserkocher | 37.66 | eBay | 1998 | 2025-01-06 | |
101 | Toaster | 29.69 | MediaMarkt | 4582 | 2025-01-06 | |
102 | Toaster | 20.47 | Aldi | 141 | 2025-03-20 | |
103 | Toaster | 26.29 | eBay | 3838 | 2024-11-15 | |
104 | Toaster | 20.38 | Aldi | 1943 | 2024-12-20 | |
105 | Toaster | 28.6 | Real | 4856 | 2025-01-08 | |
106 | Toaster | 19.2 | Lidl | 323 | 2024-12-25 | |
107 | Toaster | 24.07 | Lidl | 2074 | 2025-02-19 | |
108 | Toaster | 21.75 | eBay | 57 | 2025-02-24 | |
109 | Toaster | 27.5 | Real | 3822 | 2024-11-28 | |
110 | Toaster | 24.32 | Otto | 2154 | 2025-02-09 | |
111 | Toaster | 26.22 | Otto | 4828 | 2025-01-24 | |
112 | Toaster | 30.21 | Aldi | 2342 | 2024-11-14 | |
113 | Toaster | 20.3 | Amazon | 2487 | 2025-01-15 | |
114 | Toaster | 20.46 | Amazon | 119 | 2025-02-19 | |
115 | Toaster | 29.58 | Amazon | 4583 | 2024-12-28 | |
116 | Toaster | 30.03 | Otto | 474 | 2025-03-11 | |
117 | Toaster | 19.9 | Amazon | 3584 | 2025-01-23 | |
118 | Toaster | 23.38 | MediaMarkt | 3212 | 2024-11-22 | |
119 | Toaster | 29.49 | Amazon | 1519 | 2024-11-30 | |
120 | Toaster | 25.83 | Lidl | 1255 | 2025-02-27 | |
121 | Toaster | 22.17 | Otto | 3080 | 2024-11-22 | |
122 | Toaster | 26.86 | Amazon | 2483 | 2025-02-01 | |
123 | Toaster | 19.78 | Saturn | 1669 | 2025-03-06 | |
124 | Toaster | 26.01 | Otto | 4253 | 2024-12-24 | |
125 | Toaster | 29.82 | Otto | 2057 | 2024-11-24 | |
126 | Toaster | 29.95 | Saturn | 3855 | 2025-02-03 | |
127 | Toaster | 22.18 | Real | 2554 | 2025-02-26 | |
128 | Toaster | 29.03 | Real | 372 | 2024-11-10 | |
129 | Toaster | 19.57 | Amazon | 4051 | 2024-11-24 | |
130 | Toaster | 19.46 | Amazon | 3452 | 2025-02-02 | |
131 | Toaster | 28.44 | Aldi | 4447 | 2024-12-13 | |
132 | Toaster | 25.6 | Amazon | 2245 | 2024-12-06 | |
133 | Toaster | 29.04 | Saturn | 4906 | 2024-11-18 | |
134 | Toaster | 22.49 | Aldi | 3421 | 2025-01-08 | |
135 | Toaster | 29.74 | Otto | 1837 | 2025-01-20 | |
136 | Toaster | 24.65 | Saturn | 2887 | 2024-12-20 | |
137 | Toaster | 21.87 | Lidl | 4403 | 2024-12-03 | |
138 | Toaster | 21.63 | Lidl | 3358 | 2024-12-05 | |
139 | Toaster | 29.48 | Real | 193 | 2024-12-10 | |
140 | Toaster | 24.87 | Aldi | 156 | 2025-02-22 | |
141 | Toaster | 26.84 | Amazon | 51 | 2024-11-12 | |
142 | Toaster | 21.46 | Aldi | 3065 | 2024-12-11 | |
143 | Toaster | 23.65 | MediaMarkt | 957 | 2024-12-15 | |
144 | Toaster | 25.26 | Lidl | 4082 | 2025-01-09 | |
145 | Toaster | 25.15 | eBay | 1123 | 2025-01-26 | |
146 | Toaster | 25.65 | Aldi | 1264 | 2025-03-06 | |
147 | Toaster | 22.83 | Lidl | 3822 | 2025-03-06 | |
148 | Toaster | 27.67 | Otto | 2392 | 2025-02-15 | |
149 | Toaster | 30.74 | Amazon | 1501 | 2024-11-13 | |
150 | Toaster | 20.33 | Lidl | 2461 | 2025-03-28 |
Spalte | Statistik | 🔄 Vor Filter | 🔍 Nach Filter |
---|---|---|---|
price | count | 150,00 | 150,00 |
price | countDistinct | 148,00 | 148,00 |
price | sum | 7.966,09 | 7.966,09 |
price | avg | 53,11 | 53,11 |
price | min | 19,20 | 19,20 |
price | max | 105,37 | 105,37 |
price | range | 86,17 | 86,17 |
price | median | 43,42 | 43,42 |
price | mode | 48,12 | 48,12 |
price | variance | 796,92 | 796,92 |
price | stddev | 28,23 | 28,23 |
stock | count | 150,00 | 150,00 |
stock | countDistinct | 147,00 | 147,00 |
stock | sum | 378.032,00 | 378.032,00 |
stock | avg | 2.520,21 | 2.520,21 |
stock | min | 29,00 | 29,00 |
stock | max | 4.996,00 | 4.996,00 |
stock | range | 4.967,00 | 4.967,00 |
stock | median | 2.534,50 | 2.534,50 |
stock | mode | 2.558,00 | 2.558,00 |
stock | variance | 2.196.468,28 | 2.196.468,28 |
stock | stddev | 1.482,05 | 1.482,05 |
rating | count | 150,00 | 150,00 |
rating | countDistinct | 5,00 | 5,00 |
rating | sum | 470,00 | 470,00 |
rating | avg | 3,13 | 3,13 |
rating | min | 1,00 | 1,00 |
rating | max | 5,00 | 5,00 |
rating | range | 4,00 | 4,00 |
rating | median | 3,00 | 3,00 |
rating | mode | 4,00 | 4,00 |
rating | variance | 1,83 | 1,83 |
rating | stddev | 1,35 | 1,35 |
<?php
$pageTitle = "JsonSQL Aggregat-Demo mit Filter";
$JsonSQLpath = __DIR__ . '/../../src/JsonSQL.php';
if (!file_exists($JsonSQLpath)) {
die("❌ Datei nicht gefunden!");
}
require_once $JsonSQLpath;
require_once __DIR__ . '/../includes/header.php';
use Src\JsonSQL;
function fakeAggregatRow(string $product, int $id): array {
$vendors = ['Amazon', 'MediaMarkt', 'eBay', 'Otto', 'Saturn', 'Lidl', 'Real', 'Aldi'];
$price = match ($product) {
'Kaffeemaschine' => rand(75, 105) + rand(0, 99) / 100,
'Wasserkocher' => rand(35, 55) + rand(0, 99) / 100,
'Toaster' => rand(19, 30) + rand(0, 99) / 100,
};
return [
'id' => $id,
'product' => $product,
'rating' => rand(1, 5),
'price' => round($price, 2),
'vendor' => $vendors[array_rand($vendors)],
'stock' => rand(0, 5000),
'date' => date('Y-m-d', strtotime("2024-11-01 +" . rand(0, 150) . " days"))
];
}
// Init
$db = new JsonSQL(['aggregat_demo' => __DIR__ . '/../testdb/aggregat_demo']);
$table = 'aggregat_demo_data';
$db->use('aggregat_demo')->setTable($table);
// Daten neu generieren, wenn "reset=1"
if (isset($_GET['reset']) && $_GET['reset'] == 1) {
// Anzahl Einträge pro Produkt holen
$entriesPerProduct = isset($_GET['entriesPerProduct']) ? max(1, (int)$_GET['entriesPerProduct']) : 2;
// Tabelle leeren und neue Einträge erzeugen
$db->truncate($table);
$id = 1;
$useTransaction = isset($_GET['useTransaction']);
if ($useTransaction) {
$db->transact();
}
foreach (['Kaffeemaschine', 'Wasserkocher', 'Toaster'] as $product) {
for ($i = 0; $i < $entriesPerProduct; $i++) {
$db->insert(fakeAggregatRow($product, $id++));
}
}
if ($useTransaction) {
$db->commit();
}
// Nach dem Erzeugen: Redirect, um Parameter aus URL zu entfernen
$url = strtok($_SERVER["REQUEST_URI"], '?'); // Basis-URL ohne Parameter
// header("Location: $url");
// exit;
} else {
$db->setTable($table,true);
}
// Filterwerte holen
$filterProduct = trim($_GET['product'] ?? '');
if ($filterProduct !== '') {
$db->where([['product', '=', $filterProduct]]);
}
$filterVendor = trim($_GET['vendor'] ?? '');
if ($filterVendor !== '') {
$db->where([['vendor', '=', $filterVendor]]);
}
// Daten laden und ggf. filtern
$db->select()->from($table)->get();
// Summe berechnen
$column = 'price';
$result_sum_all = $db->sum($column);
$result_avg_all = $db->avg($column);
$resultcount_all = $db->count();
$vendors = $db->distinct('vendor');
$products = $db->distinct('product');
$debugger->dump($vendors,$products);
$db->select()->from($table);
$conditions = [];
if ($filterVendor) {
$conditions[] = ['vendor', '=', $filterVendor];
}
if ($filterProduct) {
$conditions[] = ['product', '=', $filterProduct];
}
$debugger->addInfoText('Filter');
if (!empty($conditions)) {
$db->where($conditions); // wirkt als OR-Verknüpfung
}
$debugger->dump($conditions,$db);
// Summe berechnen
$column = 'price';
$result_sum = $db->sum($column);
$result_avg = $db->avg($column);
$resultcount = $db->count();
$data = $db->get();
// Distinct für Dropdowns
// $vendors = $db->distinct('vendor');
// $products = $db->distinct('product');
$numericFields = ['price', 'stock', 'rating'];
$stats_all = [];
$stats_filtered = [];
$db->select()->from($table);
foreach ($numericFields as $field) {
// Ohne Filter
$stats_all[$field] = $db->stats($field);
// Mit Filter
if (!empty($conditions)) {
$db->where($conditions);
}
$stats_filtered[$field] = $db->stats($field);
}
?>
<div class="container">
<h1 class="mb-4">📊 JsonSQL Aggregat-Demo mit Filter</h1>
<div class="mb-4">
<p class="lead">
Diese interaktive Demo zeigt die Möglichkeiten von <strong>JsonSQL</strong> zur Analyse strukturierter JSON-Daten – ganz ohne klassische Datenbank.
</p>
<p>
Über das komfortable Filtermenü kannst du gezielt Produkte und Händler auswählen. Anschließend werden dir automatisch alle relevanten Statistiken wie <strong>Summe, Durchschnitt, Median, Minimum, Maximum, Spannweite, Varianz</strong> und <strong>Standardabweichung</strong> für numerische Felder wie Preis, Lagerbestand und Bewertung angezeigt – jeweils vor und nach dem Filter.
</p>
<p>
Zusätzlich kannst du Testdaten generieren und optional den <strong>Transaktionsmodus</strong> aktivieren, um Datenänderungen gesammelt zu speichern.
</p>
</div>
<hr>
<form method="get" class="row g-3 mb-4">
<input type="hidden" name="reset" value="1">
<div class="col-md-3">
<label for="entriesPerProduct" class="form-label">Anzahl pro Produkt:</label>
<input type="number" class="form-control" id="entriesPerProduct" name="entriesPerProduct"
value="<?= htmlspecialchars($_GET['entriesPerProduct'] ?? 5) ?>" min="1" max="1000">
</div>
<div class="col-md-3">
<label for="useTransaction" class="form-label">Transaktionsmodus:</label>
<div class="form-check pt-2">
<input class="form-check-input" type="checkbox" name="useTransaction" value="1" id="useTransaction"
<?= isset($_GET['useTransaction']) ? 'checked' : '' ?>>
<label class="form-check-label" for="useTransaction">
Verwenden
</label>
</div>
</div>
<div class="col-md-3 align-self-end">
<button type="submit" class="btn btn-warning">🔁 Daten neu generieren</button>
</div>
</form>
<hr>
<form method="get" class="row g-3 mb-4">
<div class="col-md-3">
<label for="vendor" class="form-label">Händler:</label>
<select id="vendor" name="vendor" class="form-select">
<option value="">Alle</option>
<?php foreach ($vendors as $v): ?>
<option value="<?= $v ?>" <?= $v === $filterVendor ? 'selected' : '' ?>><?= $v ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<label for="product" class="form-label">Produkt:</label>
<select id="product" name="product" class="form-select">
<option value="">Alle</option>
<?php foreach ($products as $p): ?>
<option value="<?= $p ?>" <?= $p === $filterProduct ? 'selected' : '' ?>><?= $p ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6 align-self-end">
<div class="d-flex gap-2">
<button class="btn btn-outline-secondary" type="submit">🔍 Filtern</button>
<a href="<?= strtok($_SERVER["REQUEST_URI"], '?') ?>" class="btn btn-outline-secondary">⏮️ Zurücksetzen</a>
</div>
</div>
</form>
<h5>📋 Datentabelle (<?= count($data) ?> Einträge)</h5>
<?php if (!empty($data) && is_array(reset($data))): ?>
<div class="table-wrapper mb-4">
<table class="table table-sm table-striped table-bordered">
<thead class="table-light">
<tr>
<?php foreach (array_keys(reset($data)) as $key): ?>
<th><?= htmlspecialchars($key) ?></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ($data as $row): ?>
<tr>
<?php foreach ($row as $key => $value): ?>
<?php if ($key === 'rating'): ?>
<?php $stars = (int) $value; ?>
<td title="<?= $stars ?> Sterne im Rating">
<div class="rating-stars">
<?php
for ($i = 0; $i < $stars; $i++) {
echo '<i class="bi bi-star-fill text-warning"></i>';
}
for ($i = $stars; $i < 5; $i++) {
echo '<i class="bi bi-star text-muted"></i>';
}
?>
</div>
</td>
<?php else: ?>
<td><?= htmlspecialchars((string) $value) ?></td>
<?php endif; ?>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="alert alert-warning">Keine Daten gefunden für die aktuelle Auswahl.</div>
<?php endif; ?>
<?php if (!empty($column)): ?>
<h4 class="mt-5">📈 Statistiken pro Spalte (vor / nach Filter)</h4>
<div class="row">
<div class="col-12 col-lg-8">
<div class="stats-table-wrapper mb-5">
<table class="table table-sm table-striped table-bordered table-hover align-middle">
<thead class="table-light text-center">
<tr>
<th>Spalte</th>
<th>Statistik</th>
<th>🔄 Vor Filter</th>
<th>🔍 Nach Filter</th>
</tr>
</thead>
<tbody>
<?php
// Formatierungsfunktion
function fmt($val): string {
if (is_array($val)) return json_encode($val, JSON_UNESCAPED_UNICODE);
if (is_numeric($val)) return number_format((float) $val, 2, ',', '.');
return htmlspecialchars((string) $val);
}
?>
<?php foreach ($numericFields as $field): ?>
<?php foreach ($stats_all[$field] as $key => $val): ?>
<tr>
<td><?= htmlspecialchars($field) ?></td>
<td><?= htmlspecialchars($key) ?></td>
<td class="text-end"><?= fmt($val) ?></td>
<td class="text-end"><?= fmt($stats_filtered[$field][$key] ?? null) ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php
endif;
$scriptName = basename(__FILE__);
$scriptContent = file_get_contents(__FILE__);
$scriptContent = preg_replace('//s', '', $scriptContent);
?>
<!-- Exclude Begin -->
<div class="container mt-5 mb-3">
<hr class="shadow-lg rounded">
<div class="accordion" id="codeAccordion">
<div class="accordion-item">
<h2 class="accordion-header" id="headingCode">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseCode" aria-expanded="false" aria-controls="collapseCode">
📄 Quellcodeauszug dieser Demo anzeigen (<?= htmlspecialchars($scriptName) ?>)
</button>
</h2>
<div id="collapseCode" class="accordion-collapse collapse" aria-labelledby="headingCode" data-bs-parent="#codeAccordion">
<div class="accordion-body">
<pre class="code-block language-php"><code><?php echo htmlspecialchars($scriptContent); ?></code></pre>
</div>
</div>
</div>
</div>
</div>
<style>
.table-wrapper {
max-height: 400px;
overflow-y: auto;
}
.table-wrapper table {
border-collapse: separate;
width: 100%;
}
.table-wrapper thead th {
position: sticky;
top: 0;
background: #f8f9fa;
z-index: 2;
}
.stats-table-wrapper {
max-height: 400px;
overflow-y: auto;
position: relative;
border: 1px solid #dee2e6;
border-radius: .375rem;
}
.stats-table-wrapper table {
width: 100%;
border-collapse: separate;
}
.stats-table-wrapper thead th {
position: sticky;
top: 0;
background: #f8f9fa;
z-index: 5;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
}
.rating-stars i:hover {
color:rgb(255, 176, 7); /* bleibt golden, aber du könntest auch z. B. orange nehmen */
text-shadow: 0 0 5px rgb(225, 101, 0);
}
</style>
</div>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>