| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/clients/client1/seaside2.pacim.de/web/scripts/ |
Upload File : |
<?php
declare(strict_types=1);
/**
* Vollständiger Rebuild der search_index-Tabelle aus customers/bookings/invoices/events.
* Idempotent — bestehende Zeilen werden via ON DUPLICATE KEY UPDATE aktualisiert.
*
* Aufruf:
* php scripts/search-index-rebuild.php
* php scripts/search-index-rebuild.php --types=customer,booking
* php scripts/search-index-rebuild.php --batch=500
*/
if (PHP_SAPI !== 'cli') {
fwrite(STDERR, "Bitte nur über die Kommandozeile aufrufen.\n");
exit(1);
}
$root = dirname(__DIR__);
require_once $root . '/app/core/Database.php';
require_once $root . '/app/services/SearchIndexer.php';
$opts = getopt('', ['types::', 'batch::']);
$types = isset($opts['types']) && $opts['types'] !== ''
? array_map('trim', explode(',', $opts['types']))
: ['customer', 'booking', 'invoice', 'event'];
$batchSize = max(50, (int)($opts['batch'] ?? 1000));
$db = new Database();
$pdo = $db->getConnection();
$indexer = new SearchIndexer($db);
echo "Search-Index Rebuild gestartet.\n";
echo " Types : " . implode(', ', $types) . "\n";
echo " Batch : {$batchSize}\n\n";
$totalStart = microtime(true);
if (in_array('customer', $types, true)) {
rebuild($pdo, $batchSize, 'Kunden', "SELECT * FROM customers", function ($row) use ($indexer) {
$indexer->upsertCustomer($row);
});
}
if (in_array('booking', $types, true)) {
rebuild($pdo, $batchSize, 'Buchungen',
"SELECT b.id, b.booking_no, b.license_plate, b.normalized_license_plate,
b.travel_from, b.travel_to, b.updated_at, b.customer_id,
c.first_name, c.last_name, c.company, c.email, c.phone,
e.title AS event_title, e.ship_name
FROM bookings b
INNER JOIN customers c ON c.id = b.customer_id
INNER JOIN events e ON e.id = b.event_id",
function ($row) use ($indexer) { $indexer->upsertBooking($row); }
);
}
if (in_array('invoice', $types, true)) {
rebuild($pdo, $batchSize, 'Rechnungen',
"SELECT i.id, i.invoice_no, i.invoice_date, i.updated_at,
b.booking_no,
c.first_name, c.last_name, c.company
FROM invoices i
INNER JOIN bookings b ON b.id = i.booking_id
INNER JOIN customers c ON c.id = i.customer_id",
function ($row) use ($indexer) { $indexer->upsertInvoice($row); }
);
}
if (in_array('event', $types, true)) {
rebuild($pdo, $batchSize, 'Events',
"SELECT * FROM events",
function ($row) use ($indexer) { $indexer->upsertEvent($row); }
);
}
$totalMs = (microtime(true) - $totalStart) * 1000;
printf("\nFertig in %.1f ms.\n", $totalMs);
// -------------------------------------------------------------------
function rebuild(PDO $pdo, int $batchSize, string $label, string $baseSql, callable $apply): void
{
// Zähle erst, damit die Fortschritts-Anzeige sinnvoll ist.
$countStmt = $pdo->query("SELECT COUNT(*) FROM (" . $baseSql . ") AS t");
$total = (int)$countStmt->fetchColumn();
echo str_pad($label . ': ' . $total . ' Datensätze', 40);
if ($total === 0) { echo " → übersprungen\n"; return; }
$start = microtime(true);
$processed = 0;
$offset = 0;
while (true) {
$sql = $baseSql . " LIMIT {$batchSize} OFFSET {$offset}";
$stmt = $pdo->query($sql);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($rows)) break;
foreach ($rows as $row) {
try { $apply($row); $processed++; }
catch (Throwable $e) { fwrite(STDERR, " ! " . $e->getMessage() . "\n"); }
}
$offset += $batchSize;
echo '.';
}
$ms = (microtime(true) - $start) * 1000;
printf(" → %d / %d in %.1f ms\n", $processed, $total, $ms);
}