PHP基于单例模式封装MySQL类实例
本文展示如何利用PHP的单例模式(Singleton Pattern)编写一个基础的MySQL数据库操作类。该设计通过限制外部实例化来保证系统中仅存在一个数据库连接对象,并提供封装好的SELECT、INSERT、UPDATE、DELETE等方法,简化日常的数据交互逻辑。
核心原理与设计目标
单例模式的核心在于确保一个类只有一个实例,并提供一个全局访问点。在数据库连接场景中,避免频繁创建和销毁连接能显著提升性能。本案例中的 db 类严格遵循以下规范:
- 私有的构造方法:阻止外部直接使用
new db()实例化对象。 - 私有的静态成员属性:用于存储唯一的连接实例(
$dbcon),防止被外部篡改。 - 私有的克隆方法:
__clone()为空实现,防止通过clone关键字复制对象产生新的连接。 - 公有的静态方法:
getIntance()作为获取唯一实例的入口,内部判断若实例不存在则自行创建。
第1步:定义单例结构与连接参数
首先初始化类的结构,设置静态属性 $dbcon 初始为 false,并编写私有构造函数处理数据库连接逻辑。
<?php
// 配置常量可替换硬编码值
$host = "localhost";
$user = "root";
$pass = "root";
$dbname = "small2";
class db {
// 私有的静态属性
private static $dbcon = false;
// 私有的构造方法
private function __construct() {
@mysql_connect($host, $user, $pass) or die("mysql_connect error");
mysql_select_db($dbname) or die("database select error");
mysql_query("set names utf8");
}
// 私有的克隆方法
private function __clone() {}
// 公共静态方法:获取实例
public static function getIntance() {
if(self::$dbcon == false) {
self::$dbcon = new self();
}
return self::$dbcon;
}
}
?>
完成状态:成功创建一个无法从外部实例化,且能通过 db::getIntance() 获取唯一连接的类骨架。
第2步:实现调试与结果辅助方法
为了方便测试和查看数据返回,添加两个辅助输出方法,分别用于格式化打印数组和变量详细类型。
public function p($arr){
echo "<pre>";
print_r($arr);
echo "</pre>";
}
public function v($arr){
echo "<pre>";
var_dump($arr);
echo "</pre>";
}
第3步:封装基础查询方法
这是数据库操作的核心部分。该类封装了执行SQL语句、获取单个字段、获取一行记录以及获取多条记录的功能。
// 执行通用SQL语句
public function query($sql){
$query = mysql_query($sql);
return $query;
}
// 获取某个字段的第一条记录 (标量)
public function getOne($sql){
$query = $this->query($sql);
return mysql_result($query, 0);
}
// 获取一行记录,支持 assoc/array/row 格式
public function getRow($sql, $type="assoc"){
$query = $this->query($sql);
if(!in_array($type, array("assoc",'array',"row"))){
die("Invalid fetch type");
}
$funcname = "mysql_fetch_".$type;
return $funcname($query);
}
// 获取多条记录 (二维数组)
public function getAll($sql){
$query = $this->query($sql);
$list = array();
while ($r = $this->getRow($query)) { // 注意:原代码此处调用getFormSource或getRow逻辑相似
$list[] = $r;
}
return $list;
}
关键提示:在使用时,务必先通过 $db = db::getIntance() 获取实例,再调用上述方法。例如:$data = $db->getAll('select * from users');
第4步:封装增、删、改高级操作方法
针对常用的CRUD操作进行封装,提高重复代码编写的效率。注意处理数组数据的拼接逻辑。
// 插入数据
public function insert($table, $data){
foreach($data as $key=>$v){
$keys[] = '`'.$key.'`';
$vals[] = "'".addslashes($v)."'";
}
$sql = "INSERT INTO `{$table}` (" . implode(',', $keys) . ") VALUES (" . implode(',', $vals) . ")";
$this->query($sql);
return mysql_insert_id();
}
// 删除单条或多条 (支持简单条件数组或字符串)
public function delete($table, $where){
$condition = '';
if(is_array($where)){
foreach ($where as $key => $val) {
if(is_array($val)){
$condition .= "$key IN (".implode(',', $val).") AND ";
} else {
$condition .= "$key='".addslashes($val)."' AND ";
}
}
$condition = rtrim($condition, 'AND '); // 去除尾部AND
} else {
$condition = $where;
}
$sql = "DELETE FROM `{$table}` WHERE {$condition}";
return $this->query($sql);
}
// 更新数据
public function update($table, $data, $where){
foreach($data as $key=>$v){
$sets[] = "$key='".addslashes($v)."'";
}
$sql = "UPDATE `{$table}` SET " . implode(',', $sets) . " WHERE $where";
return $this->query($sql);
}
使用说明与安全警告
1. 获取实例
所有数据库操作前必须调用静态方法获取单例:
$db = db::getIntance();
2. ⚠️ 重要安全风险提醒
原文示例中使用的 mysql_* 系列函数(如 mysql_connect, mysql_query)在 PHP 5.5.0 中已被废弃,并在 PHP 7.0.0 中被彻底移除。如果在现代PHP环境(PHP 7/8)中运行上述代码,将无法执行甚至导致致命错误。
此外,原文 insert 和 update 方法直接拼接变量到SQL语句中,极易受到 SQL注入攻击。虽然添加了简单的 addslashes,但这不是防御注入的最佳实践。
3. 改进建议
- 升级驱动:强烈建议使用
PDO或MySQLi扩展重写此类。 - 预处理语句:在INSERT/UPDATE/DELETE操作中,必须使用预处理语句(Prepared Statements)绑定参数,而非简单的字符串拼接,以彻底杜绝SQL注入。
总结
以上介绍了基于单例模式的MySQL类封装方法。该模式能有效管理单一数据库连接。但鉴于技术演进,建议在个人学习后将其转换为基于PDO或ORM的现代架构,以确保系统的安全性与兼容性。以上就是关于PHP基于单例模式封装mysql类的详细内容,更多关于PHP单例设计与数据库安全的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













