Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Kết nối cơ sở dữ liệu là bước đầu tiên của hầu hết ứng dụng PHP. Bài này hướng dẫn dùng PDO để làm đủ bốn thao tác thêm, đọc, sửa, xóa với MySQL, đặc biệt nhấn mạnh prepared statement để tránh lỗ hổng SQL Injection ngay từ đầu.
PDO (PHP Data Objects) là lớp truy cập dữ liệu thống nhất của PHP, hỗ trợ nhiều hệ cơ sở dữ liệu. Nó cung cấp prepared statement, xử lý lỗi bằng ngoại lệ và API nhất quán. Các hàm mysql_* cũ đã bị loại bỏ, còn mysqli là lựa chọn khác nhưng chỉ dành cho MySQL.
Dùng phpMyAdmin hoặc dòng lệnh MySQL chạy đoạn SQL sau:
CREATE DATABASE demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE demo;
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;Bảng mã utf8mb4 lưu đúng tiếng Việt có dấu và cả ký tự biểu tượng.
Tạo file db.php dùng chung cho cả dự án:
<?php
$host = '127.0.0.1';
$db = 'demo';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
error_log($e->getMessage());
exit('Không kết nối được cơ sở dữ liệu.');
}Ba tùy chọn quan trọng: chế độ ngoại lệ để lỗi không bị bỏ qua âm thầm, kiểu lấy dữ liệu mặc định là mảng kết hợp, và tắt giả lập prepared statement để dùng bản thật của MySQL. Ghi lỗi chi tiết vào log chứ đừng in ra cho người dùng, vì thông báo lỗi có thể lộ thông tin hệ thống. Trong dự án thật, thông tin đăng nhập nên nằm trong biến môi trường hoặc file cấu hình ngoài mã nguồn công khai, và không dùng tài khoản root.
Nếu bạn ghép trực tiếp dữ liệu người dùng vào câu lệnh SQL, kẻ xấu có thể chèn thêm lệnh. Ví dụ đoạn code nguy hiểm sau:
// KHÔNG LÀM NHƯ THẾ NÀY
$sql = "SELECT * FROM students WHERE email = '" . $_GET['email'] . "'";Chỉ cần gửi giá trị đặc biệt là câu lệnh có thể bị thay đổi ý nghĩa. Giải pháp là prepared statement: câu SQL và dữ liệu được gửi tách biệt, dữ liệu không bao giờ được diễn giải như lệnh.
<?php
require 'db.php';
// CREATE
$stmt = $pdo->prepare('INSERT INTO students (name, email) VALUES (:name, :email)');
$stmt->execute(['name' => 'Nguyễn An', 'email' => 'an@example.com']);
$newId = $pdo->lastInsertId();
// READ - danh sách
$stmt = $pdo->query('SELECT id, name, email FROM students ORDER BY id DESC');
$students = $stmt->fetchAll();
// READ - một bản ghi theo id
$stmt = $pdo->prepare('SELECT * FROM students WHERE id = :id');
$stmt->execute(['id' => $newId]);
$student = $stmt->fetch();
// UPDATE
$stmt = $pdo->prepare('UPDATE students SET name = :name WHERE id = :id');
$stmt->execute(['name' => 'Nguyễn Văn An', 'id' => $newId]);
echo 'Số dòng đã sửa: ' . $stmt->rowCount();
// DELETE
$stmt = $pdo->prepare('DELETE FROM students WHERE id = :id');
$stmt->execute(['id' => $newId]);Dấu hai chấm như :name là tham số có tên. Với truy vấn không có dữ liệu người dùng như danh sách đơn giản, query() là đủ. Khi có bất kỳ giá trị nào đến từ bên ngoài, hãy luôn dùng prepare và execute.
Chống SQL Injection chưa đủ, bạn còn phải chống XSS khi in dữ liệu ra trang. Hãy bọc đầu ra bằng htmlspecialchars:
<?php foreach ($students as $s): ?>
<tr>
<td><?= htmlspecialchars($s['name'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars($s['email'], ENT_QUOTES, 'UTF-8') ?></td>
</tr>
<?php endforeach; ?>Khi một nghiệp vụ gồm nhiều câu lệnh phải cùng thành công hoặc cùng thất bại, dùng giao dịch:
try {
$pdo->beginTransaction();
// ... nhiều câu lệnh prepare/execute ...
$pdo->commit();
} catch (Throwable $e) {
$pdo->rollBack();
throw $e;
}charset khiến tiếng Việt bị lỗi hiển thị.password_hash.Với PDO và prepared statement, bạn vừa có code CRUD gọn vừa có lớp phòng thủ đầu tiên trước SQL Injection. Nhiều framework như Laravel dựa trên cùng nguyên lý này, nên hiểu rõ nền tảng sẽ giúp bạn dùng framework tự tin hơn.
Để học PHP và xây dựng ứng dụng web hoàn chỉnh, bạn có thể xem các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment