PDO (PHP Data Objects) adalah ekstensi PHP yang menyediakan antarmuka seragam untuk mengakses berbagai jenis database (MySQL, PostgreSQL, SQLite, dll). PDO adalah cara modern dan aman untuk berinteraksi dengan database di PHP.
Mencegah SQL Injection dengan Prepared Statements
Satu cara coding untuk berbagai jenis database
Standar industri PHP saat ini, mysql_* sudah dihapus
<?php
// Cara lama - mysql_* sudah DIHAPUS di PHP 7+
$conn = mysql_connect("localhost","root","");
mysql_select_db("pos_sederhana");
// BERBAHAYA: rentan SQL Injection!
$nama = $_GET['nama'];
$sql = "SELECT * FROM produk
WHERE nama_produk = '$nama'";
$result = mysql_query($sql);
?>
â ī¸ Ini berbahaya karena hacker bisa inject SQL!
<?php
// Cara PDO - aman & modern
$pdo = new PDO(
"mysql:host=localhost;dbname=pos_sederhana",
"root",
""
);
// AMAN: Prepared Statement
$nama = $_GET['nama'];
$stmt = $pdo->prepare(
"SELECT * FROM produk
WHERE nama_produk = ?"
);
$stmt->execute([$nama]);
?>
â SQL Injection tidak bisa terjadi!
Buat file config/database.php â file ini akan di-include di setiap halaman yang butuh database.
<?php
// ============================================
// FILE: config/database.php
// Fungsi: Koneksi PDO ke MySQL
// ============================================
// Konfigurasi database
define('DB_HOST', 'localhost'); // Host database
define('DB_NAME', 'pos_sederhana'); // Nama database
define('DB_USER', 'root'); // Username MySQL
define('DB_PASS', ''); // Password MySQL (kosong di XAMPP)
define('DB_CHARSET', 'utf8mb4'); // Charset
// Data Source Name (DSN)
$dsn = "mysql:host=" . DB_HOST .
";dbname=" . DB_NAME .
";charset=" . DB_CHARSET;
// Opsi PDO yang direkomendasikan
$options = [
// Lempar exception jika ada error (bukan diam-diam gagal)
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// Hasil query berupa array asosiatif (bisa pakai $row['nama'])
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// Gunakan prepared statements bawaan MySQL (lebih aman)
PDO::ATTR_EMULATE_PREPARES => false,
];
// Buat koneksi PDO
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, $options);
// echo "Koneksi berhasil!"; // Aktifkan saat testing
} catch (PDOException $e) {
// Tampilkan error yang ramah pengguna
// Di production, jangan tampilkan detail error!
die("<div class='alert alert-danger m-3'>
<strong>Error Koneksi Database!</strong><br>
" . htmlspecialchars($e->getMessage()) . "
</div>");
}
?>
DSN adalah string koneksi yang memberitahu PDO bagaimana cara terhubung ke database:
$dsn = "mysql:host=localhost;dbname=pos_sederhana;charset=utf8mb4";
// âââââ âââââââââââââââââ âââââââââââââââââââââ
// Driver Host database Nama database
mysql: â Jenis database (bisa juga pgsql:, sqlite:, dll)host=localhost â Database ada di komputer sendiridbname=pos_sederhana â Nama database yang dipakaicharset=utf8mb4 â Mendukung karakter Indonesia & emojiMengatur bagaimana PDO menangani error:
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
// Artinya: Jika ada error SQL, lempar Exception
// Kita bisa tangkap dengan try-catch
// Tanpa ini, error terjadi diam-diam!
// Kode kita tetap jalan tapi data tidak tersimpan
Menentukan format hasil query:
// Dengan FETCH_ASSOC (array asosiatif):
$row['nama_produk'] // â
Bisa akses pakai nama kolom
$row['harga_jual']
// Tanpa pengaturan (default FETCH_BOTH):
$row['nama_produk'] // Bisa
$row[1] // Juga bisa (index angka) â membingungkan!
try {
// Coba jalankan kode
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
// Jika gagal, tangkap errornya
// $e->getMessage() = pesan error dari PHP
die("Koneksi gagal: " . $e->getMessage());
}
// Analogi: seperti try-catch di kehidupan nyata
// "COBA buka pintu, KALAU kuncinya salah, tampilkan pesan error"
Buat file test sementara untuk memastikan koneksi berhasil:
<?php
// File: test_koneksi.php
// HAPUS file ini setelah testing!
require_once 'config/database.php';
echo "<div style='font-family:Arial; margin:20px'>";
// Test 1: Koneksi berhasil
echo "<h3>đ Test Koneksi PDO</h3>";
echo "<p style='color:green'>â
Koneksi berhasil!</p>";
// Test 2: Query sederhana
$stmt = $pdo->query("SELECT COUNT(*) as total FROM produk");
$row = $stmt->fetch();
echo "<p>đĻ Jumlah produk: <strong>" . $row['total'] . "</strong></p>";
// Test 3: Tampilkan data
$stmt = $pdo->query("SELECT * FROM produk LIMIT 3");
echo "<table border='1' cellpadding='8'>";
echo "<tr><th>Kode</th><th>Nama</th><th>Harga</th></tr>";
while ($row = $stmt->fetch()) {
echo "<tr>";
echo "<td>" . $row['kode_produk'] . "</td>";
echo "<td>" . $row['nama_produk'] . "</td>";
echo "<td>Rp " . number_format($row['harga_jual'], 0, ',', '.') . "</td>";
echo "</tr>";
}
echo "</table>";
echo "</div>";
?>
http://localhost/pos_sederhana/test_koneksi.phpBuat includes/functions.php berisi fungsi-fungsi yang akan sering dipakai:
<?php
// ============================================
// FILE: includes/functions.php
// Berisi fungsi-fungsi helper yang sering dipakai
// ============================================
/**
* Format angka ke format Rupiah
* Contoh: 15000 â "Rp 15.000"
*/
function formatRupiah($angka) {
return 'Rp ' . number_format($angka, 0, ',', '.');
}
/**
* Cek apakah user sudah login
* Jika belum, redirect ke halaman login
*/
function cekLogin() {
if (!isset($_SESSION['user_id'])) {
header('Location: /pos_sederhana/auth/login.php');
exit();
}
}
/**
* Tampilkan alert Bootstrap (success/danger/warning)
*/
function tampilkanAlert($pesan, $tipe = 'success') {
$icon = match($tipe) {
'success' => 'â
',
'danger' => 'â',
'warning' => 'â ī¸',
default => 'âšī¸'
};
echo "<div class='alert alert-{$tipe} alert-dismissible fade show' role='alert'>
{$icon} {$pesan}
<button type='button' class='btn-close' data-bs-dismiss='alert'></button>
</div>";
}
/**
* Generate nomor transaksi unik
* Format: TRX-YYYYMMDD-XXXX (contoh: TRX-20250101-0001)
*/
function generateNoTransaksi($pdo) {
$tanggal = date('Ymd');
$prefix = "TRX-{$tanggal}-";
$stmt = $pdo->prepare(
"SELECT COUNT(*) FROM transaksi
WHERE no_transaksi LIKE ?"
);
$stmt->execute([$prefix . '%']);
$count = $stmt->fetchColumn();
return $prefix . str_pad($count + 1, 4, '0', STR_PAD_LEFT);
}
/**
* Bersihkan input dari karakter berbahaya
* SELALU gunakan ini sebelum menampilkan input user ke HTML!
*/
function bersihkan($input) {
return htmlspecialchars(strip_tags(trim($input)));
}
?>
// Di file manapun yang butuh functions.php: require_once '../includes/functions.php'; // Contoh penggunaan: echo formatRupiah(15000); // â Rp 15.000 cekLogin(); // â Redirect jika belum login echo bersihkan($_GET['q']); // â Input aman dari XSS