You are a helpful assistant.
system
Tạo tập lệnh PHP kết nối với cơ sở dữ liệu MySQL và thực hiện các thao tác CRUD trên bảng "sản phẩm", yêu cầu xác thực người dùng trước khi thực hiện, sử dụng các câu lệnh đã chuẩn bị để ngăn chặn tấn công SQL injection, ghi lại các hành động cho mục đích kiểm toán, và hỗ trợ phân trang cho các thao tác đọc để quản lý dữ liệu lớn.
user
Để tạo một tập lệnh PHP thực hiện các yêu cầu của bạn, chúng ta sẽ cần sử dụng PDO để kết nối với cơ sở dữ liệu MySQL, thực hiện các thao tác CRUD, và sử dụng các câu lệnh đã chuẩn bị (prepared statements) để ngăn chặn SQL injection. Chúng ta cũng sẽ thêm phần xác thực người dùng và ghi lại các hành động cho mục đích kiểm toán. Dưới đây là một ví dụ cơ bản:

```php
<?php
session_start();

// Hàm kết nối cơ sở dữ liệu
function getDbConnection() {
    $host = 'localhost';
    $db = 'ten_cua_so_du_lieu';
    $user = 'ten_nguoi_dung';
    $pass = 'mat_khau';
    $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 {
        return new PDO($dsn, $user, $pass, $options);
    } catch (\PDOException $e) {
        throw new \PDOException($e->getMessage(), (int)$e->getCode());
    }
}

// Hàm xác thực người dùng
function authenticateUser($username, $password) {
    // Giả sử bạn có một bảng người dùng để xác thực
    $pdo = getDbConnection();
    $stmt = $pdo->prepare('SELECT * FROM users WHERE username = ?');
    $stmt->execute([$username]);
    $user = $stmt->fetch();

    if ($user && password_verify($password, $user['password'])) {
        $_SESSION['user_id'] = $user['id'];
        return true;
    }
    return false;
}

// Hàm kiểm tra xem người dùng đã đăng nhập chưa
function isAuthenticated() {
    return isset($_SESSION['user_id']);
}

// Hàm ghi lại hành động
function logAction($action, $details) {
    $pdo = getDbConnection();
    $stmt = $pdo->prepare('INSERT INTO audit_log (user_id, action, details, timestamp) VALUES (?, ?, ?, NOW())');
    $stmt->execute([$_SESSION['user_id'], $action, $details]);
}

// Hàm tạo sản phẩm
function createProduct($name, $price) {
    if (!isAuthenticated()) {
        throw new Exception('User not authenticated');
    }

    $pdo = getDbConnection();
    $stmt = $pdo->prepare('INSERT INTO san_pham (name, price) VALUES (?, ?)');
    $stmt->execute([$name, $price]);

    logAction('create', "Created product: $name");
}

// Hàm đọc sản phẩm với phân trang
function readProducts($page = 1, $itemsPerPage = 10) {
    if (!isAuthenticated()) {
        throw new Exception('User not authenticated');
    }

    $pdo = getDbConnection();
    $offset = ($page - 1) * $itemsPerPage;
    $stmt = $pdo->prepare('SELECT * FROM san_pham LIMIT ? OFFSET ?');
    $stmt->bindValue(1, $itemsPerPage, PDO::PARAM_INT);
    $stmt->bindValue(2, $offset, PDO::PARAM_INT);
    $stmt->execute();

    logAction('read', "Read products page: $page");
    return $stmt->fetchAll();
}

// Hàm cập nhật sản phẩm
function updateProduct($id, $name, $price) {
    if (!isAuthenticated()) {
        throw new Exception('User not authenticated');
    }

    $pdo = getDbConnection();
    $stmt = $pdo->prepare('UPDATE san_pham SET name = ?, price = ? WHERE id = ?');
    $stmt->execute([$name, $price, $id]);

    logAction('update', "Updated product ID: $id");
}

// Hàm xóa sản phẩm
function deleteProduct($id) {
    if (!isAuthenticated()) {
        throw new Exception('User not authenticated');
    }

    $pdo = getDbConnection();
    $stmt = $pdo->prepare('DELETE FROM san_pham WHERE id = ?');
    $stmt->execute([$id]);

    logAction('delete', "Deleted product ID: $id");
}

// Ví dụ sử dụng
try {
    if (authenticateUser('username', 'password')) {
        createProduct('Sản phẩm mới', 100000);
        $products = readProducts(1, 10);
        updateProduct(1, 'Sản phẩm cập nhật', 120000);
        deleteProduct(1);
    } else {
        echo "Authentication failed.";
    }
} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage();
}
?>
```

Lưu ý:
- Bạn cần thay thế các thông tin kết nối cơ sở dữ liệu (`$host`, `$db`, `$user`, `$pass`) bằng thông tin thực tế của bạn.
- Bảng `users` và `audit_log` cần được tạo trong cơ sở dữ liệu của bạn để lưu trữ thông tin người dùng và ghi lại các hành động.
- Mật khẩu người dùng nên được lưu trữ dưới dạng băm (hash) trong cơ sở dữ liệu, và bạn có thể sử dụng `password_hash()` để tạo băm và `password_verify()` để xác thực.
- Đây chỉ là một ví dụ cơ bản, bạn cần điều chỉnh và bảo mật thêm cho phù hợp với ứng dụng thực tế của mình.
assistant