这个类封装了对 MySQL 数据库的常用操作,主要优势有:
处理离线或超时连接:通过在操作前检查连接是否有效, 如果失效就重新连接,避免出现离线或超时的错误.
方法用于在创建 Mysql 类的新实例时初始化连接到 MySQL 服务器所需的信息。
更具体地说, 它在类初始化时需要一个配置数组作为参数, 这个数组包含连接到 MySQL 服务器所需的主机名,用户名,密码,数据库名称和超时时间。
构造函数会把这些信息保存到类的私有变量中,并且使用这些变量来创建连接数据库的实例. 如果连接失败,则会打印一条消息并终止程序运行。
public function __construct($config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
$this->timeout = $config['timeout'];
$this->conn = new mysqli($this->host, $this->username, $this->password, $this->database);
if ($this->conn->connect_error) {
die('Connection failed: ' . $this->conn->connect_error);
}
$this->conn->options(MYSQLI_OPT_CONNECT_TIMEOUT, $this->timeout);
}
public function Operate($data) {
//检查连接是否有效
if(!$this->conn->ping()) {
$this->conn->close();
$this->conn = mysqli_init();
mysqli_options($this->conn, MYSQLI_OPT_CONNECT_TIMEOUT, $this->timeout);
if(!mysqli_real_connect($this->conn, $this->host, $this->username, $this->password, $this->database)) {
throw new Exception('Error: '.mysqli_connect_error());
}
}
//验证数组合法性
$ArrayKeyJoining = $this->ArrayKeyJoining($data);
$ArrayKeyJoining = str_replace(".Sort", "", $ArrayKeyJoining);
switch ($ArrayKeyJoining) {
case 'Insert.Table.Data':
# 增与批量增
$Sql = $this->SqlStr($data,'Insert');
$type = 'Num';
break;
case 'Delete.Table.Key.KeyValue':
# 主键删除
$Sql = $this->SqlStr($data,'Delete','Key');
$type = 'Num';
break;
case 'Delete.Table.Filter':
# 条件删除
$Sql = $this->SqlStr($data,'Delete','Filter');
$type = 'Num';
break;
case 'Modify.Table.Key.KeyValue.Data':
# 主键改
$Sql = $this->SqlStr($data,'Modify','Key');
$type = 'Num';
break;
case 'Modify.Table.Filter.Data':
# 筛选改
$Sql = $this->SqlStr($data,'Modify','Filter');
$type = 'Num';
//var_dump($Sql);die();
break;
case 'Query.Table.Num.Filter':
# 查询
$Sql = $this->SqlStr($data,'Query');
$type = 'Result';
//var_dump($Sql);die();
break;
case 'Query.Table.Num.Page.Filter':
# 分页查询
$Sql = $this->SqlStr($data,'Query','Pag');
$type = 'Pag';
break;
default:
return ['State' => false,'error' => '传递参数错误'];
break;
}
// 执行操作 无需返回数据
if ($type == 'Num') {
if ($this->conn->query($Sql) === TRUE) {
return ['State' => TRUE,'Message' => $this->conn->affected_rows];
} else {
return ['State' => false,'error' => $this->conn->error];
}
}
// 执行操作 只需返回数据
if ($type == 'Result') {
// 执行查询
$result = $this->conn->query($Sql);
if ($result === false) {
return ['State' => false,'error' => $this->conn->error];
}
// 将查询结果转换为数组
$rows = [];
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
return ['State' => TRUE,'Data' => $rows];
}
//执行操作 分页
if ($type == 'Pag') {
// 执行查询
$result = $this->conn->query($Sql['Sql']);
if ($result === false) {
return ['State' => false,'error' => $this->conn->error];
}
// 将查询结果转换为数组
$rows = [];
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
// 获取总记录数
$totalResult = $this->conn->query($Sql['SqlTotal']);
$totalRow = $totalResult->fetch_assoc();
$total = $totalRow['COUNT'];//数据总量
// 计算总页数
$totalPages = ceil($total / $data['Query']['Num']);
return ['State' => TRUE,'Total' =>$total, 'PageCount' =>$totalPages,'Current' =>$data['Query']['Page'],'Num' => $data['Query']['Num'],'Data' => $rows];
}
}
public function SqlStr($data,$type,$Class = '') {
// var_dump($data[$type]);die();
$escapedValues = $this->EscapeStrings($data[$type]);
//var_dump($escapedValues);
$Table = $escapedValues["Table"];//表名称
// 准备增Sql语句
if ($type == 'Insert') {
//获取字段
$Field = array_keys($escapedValues["Data"][0]);
$FieldStr = implode(',', $Field);
//获取值
$Value = [];
foreach ($escapedValues["Data"] as $value) {
$Value[] = "('" . implode("','", $value) . "')";
}
$ValueStr = implode(',', $Value);
return "INSERT INTO `$Table` ($FieldStr) VALUES $ValueStr";
}
// 准备主键删除Sql语句
if ($type == 'Delete' && $Class == 'Key') {
$Key = $escapedValues["Key"];//获取主键
//获取值
$Value = [];
foreach ($escapedValues["KeyValue"] as $value) {
$Value[] = $value;
}
$ValueStr = implode(',', $Value);
return "DELETE FROM `$Table` WHERE `$Key` IN ($ValueStr)";
}
// 准备条件删除Sql语句
if ($type == 'Delete' && $Class == 'Filter') {
$Filter = $this->Filter($escapedValues['Filter']);//筛选条件
return "DELETE FROM `$Table` WHERE $Filter";
}
// 准备主键修改Sql语句
if ($type == 'Modify' && $Class == 'Key') {
$Key = $escapedValues["Key"];//获取主键
$KeyValue=[];
foreach ($escapedValues["KeyValue"] as $value) {
if (!is_numeric($value)) {
die('error: 主键值只能是int');
}
$KeyValue[]=$value;
}
$KeyStr = implode(',', $KeyValue);
$DataValue=[];
foreach ($escapedValues["Data"] as $key => $value) {
$DataValue[]= "`".$key."` = '".$value."'";
}
$DataStr = implode(' , ', $DataValue);
return "UPDATE `$Table` SET $DataStr WHERE $Key IN ($KeyStr)";
}
//准备条件修改SQL语句
if ($type == 'Modify' && $Class == 'Filter') {
$Filter = $this->Filter($escapedValues['Filter']);//筛选条件
$DataValue=[];
foreach ($escapedValues["Data"] as $key => $value) {
$DataValue[]= "`".$key."` = '".$value."'";
}
$DataStr = implode(' , ', $DataValue);
return "UPDATE `$Table` SET $DataStr WHERE $Filter";
}
//准备查询Sql语句
if ($type == 'Query' && $Class == '') {
$Num = $escapedValues["Num"];//获取条数
if (!is_int($Num)) {
die('error: Num只能是INT');
}
$Filter = $this->Filter($escapedValues['Filter']);//筛选条件
$Sort ='';
if (isset($escapedValues["Sort"])) {
$Sort = $this->Sort($escapedValues['Sort']);//排序
}
return "SELECT * FROM `$Table` WHERE $Filter $Sort LIMIT $Num";
}
//准备分页查询Sql语句
if ($type == 'Query' && $Class == 'Pag') {
$Page = $escapedValues["Page"];//获取当前页
$Num = $escapedValues["Num"];//获取条数
if (!is_int($Num) && !is_int($Page) ) {
die('error: Num与Page只能是INT');
}
$offset = ($Page - 1) * $Num;//计算起始条数
$Filter = $this->Filter($escapedValues['Filter']);//筛选条件
$Sort ='';
if (isset($escapedValues["Sort"])) {
$Sort = $this->Sort($escapedValues['Sort']);//排序
}
return ['Sql' => "SELECT * FROM `$Table` WHERE $Filter $Sort LIMIT $offset,$Num" , 'SqlTotal'=>"SELECT COUNT(*) AS COUNT FROM `$Table` WHERE $Filter"];
}
$this->conn->close();
}
//组装排序
public function Sort($Sort){
if (count($Sort) >=3) {
die('error: 排序参数超过两个');
}elseif (count($Sort) == 1) {
return " ORDER BY `$Sort[0]`";
}elseif (count($Sort) == 2) {
if ($Sort[1] == 'DESC' || $Sort[1] == 'ASC') {
return " ORDER BY `$Sort[0]` $Sort[1]";
}else{
die('error: 排序类型只能是DESC或ASC');
}
}else{
die('error: 排序参数错误');
}
}
//组装筛选条件
public function Filter($Filter){
$FilterArray=[];
foreach ($Filter as $value) {
if (count($value) == 1) {
if ($value[0] == 'AND' OR $value[0] == 'OR' ) {
$FilterArray[]=$value[0];
}else{
die('error: 筛选连接符只能是AND或OR');
}
} else if (count($value) == 3) {
$FilterArray[] = '`'.$value[0].'`' . ' ' . $value[1] . " '" . $value[2]."'";
}else {
die('error: 筛选值不正确');
}
}
// 将数组中的元素用 AND 或 OR 连接起来
return implode(' ', $FilterArray);
}
//检测字符串合法性方法
public function ArrayKeyJoining($data){
if ($this->is_2d_array($data)) {
$ArrayKeyJoining='';
foreach ($data as $key_1 => $value_1) {
$ArrayKeyJoining .=$key_1;
foreach ($value_1 as $key_2 => $value_2) {
$ArrayKeyJoining .='.'.$key_2;
}
if (!is_string($data[$key_1]['Table'])) {
die('error: Table只能是字符串');
}
}
return $ArrayKeyJoining;
}else{
die('error: 传递参数必须是一个二维数组');
}
}
//转义数组中的每个字符串方法 起到预防sql攻击
private function EscapeStrings($data) {
if (is_array($data)) {
$escapedData = [];
foreach ($data as $key => $value) {
$escapedData[$key] = $this->escapeStrings($value);
}
return $escapedData;
} else if (is_string($data)) {
return $this->conn->real_escape_string($data);
} else {
return $data;
}
}
//判断是否是二维数组方法
public function is_2d_array($arr) {
if (!is_array($arr)) {
return false;
}
foreach ($arr as $item) {
if (!is_array($item)) {
return false;
}
}
return true;
}
// 增
$data = ['operation' => 'Insert','table' => 'TableName','data' => [
['ip_id' => 888, 'address_id' => 88, 'isp_id' => 88],
['ip_id' => 6, 'address_id' => 666, 'isp_id' => 666],
]
];
// 删
$data = ['operation' => 'Delete','table' => 'TableName','filter' => [
['ip_id', '>=', 888],
['AND'],
['ip_id', '<=', 98248429]
]
];
$data = ['operation' => 'Delete','table' => 'TableName','key' => 'ip_id','key_value' => [1, 2, 3, 4, 5, 6],];
// 改
$data = ['operation' => 'Modify','table' => 'TableName','filter' => [
['ip_id', '=', 167292492],
['OR'],
['ip_id', '=', 501131500],
],
'data' => [
'address_id' => 'asdasd',
]
];
$data = ['operation' => 'Modify','table' => 'TableName','key' => 'ip_id','key_value' => [326165381, 368344353, 501131500],
'data' => ['address_id' => 6,]
];
// 查
$data = ['operation' => 'Query','table' => 'TableName','num' => 10,'filter' => [
['ip_id', '>', 167292492],
['AND'],
['ip_id', '<', 784746588],
],
'sort' => ['ip_id', 'DESC']
];
$data = ['operation' => 'Query','table' => 'TableName','num' => 2,'page' => 3,'filter' => [
['ip_id', '>', 167292492],
['AND'],
['ip_id', '<', 1002378841],
],
'sort' => ['ip_id', 'DESC']
];
class Mysql {
private $host;
private $username;
private $password;
private $database;
private $conn;
private $timeout; //超时时间变量
public function __construct( $config ) {
// 从配置数组中获取数据库连接信息
$this->host = $config[ 'host' ];
$this->username = $config[ 'username' ];
$this->password = $config[ 'password' ];
$this->database = $config[ 'database' ];
$this->timeout = $config[ 'timeout' ]; //获取超时时间
// 创建数据库连接
$this->conn = new mysqli( $this->host, $this->username, $this->password, $this->database );
if ( $this->conn->connect_error ) {
die( 'Connection failed: ' . $this->conn->connect_error );
}
$this->conn->options( MYSQLI_OPT_CONNECT_TIMEOUT, $this->timeout ); //设置超时时间
}
//操作
public function Operate( $data ) {
//检查连接是否有效
if ( !$this->conn->ping() ) {
$this->conn->close();
$this->conn = mysqli_init();
mysqli_options( $this->conn, MYSQLI_OPT_CONNECT_TIMEOUT, $this->timeout );
if ( !mysqli_real_connect( $this->conn, $this->host, $this->username, $this->password, $this->database ) ) {
throw new Exception( 'Error: ' . mysqli_connect_error() );
}
}
//验证数组合法性
$ArrayKeyJoining = $this->ArrayKeyJoining( $data );
$ArrayKeyJoining = str_replace( ".Sort", "", $ArrayKeyJoining );
switch ( $ArrayKeyJoining ) {
case 'Insert.Table.Data':
# 增与批量增
$Sql = $this->SqlStr( $data, 'Insert' );
$type = 'Num';
break;
case 'Delete.Table.Key.KeyValue':
# 主键删除
$Sql = $this->SqlStr( $data, 'Delete', 'Key' );
$type = 'Num';
break;
case 'Delete.Table.Filter':
# 条件删除
$Sql = $this->SqlStr( $data, 'Delete', 'Filter' );
$type = 'Num';
break;
case 'Modify.Table.Key.KeyValue.Data':
# 主键改
$Sql = $this->SqlStr( $data, 'Modify', 'Key' );
$type = 'Num';
break;
case 'Modify.Table.Filter.Data':
# 筛选改
$Sql = $this->SqlStr( $data, 'Modify', 'Filter' );
$type = 'Num';
//var_dump($Sql);die();
break;
case 'Query.Table.Num.Filter':
# 查询
$Sql = $this->SqlStr( $data, 'Query' );
$type = 'Result';
//var_dump($Sql);die();
break;
case 'Query.Table.Num.Page.Filter':
# 分页查询
$Sql = $this->SqlStr( $data, 'Query', 'Pag' );
$type = 'Pag';
break;
default:
return [ 'State' => false, 'error' => '传递参数错误' ];
break;
}
// 执行操作 无需返回数据
if ( $type == 'Num' ) {
if ( $this->conn->query( $Sql ) === TRUE ) {
return [ 'State' => TRUE, 'Message' => $this->conn->affected_rows ];
} else {
return [ 'State' => false, 'error' => $this->conn->error ];
}
}
// 执行操作 只需返回数据
if ( $type == 'Result' ) {
// 执行查询
$result = $this->conn->query( $Sql );
if ( $result === false ) {
return [ 'State' => false, 'error' => $this->conn->error ];
}
// 将查询结果转换为数组
$rows = [];
while ( $row = $result->fetch_assoc() ) {
$rows[] = $row;
}
return [ 'State' => TRUE, 'Data' => $rows ];
}
//执行操作 分页
if ( $type == 'Pag' ) {
// 执行查询
$result = $this->conn->query( $Sql[ 'Sql' ] );
if ( $result === false ) {
return [ 'State' => false, 'error' => $this->conn->error ];
}
// 将查询结果转换为数组
$rows = [];
while ( $row = $result->fetch_assoc() ) {
$rows[] = $row;
}
// 获取总记录数
$totalResult = $this->conn->query( $Sql[ 'SqlTotal' ] );
$totalRow = $totalResult->fetch_assoc();
$total = $totalRow[ 'COUNT' ]; //数据总量
// 计算总页数
$totalPages = ceil( $total / $data[ 'Query' ][ 'Num' ] );
return [ 'State' => TRUE, 'Total' => $total, 'PageCount' => $totalPages, 'Current' => $data[ 'Query' ][ 'Page' ], 'Num' => $data[ 'Query' ][ 'Num' ], 'Data' => $rows ];
}
}
//拼接SQL语句
public function SqlStr( $data, $type, $Class = '' ) {
// var_dump($data[$type]);die();
$escapedValues = $this->EscapeStrings( $data[ $type ] );
//var_dump($escapedValues);
$Table = $escapedValues[ "Table" ]; //表名称
// 准备增Sql语句
if ( $type == 'Insert' ) {
//获取字段
$Field = array_keys( $escapedValues[ "Data" ][ 0 ] );
$FieldStr = implode( ',', $Field );
//获取值
$Value = [];
foreach ( $escapedValues[ "Data" ] as $value ) {
$Value[] = "('" . implode( "','", $value ) . "')";
}
$ValueStr = implode( ',', $Value );
return "INSERT INTO `$Table` ($FieldStr) VALUES $ValueStr";
}
// 准备主键删除Sql语句
if ( $type == 'Delete' && $Class == 'Key' ) {
$Key = $escapedValues[ "Key" ]; //获取主键
//获取值
$Value = [];
foreach ( $escapedValues[ "KeyValue" ] as $value ) {
$Value[] = $value;
}
$ValueStr = implode( ',', $Value );
return "DELETE FROM `$Table` WHERE `$Key` IN ($ValueStr)";
}
// 准备条件删除Sql语句
if ( $type == 'Delete' && $Class == 'Filter' ) {
$Filter = $this->Filter( $escapedValues[ 'Filter' ] ); //筛选条件
return "DELETE FROM `$Table` WHERE $Filter";
}
// 准备主键修改Sql语句
if ( $type == 'Modify' && $Class == 'Key' ) {
$Key = $escapedValues[ "Key" ]; //获取主键
$KeyValue = [];
foreach ( $escapedValues[ "KeyValue" ] as $value ) {
if ( !is_numeric( $value ) ) {
die( 'error: 主键值只能是int' );
}
$KeyValue[] = $value;
}
$KeyStr = implode( ',', $KeyValue );
$DataValue = [];
foreach ( $escapedValues[ "Data" ] as $key => $value ) {
$DataValue[] = "`" . $key . "` = '" . $value . "'";
}
$DataStr = implode( ' , ', $DataValue );
return "UPDATE `$Table` SET $DataStr WHERE $Key IN ($KeyStr)";
}
//准备条件修改SQL语句
if ( $type == 'Modify' && $Class == 'Filter' ) {
$Filter = $this->Filter( $escapedValues[ 'Filter' ] ); //筛选条件
$DataValue = [];
foreach ( $escapedValues[ "Data" ] as $key => $value ) {
$DataValue[] = "`" . $key . "` = '" . $value . "'";
}
$DataStr = implode( ' , ', $DataValue );
return "UPDATE `$Table` SET $DataStr WHERE $Filter";
}
//准备查询Sql语句
if ( $type == 'Query' && $Class == '' ) {
$Num = $escapedValues[ "Num" ]; //获取条数
if ( !is_int( $Num ) ) {
die( 'error: Num只能是INT' );
}
$Filter = $this->Filter( $escapedValues[ 'Filter' ] ); //筛选条件
$Sort = '';
if ( isset( $escapedValues[ "Sort" ] ) ) {
$Sort = $this->Sort( $escapedValues[ 'Sort' ] ); //排序
}
return "SELECT * FROM `$Table` WHERE $Filter $Sort LIMIT $Num";
}
//准备分页查询Sql语句
if ( $type == 'Query' && $Class == 'Pag' ) {
$Page = $escapedValues[ "Page" ]; //获取当前页
$Num = $escapedValues[ "Num" ]; //获取条数
if ( !is_int( $Num ) && !is_int( $Page ) ) {
die( 'error: Num与Page只能是INT' );
}
$offset = ( $Page - 1 ) * $Num; //计算起始条数
$Filter = $this->Filter( $escapedValues[ 'Filter' ] ); //筛选条件
$Sort = '';
if ( isset( $escapedValues[ "Sort" ] ) ) {
$Sort = $this->Sort( $escapedValues[ 'Sort' ] ); //排序
}
return [ 'Sql' => "SELECT * FROM `$Table` WHERE $Filter $Sort LIMIT $offset,$Num", 'SqlTotal' => "SELECT COUNT(*) AS COUNT FROM `$Table` WHERE $Filter" ];
}
$this->conn->close();
}
//组装排序
public function Sort( $Sort ) {
if ( count( $Sort ) >= 3 ) {
die( 'error: 排序参数超过两个' );
} elseif ( count( $Sort ) == 1 ) {
return " ORDER BY `$Sort[0]`";
} elseif ( count( $Sort ) == 2 ) {
if ( $Sort[ 1 ] == 'DESC' || $Sort[ 1 ] == 'ASC' ) {
return " ORDER BY `$Sort[0]` $Sort[1]";
} else {
die( 'error: 排序类型只能是DESC或ASC' );
}
} else {
die( 'error: 排序参数错误' );
}
}
//组装筛选条件
public function Filter( $Filter ) {
$FilterArray = [];
foreach ( $Filter as $value ) {
if ( count( $value ) == 1 ) {
if ( $value[ 0 ] == 'AND'
OR $value[ 0 ] == 'OR' ) {
$FilterArray[] = $value[ 0 ];
} else {
die( 'error: 筛选连接符只能是AND或OR' );
}
} else if ( count( $value ) == 3 ) {
$FilterArray[] = '`' . $value[ 0 ] . '`' . ' ' . $value[ 1 ] . " '" . $value[ 2 ] . "'";
} else {
die( 'error: 筛选值不正确' );
}
}
// 将数组中的元素用 AND 或 OR 连接起来
return implode( ' ', $FilterArray );
}
//检测字符串合法性方法
public function ArrayKeyJoining( $data ) {
if ( $this->is_2d_array( $data ) ) {
$ArrayKeyJoining = '';
foreach ( $data as $key_1 => $value_1 ) {
$ArrayKeyJoining .= $key_1;
foreach ( $value_1 as $key_2 => $value_2 ) {
$ArrayKeyJoining .= '.' . $key_2;
}
if ( !is_string( $data[ $key_1 ][ 'Table' ] ) ) {
die( 'error: Table只能是字符串' );
}
}
return $ArrayKeyJoining;
} else {
die( 'error: 传递参数必须是一个二维数组' );
}
}
//转义数组中的每个字符串方法 起到预防sql攻击
private function EscapeStrings( $data ) {
if ( is_array( $data ) ) {
$escapedData = [];
foreach ( $data as $key => $value ) {
$escapedData[ $key ] = $this->escapeStrings( $value );
}
return $escapedData;
} else if ( is_string( $data ) ) {
return $this->conn->real_escape_string( $data );
} else {
return $data;
}
}
//判断是否是二维数组方法
public function is_2d_array( $arr ) {
if ( !is_array( $arr ) ) {
return false;
}
foreach ( $arr as $item ) {
if ( !is_array( $item ) ) {
return false;
}
}
return true;
}
}