connect_error) { http_response_code(500); die(json_encode([ 'status' => 'error', 'message' => 'Koneksi server database gagal: ' . $conn->connect_error, 'target' => $host . ':' . $port, 'user' => $user ])); } $selectedDb = null; foreach ($dbCandidates as $candidate) { if ($candidate && @$conn->select_db($candidate)) { $selectedDb = $candidate; break; } } if (!$selectedDb) { http_response_code(500); die(json_encode([ 'status' => 'error', 'message' => 'Tidak bisa memilih database. Cek DB_NAME di Production Environment Variables Coolify. DB_NAME harus sama dengan Initial Database / nama database di MySQL URL internal.', 'dicoba' => $dbCandidates, 'target' => $host . ':' . $port, 'user' => $user ])); } $conn->set_charset('utf8mb4'); // Alias agar kompatibel kalau file lain memakai nama variable berbeda. $koneksi = $conn; $mysqli = $conn; // Constants agar kompatibel kalau kode lama memakai DB_HOST, DB_USER, dst. if (!defined('DB_HOST')) define('DB_HOST', $host); if (!defined('DB_USER')) define('DB_USER', $user); if (!defined('DB_PASS')) define('DB_PASS', $pass); if (!defined('DB_NAME')) define('DB_NAME', $selectedDb); if (!defined('DB_PORT')) define('DB_PORT', $port); function bersih($str, $conn) { return $conn->real_escape_string(htmlspecialchars(strip_tags(trim((string)$str)))); } function cekLogin() { if (!isset($_SESSION['user_id'])) { header('Location: login.php'); exit; } } function cekRole(...$roles) { if (!in_array($_SESSION['role'] ?? '', $roles)) { header('Location: index.php?error=akses_ditolak'); exit; } } function rupiah($angka) { return 'Rp ' . number_format((float)$angka, 0, ',', '.'); } function hitungUsia($tgl) { if (!$tgl || $tgl === '0000-00-00') return '-'; try { $lahir = new DateTime($tgl); $sekarang = new DateTime(); return $lahir->diff($sekarang)->y . ' th'; } catch (Exception $e) { return '-'; } } ?>