在 PHP 开发中,数据库连接是基础且关键的一环。一个高效且安全的数据库连接类不仅能够简化开发流程,还能有效防止 SQL 注入等安全风险。本文将介绍如何封装一个安全的 connect() 函数,并实现防止 SQL 注入的数据库连接方式。
直接使用原生的 mysqli_connect() 或 PDO 连接数据库虽然方便,但缺乏封装的话,代码易重复且难维护。通过面向对象封装,可以实现:
统一管理数据库连接配置
提高代码复用性
集中处理异常和错误
结合预处理语句防止 SQL 注入
PHP 中推荐使用 PDO(PHP Data Objects)作为数据库连接接口,理由:
支持多种数据库,代码可移植性高
内置预处理语句,防止 SQL 注入
异常处理机制完善
<?php
class Database {
private $host = 'localhost';
private $dbname = 'testdb';
private $username = 'root';
private $password = 'password';
private $pdo;
private $error;
// 构造函数,初始化连接
public function __construct() {
$dsn = "mysql:host={$this->host};dbname={$this->dbname};charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 抛出异常
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认关联数组
PDO::ATTR_EMULATE_PREPARES => false, // 禁用模拟预处理,使用原生预处理
];
try {
$this->pdo = new PDO($dsn, $this->username, $this->password, $options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
// 记录日志或处理错误
die("数据库连接失败: " . $this->error);
}
}
// 统一执行查询(SELECT)
public function query($sql, $params = []) {
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
// 统一执行增删改(INSERT/UPDATE/DELETE)
public function execute($sql, $params = []) {
$stmt = $this->pdo->prepare($sql);
return $stmt->execute($params);
}
// 获取最后插入ID
public function lastInsertId() {
return $this->pdo->lastInsertId();
}
}
?>
<?php
$db = new Database();
// 安全查询示例:防止 SQL 注入
$userId = 123;
$result = $db->query("SELECT * FROM users WHERE id = :id", ['id' => $userId]);
// 安全插入示例
$name = '张三';
$email = 'zhangsan@m66.net';
$insertSql = "INSERT INTO users (name, email) VALUES (:name, :email)";
$db->execute($insertSql, ['name' => $name, 'email' => $email]);
?>
使用 PDO 预处理语句,SQL 语句与数据分离,用户输入不会直接拼接到 SQL 字符串中
参数绑定让数据库驱动自动处理特殊字符转义
禁用模拟预处理,使用原生预处理增强安全性
封装一个 connect() 函数的数据库连接类,选择 PDO 作为底层连接,结合预处理语句,是 PHP 中防止 SQL 注入的高效且安全方案。该类的设计简洁且易于扩展,可以满足大多数业务需求,是现代 PHP 开发的推荐做法。