driver = 'mysqli'; try { mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $this->connection = mysqli_connect($host, $user, $pass, null, (int)$port); mysqli_report(MYSQLI_REPORT_OFF); } catch (Exception $e) { throw new Exception("MySQLi Connect Error: " . $e->getMessage()); } } elseif (extension_loaded('pdo_mysql')) { $this->driver = 'pdo'; try { $dsn = "mysql:host={$host};port={$port}"; $this->connection = new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]); } catch (PDOException $e) { throw new Exception("PDO Connect Error: " . $e->getMessage()); } } else { throw new Exception("Tidak ada driver database yang tersedia (MySQLi atau PDO_MySQL tidak ditemukan)."); } } public function selectDb($dbName) { if ($this->driver === 'mysqli') { return mysqli_select_db($this->connection, $dbName); } else { // PDO $this->connection->exec("USE `$dbName`"); return true; } } public function query($sql) { if ($this->driver === 'mysqli') { return mysqli_query($this->connection, $sql); } else { // PDO return $this->connection->query($sql); } } public function prepare($sql) { if ($this->driver === 'mysqli') { return mysqli_prepare($this->connection, $sql); } else { // PDO return $this->connection->prepare($sql); } } public function execute($stmt, $params = []) { if ($this->driver === 'mysqli') { if (!empty($params)) { $types = str_repeat('s', count($params)); // Asumsi semua string untuk kesederhanaan mysqli_stmt_bind_param($stmt, $types, ...$params); } return mysqli_stmt_execute($stmt); } else { // PDO return $stmt->execute($params); } } public function getResult($stmt) { if ($this->driver === 'mysqli') { return mysqli_stmt_get_result($stmt); } else { // PDO return $stmt; // PDO statement object is iterable } } public function fetchAllAssoc($result) { if ($this->driver === 'mysqli') { return mysqli_fetch_all($result, MYSQLI_ASSOC); } else { // PDO return $result->fetchAll(PDO::FETCH_ASSOC); } } public function fetchAssoc($result) { if ($this->driver === 'mysqli') { return mysqli_fetch_assoc($result); } else { // PDO return $result->fetch(PDO::FETCH_ASSOC); } } public function fetchRow($result) { if ($this->driver === 'mysqli') { return mysqli_fetch_row($result); } else { // PDO return $result->fetch(PDO::FETCH_NUM); } } public function fetchFields($result) { if ($this->driver === 'mysqli') { return mysqli_fetch_fields($result); } else { // PDO $fields = []; for ($i = 0; $i < $result->columnCount(); $i++) { $meta = $result->getColumnMeta($i); $field = new stdClass(); $field->name = $meta['name']; $fields[] = $field; } return $fields; } } public function dataSeek($result, $offset) { if ($this->driver === 'mysqli') { return mysqli_data_seek($result, $offset); } // PDO is forward-only, this is a limitation we accept for now. return true; } public function getAffectedRows($stmt = null) { if ($this->driver === 'mysqli') { return !is_null($stmt) ? mysqli_stmt_affected_rows($stmt) : mysqli_affected_rows($this->connection); } else { // PDO return !is_null($stmt) ? $stmt->rowCount() : 0; } } public function getLastError($stmt = null) { if ($this->driver === 'mysqli') { return !is_null($stmt) ? mysqli_stmt_error($stmt) : mysqli_error($this->connection); } else { // PDO $errorInfo = !is_null($stmt) ? $stmt->errorInfo() : $this->connection->errorInfo(); return $errorInfo[2] ?? 'Unknown PDO Error'; } } public function escape($string) { if ($this->driver === 'mysqli') { return mysqli_real_escape_string($this->connection, $string); } else { // PDO // PDO's quote() adds quotes, so we need to substr. // This is for simple cases. Prepared statements are always better. return substr($this->connection->quote($string), 1, -1); } } public function getServerInfo() { if ($this->driver === 'mysqli') { return mysqli_get_server_info($this->connection); } else { // PDO return $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION); } } public function getDriver() { return $this->driver; } public function multiQuery($sql) { if ($this->driver === 'mysqli') { if (mysqli_multi_query($this->connection, $sql)) { do { if ($res = mysqli_store_result($this->connection)) { mysqli_free_result($res); } } while (mysqli_more_results($this->connection) && mysqli_next_result($this->connection)); return true; } else { return false; } } else { // PDO try { $this->connection->exec($sql); return true; } catch(PDOException $e) { return false; } } } } // ============================================================================ // === FUNGSI BANTU === function execute_sql_from_file($db, $filepath, $is_gzipped = false) { $sql_content = ''; if (!file_exists($filepath) || !is_readable($filepath)) { return "File tidak ditemukan atau tidak dapat dibaca di server: " . htmlspecialchars($filepath); } if ($is_gzipped) { $zp = gzopen($filepath, "r"); if (!$zp) return "Gagal membuka file .gz."; while (!gzeof($zp)) { $sql_content .= gzgets($zp, 8192); } gzclose($zp); } else { $sql_content = file_get_contents($filepath); } if (trim($sql_content) === '') return "File SQL kosong."; if ($db->multiQuery($sql_content)) { return true; } else { return "Error impor: " . $db->getLastError(); } } // === MANAJEMEN KONEKSI & SESI === $db = null; $dbConnected = false; $connectionError = ''; $dbVersion = ''; $activeConnection = null; if (!isset($_SESSION['connections'])) { $_SESSION['connections'] = []; } if (isset($_GET['logout'])) { session_destroy(); header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); exit; } if (isset($_GET['disconnect'])) { unset($_SESSION['active_connection_id']); header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST' && !isset($_POST['ajax_action'])) { if (isset($_POST['add_connection'])) { $id = uniqid(); $_SESSION['connections'][$id] = [ 'id' => $id, 'host' => $_POST['dbHost'], 'user' => $_POST['dbUser'], 'pass' => $_POST['dbPass'], 'port' => $_POST['dbPort'] ]; // Redirect to connect immediately after adding header("Location: " . strtok($_SERVER["REQUEST_URI"], '?') . "?connect=" . $id); exit; } if (isset($_POST['delete_connection'])) { unset($_SESSION['connections'][$_POST['conn_id']]); header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); exit; } } if (isset($_GET['connect'])) { $conn_id = $_GET['connect']; if (isset($_SESSION['connections'][$conn_id])) { $_SESSION['active_connection_id'] = $conn_id; } header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); // Redirect to clean URL exit; } // Try to establish a connection if an active one is set if (isset($_SESSION['active_connection_id']) && isset($_SESSION['connections'][$_SESSION['active_connection_id']])) { $activeConnection = $_SESSION['connections'][$_SESSION['active_connection_id']]; try { $db = new Database($activeConnection['host'], $activeConnection['user'], $activeConnection['pass'], $activeConnection['port']); $dbConnected = true; $dbVersion = $db->getServerInfo(); } catch (Exception $e) { $connectionError = $e->getMessage(); unset($_SESSION['active_connection_id']); $dbConnected = false; } } // Inisialisasi variabel setelah koneksi $dbName = $_GET['db'] ?? null; $tableName = $_GET['table'] ?? null; $action = $_GET['action'] ?? ($tableName ? 'browse' : ($dbName ? 'tables' : 'databases')); $message = $_SESSION['message'] ?? ''; unset($_SESSION['message']); if ($dbConnected && $dbName) { $db->selectDb($dbName); } // === PENANGANAN PERMINTAAN AJAX (MENGGUNAKAN $db) === if ($dbConnected && isset($_POST['ajax_action'])) { header('Content-Type: application/json'); $response = ['status' => 'error', 'message' => 'Aksi tidak valid.']; $db->selectDb($_POST['db']); switch ($_POST['ajax_action']) { case 'update_row': $update_table = $_POST['table']; $pk_col = $_POST['pk_col']; $pk_val = $_POST['pk_val']; $data = $_POST['data']; $set_parts = []; $params = []; foreach ($data as $col => $val) { $set_parts[] = "`$col` = ?"; $params[] = $val; } $params[] = $pk_val; $sql = "UPDATE `$update_table` SET " . implode(', ', $set_parts) . " WHERE `$pk_col` = ?"; try { $stmt = $db->prepare($sql); $db->execute($stmt, $params); if ($db->getAffectedRows($stmt) >= 0) { $response = ['status' => 'success', 'message' => 'Baris berhasil diperbarui.']; } } catch (Exception $e) { $response['message'] = 'Gagal memperbarui: ' . $e->getMessage(); } break; case 'delete_row': $delete_table = $_POST['table']; $pk_col = $_POST['pk_col']; $pk_val = $_POST['pk_val']; $sql = "DELETE FROM `$delete_table` WHERE `$pk_col` = ?"; try { $stmt = $db->prepare($sql); $db->execute($stmt, [$pk_val]); if ($db->getAffectedRows($stmt) > 0) { $response = ['status' => 'success', 'message' => 'Baris berhasil dihapus.']; } else { $response = ['status' => 'error', 'message' => 'Baris tidak ditemukan atau gagal dihapus.']; } } catch (Exception $e) { $response['message'] = 'Gagal menghapus: ' . $e->getMessage(); } break; } echo json_encode($response); exit; } // === PENANGANAN AKSI POST (MENGGUNAKAN $db) === if ($dbConnected && $_SERVER['REQUEST_METHOD'] === 'POST') { $redirectUrl = "?db=" . urlencode($dbName) . ($tableName ? "&table=" . urlencode($tableName) : ''); // Action on table if ($tableName) { if (isset($_POST['rename_table'])) { $newTableName = $_POST['new_table_name']; if ($newTableName && $db->query("RENAME TABLE `$tableName` TO `$newTableName`")) { $_SESSION['message'] = "✅ Tabel '$tableName' berhasil diubah namanya menjadi '$newTableName'."; header("Location: ?db=".urlencode($dbName)."&table=".urlencode($newTableName)."&action=structure"); exit; } else { $_SESSION['message'] = "❌ Error: " . $db->getLastError(); } } elseif (isset($_POST['drop_table_confirm'])) { if($db->query("DROP TABLE `$tableName`")) { $_SESSION['message'] = "✅ Tabel '$tableName' berhasil dihapus."; header("Location: ?db=".urlencode($dbName)); exit; } else { $_SESSION['message'] = "❌ Error: " . $db->getLastError(); } } elseif (isset($_POST['truncate_table_confirm'])) { if($db->query("TRUNCATE TABLE `$tableName`")) { $_SESSION['message'] = "✅ Tabel '$tableName' berhasil dikosongkan."; header("Location: " . $redirectUrl . "&action=browse"); exit; } else { $_SESSION['message'] = "❌ Error: " . $db->getLastError(); } } elseif (isset($_POST['add_column'])) { $col = $_POST['col']; $sql = "ALTER TABLE `$tableName` ADD COLUMN `{$col['name']}` {$col['type']}"; if (!empty($col['length'])) $sql .= "({$col['length']})"; if (!empty($col['attributes'])) $sql .= " {$col['attributes']}"; if (!empty($col['collation'])) $sql .= " COLLATE {$col['collation']}"; $sql .= isset($col['nullable']) ? " NULL" : " NOT NULL"; if (isset($col['default_type'])) { switch ($col['default_type']) { case 'defined': $sql .= " DEFAULT '" . $db->escape($col['default_value']) . "'"; break; case 'NULL': $sql .= " DEFAULT NULL"; break; case 'CURRENT_TIMESTAMP': $sql .= " DEFAULT CURRENT_TIMESTAMP"; break; } } if (isset($col['auto_increment'])) $sql .= " AUTO_INCREMENT"; if (!empty($col['after'])) $sql .= $col['after'] == '--FIRST--' ? ' FIRST' : " AFTER `{$col['after']}`"; if($db->query($sql)) { $_SESSION['message'] = "✅ Kolom '{$col['name']}' berhasil ditambahkan."; if (!empty($col['index']) && $col['index'] != '---') { $indexType = $col['index']; $indexSql = "ALTER TABLE `$tableName` ADD " . ($indexType == 'PRIMARY' ? "PRIMARY KEY" : $indexType) . " (`{$col['name']}`)"; if(!$db->query($indexSql)) { $_SESSION['message'] .= " ⚠️ Gagal menambahkan index: " . $db->getLastError(); } } } else { $_SESSION['message'] = "❌ Gagal menambah kolom: " . $db->getLastError(); } header("Location: ?db=".urlencode($dbName)."&table=".urlencode($tableName)."&action=structure"); exit; } elseif (isset($_POST['update_column'])) { $col = $_POST['col']; $original_name = $_POST['original_col_name']; $sql = "ALTER TABLE `$tableName` CHANGE COLUMN `{$original_name}` `{$col['name']}` {$col['type']}"; if (!empty($col['length'])) $sql .= "({$col['length']})"; if (!empty($col['attributes'])) $sql .= " {$col['attributes']}"; $sql .= isset($col['nullable']) ? " NULL" : " NOT NULL"; if ($col['default_type'] == 'defined') $sql .= " DEFAULT '" . $db->escape($col['default_value']) . "'"; elseif ($col['default_type'] == 'NULL') $sql .= " DEFAULT NULL"; elseif ($col['default_type'] == 'CURRENT_TIMESTAMP') $sql .= " DEFAULT CURRENT_TIMESTAMP"; if($db->query($sql)) { $_SESSION['message'] = "✅ Kolom '{$original_name}' berhasil diubah."; } else { $_SESSION['message'] = "❌ Gagal mengubah kolom: " . $db->getLastError(); } header("Location: ?db=".urlencode($dbName)."&table=".urlencode($tableName)."&action=structure"); exit; } elseif (isset($_POST['drop_column_confirm'])) { $col_to_drop = $_POST['col_to_drop']; if($db->query("ALTER TABLE `$tableName` DROP COLUMN `$col_to_drop`")) { $_SESSION['message'] = "✅ Kolom '$col_to_drop' berhasil dihapus."; } else { $_SESSION['message'] = "❌ Gagal menghapus kolom: " . $db->getLastError(); } header("Location: ?db=".urlencode($dbName)."&table=".urlencode($tableName)."&action=structure"); exit; } } if(isset($_POST['insert_data']) && $tableName) { $columns = array_keys($_POST['data']); $values = array_values($_POST['data']); $placeholders = implode(',', array_fill(0, count($columns), '?')); $sql = "INSERT INTO `$tableName` (`" . implode('`,`', $columns) . "`) VALUES ($placeholders)"; $stmt = $db->prepare($sql); if($db->execute($stmt, $values)){ $_SESSION['message'] = '✅ 1 baris baru berhasil ditambahkan.'; } else { $_SESSION['message'] = '❌ Gagal menambahkan data: ' . $db->getLastError($stmt); } header("Location: " . $redirectUrl . "&action=browse"); exit; } if((isset($_POST['import_sql_upload']) && isset($_FILES['import_file']) && $_FILES['import_file']['error'] == UPLOAD_ERR_OK) || isset($_POST['import_sql_server'])) { $is_server_file = isset($_POST['import_sql_server']); $filepath = $is_server_file ? $_POST['server_file'] : $_FILES['import_file']['tmp_name']; $filename = $is_server_file ? $filepath : $_FILES['import_file']['name']; $is_gz = pathinfo($filename, PATHINFO_EXTENSION) == 'gz'; $result = execute_sql_from_file($db, $filepath, $is_gz); $_SESSION['message'] = ($result === true) ? "✅ File '{$filename}' berhasil diimpor." : '❌ ' . $result; header("Location: " . $redirectUrl); exit; } } // === FIND PRIMARY KEY & LOAD DATA (MENGGUNAKAN $db) === $primaryKey = null; if ($dbConnected && $dbName && $tableName) { try { $keys_res = $db->query("SHOW KEYS FROM `$tableName` WHERE Key_name = 'PRIMARY'"); if ($pk = $db->fetchAssoc($keys_res)) $primaryKey = $pk['Column_name']; } catch (Exception $e) { /* table might not exist yet */ } } $databases = []; $tables = []; if ($dbConnected) { $r = $db->query("SHOW DATABASES"); while ($row = $db->fetchAssoc($r)) $databases[] = $row['Database']; if ($dbName) { $db->selectDb($dbName); $r = $db->query("SHOW TABLES"); if ($r) while ($row = $db->fetchRow($r)) $tables[] = $row[0]; } } // === EKSPORT (MENGGUNAKAN $db) === if ($dbConnected && $action == 'export' && isset($_POST['export_data']) ) { $db->selectDb($dbName); $format = $_POST['format']; $type = $_POST['type']; $filename = $type == 'db' ? $dbName : $tableName; header('Content-Type: text/plain; charset=utf-8'); header('Content-Disposition: attachment; filename="' . htmlspecialchars($filename) . '.' . $format . '"'); if ($type == 'db') { $tables_to_export = []; $res = $db->query("SHOW TABLES"); while($row = $db->fetchRow($res)) $tables_to_export[] = $row[0]; foreach($tables_to_export as $table_to_export) { $create_table_res = $db->query("SHOW CREATE TABLE `$table_to_export`"); $create_table_row = $db->fetchRow($create_table_res); echo $create_table_row[1] . ";\n\n"; $r_data = $db->query("SELECT * FROM `$table_to_export`"); while($row_data = $db->fetchAssoc($r_data)) { $cols = array_keys($row_data); $vals = array_map(function($val) use ($db) { return is_null($val) ? 'NULL' : "'" . $db->escape($val) . "'"; }, array_values($row_data)); echo "INSERT INTO `$table_to_export` (`".implode('`,`', $cols)."`) VALUES (".implode(',', $vals).");\n"; } echo "\n-- --------------------------------------------------------\n\n"; } } else { // Table Export if ($format == 'csv') { $output = fopen('php://output', 'w'); $r = $db->query("SELECT * FROM `$tableName`"); $fields = $db->fetchFields($r); if (is_array($fields)) { $header = []; foreach ($fields as $f) { if (is_object($f) && isset($f->name)) { $header[] = $f->name; } else { $header[] = ''; } } fputcsv($output, $header); } else { fputcsv($output, ['No Fields']); } while ($row = $db->fetchAssoc($r)) fputcsv($output, $row); fclose($output); } else { // SQL Format if ($type == 'structure' || $type == 'all') { $create_table_res = $db->query("SHOW CREATE TABLE `$tableName`"); $create_table_row = $db->fetchRow($create_table_res); echo $create_table_row[1] . ";\n\n"; } if ($type == 'data' || $type == 'all') { $r = $db->query("SELECT * FROM `$tableName`"); while($row = $db->fetchAssoc($r)) { $cols = array_keys($row); $vals = array_map(function($val) use ($db) { return is_null($val) ? 'NULL' : "'" . $db->escape($val) . "'"; }, array_values($row)); echo "INSERT INTO `$tableName` (`".implode('`,`', $cols)."`) VALUES (".implode(',', $vals).");\n"; } } } } exit; } ?>
❌ = htmlspecialchars($connectionError) ?>
Belum ada koneksi yang tersimpan.
Nama Tabel (= count($tables) ?>) | Aksi |
---|---|
= htmlspecialchars($table) ?> | Data | Struktur | Operasi |
Nama | Tipe | Collation | Null | Key | Default | Extra | Aksi |
---|---|---|---|---|---|---|---|
=htmlspecialchars($row['Field'])?> | =htmlspecialchars($row['Type'])?> | =htmlspecialchars($row['Collation'])?> | =htmlspecialchars($row['Null'])?> | =htmlspecialchars($row['Key'])?> | =htmlspecialchars($row['Default'])?> | =htmlspecialchars($row['Extra'])?> | Ubah Hapus |
Apakah Anda yakin ingin menghapus kolom `= htmlspecialchars($_GET['col']) ?>` dari tabel `= htmlspecialchars($tableName) ?>`?
query("SELECT User, Host FROM mysql.user ORDER BY User, Host"); if ($res) { while($row = $db->fetchAssoc($res)) { $users[] = $row; } } else { echo "❌ Tidak dapat mengambil daftar pengguna. Pengguna saat ini mungkin tidak memiliki hak akses ke database `mysql`.
"; } } catch (Exception $e) { echo "❌ Error: " . $e->getMessage() . "
"; } ?>Username | Host | Aksi |
---|---|---|
= htmlspecialchars($user['User']) ?> | = htmlspecialchars($user['Host']) ?> | Lihat Hak Akses |
Peringatan: Fungsionalitas di bawah ini adalah contoh kerangka. Mengelola pengguna dan hak akses secara programatik memiliki risiko keamanan. Pastikan Anda mengerti perintah SQL yang dijalankan.
escape($grant_user); $escaped_host = $db->escape($grant_host); $res = $db->query("SHOW GRANTS FOR '{$escaped_user}'@'{$escaped_host}'"); if ($res) { while($row = $db->fetchRow($res)) { $grants[] = $row[0]; } } else { echo "❌ Gagal mengambil hak akses.
"; } } catch (Exception $e) { echo "❌ Error: " . $e->getMessage() . "
"; } ?>= htmlspecialchars($grant_user) ?>@= htmlspecialchars($grant_host) ?>
Daftar di bawah ini adalah perintah `GRANT` yang mendefinisikan hak akses untuk pengguna ini.
Kembali ke Daftar PenggunaPilih file .sql
atau .sql.gz
untuk diimpor.
Letakkan file di direktori yang sama dengan skrip ini. Contoh: backup.sql.gz
Aksi ini akan menghapus semua data di dalam tabel, tetapi struktur tabel tetap ada. Aksi ini tidak dapat dibatalkan.
Aksi ini akan menghapus tabel beserta seluruh datanya. Aksi ini tidak dapat dibatalkan.
❌ = htmlspecialchars($query_error) ?>
❌ Query Gagal: ".htmlspecialchars($e->getMessage())."
"; } ?>Menampilkan = count($data) ?> baris (Total: = $totalRows ?>, Halaman: = $page ?> dari = $totalPages ?>)
No. | Aksi | ".htmlspecialchars($header).""; ?>|
---|---|---|
= $offset + $i + 1 ?> | $cell): ?> |
= nl2br(htmlspecialchars($cell ?? 'NULL')) ?>
|