企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] * * * * * #1 数据库连接对象 >>数据库连接对象表示特定配置的数据库连接对象 >可以用来对整个数据库进行操作 ## 1 数据库连接对象配置操作 ### $db->getConfig() >> 获取数据库连接的配置参数 ~~~ public function getConfig($config = '') { return $config ? $this->config[$config] : $this->config; } ~~~ ### $db->setConfig() >> 修改数据库连接的配置参数 ~~~ public function setConfig($config, $value = '') { if (is_array($config)) { $this->config = array_merge($this->config, $config); } else { $this->config[$config] = $value; } } ~~~ ## 2 数据库连接初始化 ### $db->initConnect() >>初始化数据库连接(单数据库服务器) ~~~ protected function initConnect($master = true) { if (!empty($this->config['deploy'])) { // 采用分布式数据库 if ($master) { if (!$this->linkWrite) { $this->linkWrite = $this->multiConnect(true); } $this->linkID = $this->linkWrite; } else { if (!$this->linkRead) { $this->linkRead = $this->multiConnect(false); } $this->linkID = $this->linkRead; } } elseif (!$this->linkID) { // 默认单数据库 $this->linkID = $this->connect(); } } ~~~ ### $db->multiConnect() >>初始化数据库连接(分布式数据库服务器) ~~~ protected function multiConnect($master = false) { $_config = []; // 分布式数据库配置解析 foreach (['username', 'password', 'hostname', 'hostport', 'database', 'dsn', 'charset'] as $name) { $_config[$name] = explode(',', $this->config[$name]); } // 主服务器序号 $m = floor(mt_rand(0, $this->config['master_num'] - 1)); if ($this->config['rw_separate']) { // 主从式采用读写分离 if ($master) // 主服务器写入 { $r = $m; } elseif (is_numeric($this->config['slave_no'])) { // 指定服务器读 $r = $this->config['slave_no']; } else { // 读操作连接从服务器 每次随机连接的数据库 $r = floor(mt_rand($this->config['master_num'], count($_config['hostname']) - 1)); } } else { // 读写操作不区分服务器 每次随机连接的数据库 $r = floor(mt_rand(0, count($_config['hostname']) - 1)); } $dbMaster = false; if ($m != $r) { $dbMaster = []; foreach (['username', 'password', 'hostname', 'hostport', 'database', 'dsn', 'charset'] as $name) { $dbMaster[$name] = isset($_config[$name][$m]) ? $_config[$name][$m] : $_config[$name][0]; } } $dbConfig = []; foreach (['username', 'password', 'hostname', 'hostport', 'database', 'dsn', 'charset'] as $name) { $dbConfig[$name] = isset($_config[$name][$r]) ? $_config[$name][$r] : $_config[$name][0]; } return $this->connect($dbConfig, $r, $r == $m ? false : $dbMaster); } ~~~ #2 数据库操作 ## 1 基本操作 ### $db->query() >>执行数据库查询操作 ~~~ public function query($sql, $bind = [], $master = false, $class = false) { $this->initConnect($master); if (!$this->linkID) { return false; } // 根据参数绑定组装最终的SQL语句 $this->queryStr = $this->getRealSql($sql, $bind); //释放前次的查询结果 if (!empty($this->PDOStatement)) { $this->free(); } Db::$queryTimes++; try { // 调试开始 $this->debug(true); // 预处理 $this->PDOStatement = $this->linkID->prepare($sql); // 参数绑定 $this->bindValue($bind); // 执行查询 $result = $this->PDOStatement->execute(); // 调试结束 $this->debug(false); $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); return $this->getResult($class, $procedure); } catch (\PDOException $e) { throw new PDOException($e, $this->config, $this->queryStr); } } ~~~ ### $db->execute() >>执行数据库操作 ~~~ public function execute($sql, $bind = []) { $this->initConnect(true); if (!$this->linkID) { return false; } // 根据参数绑定组装最终的SQL语句 $this->queryStr = $this->getRealSql($sql, $bind); //释放前次的查询结果 if (!empty($this->PDOStatement)) { $this->free(); } Db::$executeTimes++; try { // 调试开始 $this->debug(true); // 预处理 $this->PDOStatement = $this->linkID->prepare($sql); // 参数绑定操作 $this->bindValue($bind); // 执行语句 $result = $this->PDOStatement->execute(); // 调试结束 $this->debug(false); $this->numRows = $this->PDOStatement->rowCount(); return $this->numRows; } catch (\PDOException $e) { throw new PDOException($e, $this->config, $this->queryStr); } } ~~~ ## 2 事务操作 ### $db->startTrans() >>启动事务 ~~~ public function startTrans() { $this->initConnect(true); if (!$this->linkID) { return false; } ++$this->transTimes; if (1 == $this->transTimes) { $this->linkID->beginTransaction(); } elseif ($this->transTimes > 1 && $this->supportSavepoint()) { $this->linkID->exec( $this->parseSavepoint('trans' . $this->transTimes) ); } } ~~~ ### $db->commit() >>事务操作提交 ~~~ public function commit() { $this->initConnect(true); if (1 == $this->transTimes) { $this->linkID->commit(); } --$this->transTimes; } ~~~ ### $db->rollback() >>事务操作回滚 ~~~ public function rollback() { $this->initConnect(true); if (1 == $this->transTimes) { $this->linkID->rollBack(); } elseif ($this->transTimes > 1 && $this->supportSavepoint()) { $this->linkID->exec( $this->parseSavepointRollBack('trans' . $this->transTimes) ); } $this->transTimes = max(0, $this->transTimes - 1); } ~~~ ### $db->transaction() >>执行数据库事务 ~~~ public function transaction($callback) { $this->startTrans(); try { $result = null; if (is_callable($callback)) { $result = call_user_func_array($callback, [$this]); } $this->commit(); return $result; } catch (\Exception $e) { $this->rollback(); throw $e; } catch (\Throwable $e) { $this->rollback(); throw $e; } } ~~~ #3 数据库操作信息 ## 3-1 SQL语句 ### $db->bindValue() >>sql语句参数绑定 ~~~ protected function bindValue(array $bind = []) { foreach ($bind as $key => $val) { // 占位符 $param = is_numeric($key) ? $key + 1 : ':' . $key; if (is_array($val)) { $result = $this->PDOStatement->bindValue($param, $val[0], $val[1]); } else { $result = $this->PDOStatement->bindValue($param, $val); } if (!$result) { throw new BindParamException( "Error occurred when binding parameters '{$param}'", $this->config, $this->queryStr, $bind ); } } } ~~~ ### $db->getRealSql() >> 获取拼接后的SQL语句 ~~~ public function getRealSql($sql, array $bind = []) { if ($bind) { foreach ($bind as $key => $val) { $value = is_array($val) ? $val[0] : $val; $type = is_array($val) ? $val[1] : PDO::PARAM_STR; if (PDO::PARAM_STR == $type) { $value = $this->quote($value); } // 判断占位符 $sql = is_numeric($key) ? substr_replace($sql, $value, strpos($sql, '?'), 1) : str_replace( [':' . $key . ')', ':' . $key . ',', ':' . $key . ' '], [$value . ')', $value . ',', $value . ' '], $sql . ' '); } } return $sql; } ~~~ ### $db->quote() >> SQL语句安全过滤 ~~~ public function quote($str, $master = true) { $this->initConnect($master); return $this->linkID ? $this->linkID->quote($str) : $str; } ~~~ ## 3-2 数据库操作运行信息 ### $db->getQueryTimes() >>获取查询次数 ~~~ public function getQueryTimes($execute = false) { return $execute ? Db::$queryTimes + Db::$executeTimes : Db::$queryTimes; } ~~~ ### $db->getExecuteTimes() >>获取执行次数 ~~~ public function getExecuteTimes() { return Db::$executeTimes; } ~~~ ### $db->getLastSql() >> 获取最近一次查询的sql语句 ~~~ public function getLastSql() { return $this->queryStr; } ~~~ ### $db->getLastInsID() >> 获取最近插入的ID ~~~ public function getLastInsID($sequence = null) { return $this->linkID->lastInsertId($sequence); } ~~~ ### $db->getNumRows() >> 获取影响的记录数 ~~~ public function getNumRows() { return $this->numRows; } ~~~ ### $db->getError() >> 获取最近的错误信息 ~~~ public function getError() { if ($this->PDOStatement) { $error = $this->PDOStatement->errorInfo(); $error = $error[1] . ':' . $error[2]; } else { $error = ''; } if ('' != $this->queryStr) { $error .= "\n [ SQL语句 ] : " . $this->queryStr; } return $error; } ~~~ # 4 拦截操作 ### __call() >> 调用Query的查询方法 ~~~ public function __call($method, $args) { if (!isset($this->query['database'])) { $this->query['database'] = new Query($this); } return call_user_func_array([$this->query['database'], $method], $args); } ~~~