This commit is contained in:
Gitea
2022-01-24 10:43:35 +08:00
commit 15dfc6576b
786 changed files with 219240 additions and 0 deletions

50
core/database/Builder.php Normal file
View File

@@ -0,0 +1,50 @@
<?php
/**
* @copyright (C)2016-2099 Hnaoyun Inc.
* @author XingMeng
* @email hnxsh@foxmail.com
* @date 2017年8月23日
* 数据库连接器基类
*/
namespace core\database;
interface Builder
{
// 获取单一实例,使用单一实例数据库连接类
public static function getInstance();
// 连接数据库,接受数据库连接参数,返回数据库连接对象
public function conn($cfg);
// 执行SQL语句,接受完整SQL语句返回结果集对象
public function query($sql, $type = 'master');
// 数据是否存在模型接受完整SQL语句返回boolean数据
public function isExist($sql);
// 获取记录总量模型接受数据库表名返回int数据
public function rows($table);
// 读取字段数量模型接受数据库表名返回int数据
public function fields($table);
// 获取表字段,接受数据库表名,返回表字段数组
public function tableFields($table);
// 查询一条数据模型接受完整SQL语句有数据返回对象数组否则空数组
public function one($sql, $type = null);
// 查询多条数据模型接受完整SQL语句有数据返回二维对象数组否则空数组
public function all($sql, $type = null);
// 数据增、删、改模型接受完整SQL语句返回影响的行数的int数据
public function amd($sql);
// 最近一次插入数据的自增字段值返回int数据
public function insertId();
// 执行多条SQL模型成功返回true,否则false
public function multi($sql);
}

263
core/database/Mysqli.php Normal file
View File

@@ -0,0 +1,263 @@
<?php
/**
* @copyright (C)2016-2099 Hnaoyun Inc.
* @author XingMeng
* @email hnxsh@foxmail.com
* @date 2016年11月6日
* 数据库mysqli驱动
*/
namespace core\database;
use core\basic\Config;
class Mysqli implements Builder
{
protected static $mysqli;
protected $master;
protected $slave;
protected $begin = false;
private function __construct()
{}
public function __destruct()
{
if ($this->begin) { // 存在待提交的事务时自动进行提交
$this->commit();
}
}
// 获取单一实例,使用单一实例数据库连接类
public static function getInstance()
{
if (! self::$mysqli) {
self::$mysqli = new self();
}
return self::$mysqli;
}
// 连接数据库,接受数据库连接参数,返回数据库连接对象
public function conn($cfg)
{
if (! extension_loaded('mysqli')) {
if (extension_loaded('pdo_mysql')) {
error('未检测到您服务器环境的mysqli数据库扩展请检查php.ini中是否已经开启该扩展<br>另外检测到您服务器支持pdo_mysql扩展您也可以修改数据库配置连接驱动为pdo_mysql试试');
} else {
error('未检测到您服务器环境的mysqli数据库扩展请检查php.ini中是否已经开启该扩展');
}
}
// 优化>php5.3版本 在win2008以上服务器连接
if ($cfg['host'] == 'localhost') {
$cfg['host'] = '127.0.0.1';
}
$conn = @new \Mysqli($cfg['host'], $cfg['user'], $cfg['passwd'], $cfg['dbname'], $cfg['port']);
if (mysqli_connect_errno()) {
error("连接数据库服务器失败:" . iconv('gbk', 'utf-8', mysqli_connect_error()));
}
$charset = Config::get('database.charset') ?: 'utf8';
$conn->set_charset($charset); // 设置编码
return $conn;
}
// 关闭自动提交,开启事务模式
public function begin()
{
$this->master->autocommit(false);
$this->begin = true;
}
// 提交事务
public function commit()
{
$this->master->commit(); // 提交事务
$this->master->autocommit(true); // 提交后恢复自动提交
$this->begin = false; // 关闭事务模式
}
// 执行SQL语句,接受完整SQL语句返回结果集对象
public function query($sql, $type = 'master')
{
$time_s = microtime(true);
switch ($type) {
case 'master':
if (! $this->master) {
$cfg = Config::get('database');
$this->master = $this->conn($cfg);
$this->master->query("SET sql_mode='NO_ENGINE_SUBSTITUTION'"); // 写入规避严格模式
}
if (Config::get('database.transaction') && ! $this->begin) { // 根据配置开启mysql事务注意需要是InnoDB引擎
$this->begin();
}
$result = $this->master->query($sql) or $this->error($sql, 'master');
break;
case 'slave':
if (! $this->slave) {
// 未设置从服务器时直接读取主数据库配置
if (! $cfg = Config::get('database.slave')) {
$cfg = Config::get('database');
} else {
// 随机选择从数据库
if (is_multi_array($cfg)) {
$count = count($cfg);
$cfg = $cfg['slave' . mt_rand(1, $count)];
}
}
$this->slave = $this->conn($cfg);
}
$result = $this->slave->query($sql) or $this->error($sql, 'slave');
break;
}
return $result;
}
// 数据是否存在模型接受完整SQL语句返回boolean数据
public function isExist($sql)
{
$result = $this->query($sql, 'slave');
if ($result->num_rows) {
$result->free();
return true;
} else {
return false;
}
}
// 获取记录总量模型接受数据库表名返回int数据
public function rows($table)
{
$sql = "SELECT count(*) FROM $table";
$result = $this->query($sql, 'slave');
if (! ! $row = $result->fetch_array(2)) {
$result->free();
return $row[0];
} else {
return 0;
}
}
// 读取字段数量模型接受数据库表名返回int数据
public function fields($table)
{
$sql = "SELECT * FROM $table LIMIT 1";
$result = $this->query($sql, 'slave');
if ($result) {
return $result->field_count;
} else {
return 0;
}
}
/**
* 获取表信息,接受数据库表名,返回表字段信息数组
*
* @param $table 表名
*/
public function tableFields($table)
{
$sql = "describe $table";
$result = $this->query($sql, 'slave');
$rows = array();
if ($this->slave->affected_rows) {
while (! ! $row = $result->fetch_object()) {
$rows[] = $row->Field;
}
$result->free();
}
return $rows;
}
/**
* 查询一条数据模型接受完整SQL语句有数据返回对象数组否则空数组
*
* @$type 可以是MYSQLI_ASSOC ,MYSQLI_NUM ,MYSQLI_BOTH,不设置则返回对象数组
*/
public function one($sql, $type = null)
{
$result = $this->query($sql, 'slave');
$row = array();
if ($this->slave->affected_rows) {
if ($type) {
$row = $result->fetch_array($type);
} else {
$row = $result->fetch_object();
}
$result->free();
}
return $row;
}
/**
* 查询多条数据模型接受完整SQL语句有数据返回二维对象数组否则空数组
* @$type 可以是MYSQLI_ASSOC ,MYSQLI_NUM ,MYSQLI_BOTH,不设置则返回对象模式
*/
public function all($sql, $type = null)
{
$result = $this->query($sql, 'slave');
$rows = array();
if ($this->slave->affected_rows) {
if ($type) {
while (! ! $array = $result->fetch_array($type)) { // 关联数组或数字数组或同时
$rows[] = $array;
}
} else {
while (! ! $objects = $result->fetch_object()) {
$rows[] = $objects;
}
}
$result->free();
}
return $rows;
}
// 数据增、删、改模型接受完整SQL语句返回影响的行数的int数据
public function amd($sql)
{
$result = $this->query($sql, 'master');
$num = $this->master->affected_rows;
if ($num > 0) {
return $num;
} else {
return 0;
}
}
// 最近一次插入数据的自增字段值返回int数据
public function insertId()
{
return $this->master->insert_id;
}
// 执行多条SQL模型成功返回true,否则false
public function multi($sql)
{
$result = $this->master->multi_query($sql) or $this->error($sql);
if ($result) {
$result->free();
return true;
} else {
return false;
}
}
// 显示执行错误
protected function error($sql, $conn)
{
$err = '错误:' . mysqli_error($this->$conn);
if (preg_match('/XPATH/i', $err)) {
$err = '';
}
if ($this->begin) { // 如果是事务模式,发生错误,则回滚
$this->$conn->rollback();
$this->begin = false;
}
// error('执行SQL发生错误' . $err . '语句:' . $sql);
error('执行SQL发生错误' . $err);
}
}

311
core/database/Pdo.php Normal file
View File

@@ -0,0 +1,311 @@
<?php
/**
* @copyright (C)2016-2099 Hnaoyun Inc.
* @author XingMeng
* @email hnxsh@foxmail.com
* @date 2017年8月30日
* 数据库PDO驱动
*/
namespace core\database;
use core\basic\Config;
class Pdo implements Builder
{
protected static $pdo;
protected $master;
protected $slave;
protected $begin = false;
private function __construct()
{}
public function __destruct()
{
if ($this->begin) { // 存在待提交的事务时自动进行提交
$this->commit();
}
}
// 获取单一实例,使用单一实例数据库连接类
public static function getInstance()
{
if (! self::$pdo) {
self::$pdo = new self();
}
return self::$pdo;
}
// 连接数据库,接受数据库连接参数,返回数据库连接对象
public function conn($cfg)
{
if (get_db_type() == 'sqlite' && ! extension_loaded('pdo_sqlite')) {
if (extension_loaded('SQLite3')) {
error('未检测到您服务器环境的pdo_sqlite数据库扩展请检查php.ini中是否已经开启该扩展<br>另外检测到您服务器支持sqlite3扩展您也可以修改数据库配置连接驱动为sqlite试试');
} else {
error('未检测到您服务器环境的pdo_sqlite数据库扩展请检查php.ini中是否已经开启对应的数据库扩展');
}
} elseif (get_db_type() == 'mysql' && ! extension_loaded('pdo_mysql')) {
if (extension_loaded('mysqli')) {
error('未检测到您服务器环境的pdo_mysqli数据库扩展请检查php.ini中是否已经开启该扩展<br>另外检测到您服务器支持mysqli扩展您也可以修改数据库配置连接驱动为mysqli试试');
} else {
error('未检测到您服务器环境的pdo_mysqli数据库扩展请检查php.ini中是否已经开启对应的数据库扩展');
}
}
$charset = Config::get('database.charset') ?: 'utf8';
switch (Config::get('database.type')) {
case 'pdo_mysql':
$dsn = 'mysql:host=' . $cfg['host'] . ';port=' . $cfg['port'] . ';dbname=' . $cfg['dbname'] . ';charset=' . $charset;
try {
$conn = new \PDO($dsn, $cfg['user'], $cfg['passwd']);
} catch (\PDOException $e) {
error('PDO方式连接MySQL数据库错误' . iconv('gbk', 'utf-8', $e->getMessage()));
}
break;
case 'pdo_sqlite':
$dsn = 'sqlite:' . ROOT_PATH . $cfg['dbname'];
try {
$conn = new \PDO($dsn);
} catch (\PDOException $e) {
error('PDO方式连接Sqlite数据库错误' . iconv('gbk', 'utf-8', $e->getMessage()));
}
break;
case 'pdo_pgsql':
$dsn = 'pgsql:host=' . $cfg['host'] . ';port=' . $cfg['port'] . ';dbname=' . $cfg['dbname'];
try {
$conn = new \PDO($dsn, $cfg['user'], $cfg['passwd']);
} catch (\PDOException $e) {
error('PDO方式连接Pgsql数据库错误' . iconv('gbk', 'utf-8', $e->getMessage()));
}
break;
default:
$dsn = Config::get('database.dsn');
try {
$conn = new \PDO($dsn, $cfg['user'], $cfg['passwd']);
} catch (\PDOException $e) {
error('PDO方式连接数据库错误' . iconv('gbk', 'utf-8', $e->getMessage()));
}
break;
}
return $conn;
}
// 关闭自动提交,开启事务模式
public function begin()
{
$this->master->beginTransaction();
$this->begin = true;
}
// 提交事务
public function commit()
{
$this->master->commit();
$this->begin = false;
}
// 执行SQL语句,接受完整SQL语句返回结果集对象
public function query($sql, $type = 'master')
{
$time_s = microtime(true);
switch ($type) {
case 'master':
if (! $this->master) {
$cfg = Config::get('database');
$this->master = $this->conn($cfg);
if ($cfg['type'] == 'pdo_mysql') {
$this->master->exec("SET sql_mode='NO_ENGINE_SUBSTITUTION'"); // MySql写入规避严格模式
}
}
// sqlite时自动启动事务
if ($cfg['type'] == 'pdo_sqlite' && ! $this->begin) {
$this->begin();
} elseif ($cfg['type'] == 'pdo_mysql' && Config::get('database.transaction') && ! $this->begin) { // 根据配置开启mysql事务注意需要是InnoDB引擎
$this->begin();
}
$result = $this->master->exec($sql);
if ($result === false) {
$this->error($sql, 'master');
}
break;
case 'slave':
if (! $this->slave) {
// 未设置从服务器时直接读取主数据库配置
if (! $cfg = Config::get('database.slave')) {
$cfg = Config::get('database');
} else {
// 随机选择从数据库
if (is_multi_array($cfg)) {
$count = count($cfg);
$cfg = $cfg['slave' . mt_rand(1, $count)];
}
}
$this->slave = $this->conn($cfg);
}
$result = $this->slave->query($sql) or $this->error($sql, 'slave');
break;
}
return $result;
}
// 数据是否存在模型接受完整SQL语句返回boolean数据
public function isExist($sql)
{
$result = $this->query($sql, 'slave');
if ($result->fetch()) {
return true;
} else {
return false;
}
}
// 获取记录总量模型接受数据库表名返回int数据
public function rows($table)
{
$sql = "SELECT count(*) FROM $table";
$result = $this->query($sql, 'slave');
if (! ! $row = $result->fetch(\PDO::FETCH_NUM)) {
return $row[0];
} else {
return 0;
}
}
// 读取字段数量模型接受数据库表名返回int数据
public function fields($table)
{
$sql = "SELECT * FROM $table LIMIT 1";
$result = $this->query($sql, 'slave');
if ($result) {
return $result->columnCount();
} else {
return false;
}
}
/**
* 获取表信息,接受数据库表名,返回表字段信息数组
*
* @param $table 表名
*/
public function tableFields($table)
{
$rows = array();
switch (Config::get('database.type')) {
case 'pdo_mysql':
$sql = "describe $table";
$result = $this->query($sql, 'slave');
while (! ! $row = $result->fetchObject()) {
$rows[] = $row->Field;
}
break;
case 'pdo_sqlite':
$sql = "pragma table_info($table)";
$result = $this->query($sql, 'slave');
while (! ! $row = $result->fetchObject()) {
$rows[] = $row->name;
}
break;
case 'pdo_pgsql':
$sql = "SELECT column_name FROM information_schema.columns WHERE table_name ='$table'";
$result = $this->query($sql, 'slave');
while (! ! $row = $result->fetchObject()) {
$rows[] = $row->column_name;
}
break;
default:
return array();
}
return $rows;
}
/**
* 查询一条数据模型接受完整SQL语句有数据返回对象数组否则空数组
* @$type 可以是MYSQLI_ASSOC(FETCH_ASSOC) ,MYSQLI_NUM(FETCH_NUM) ,MYSQLI_BOTH(FETCH_BOTH),不设置则返回对象模式
*/
public function one($sql, $type = null)
{
$result = $this->query($sql, 'slave');
$row = array();
if ($type) {
$type ++; // 与mysqli统一返回类型设置
$row = $result->fetch($type);
} else {
$row = $result->fetchObject();
}
return $row;
}
/**
* 查询多条数据模型接受完整SQL语句有数据返回二维对象数组否则空数组
* @$type 可以是MYSQLI_ASSOC(FETCH_ASSOC) ,MYSQLI_NUM(FETCH_NUM) ,MYSQLI_BOTH(FETCH_BOTH),不设置则返回对象模式
*/
public function all($sql, $type = null)
{
$result = $this->query($sql, 'slave');
$rows = array();
if ($type) {
$type ++; // 与mysqli统一返回类型设置
$rows = $result->fetchAll($type);
} else {
while (! ! $row = $result->fetchObject()) {
$rows[] = $row;
}
}
return $rows;
}
// 数据增、删、改模型接受完整SQL语句返回影响的行数的int数据
public function amd($sql)
{
$result = $this->query($sql, 'master');
if ($result > 0) {
return $result;
} else {
return 0;
}
}
// 最近一次插入数据的自增字段值返回int数据
public function insertId()
{
return $this->master->lastInsertId();
}
// 执行多条SQL模型成功返回true,否则false
public function multi($sql)
{
$sqls = explode(';', $sql);
foreach ($sqls as $key => $value) {
$result = $this->query($value, 'master');
}
if ($result) {
return true;
} else {
return false;
}
}
// 显示执行错误
protected function error($sql, $conn)
{
$errs = $this->$conn->errorInfo();
$err = '错误:' . $errs[2];
if (preg_match('/XPATH/i', $err)) {
$err = '';
}
if ($this->begin) { // 如果是事务模式,发生错误,则回滚
$this->$conn->rollBack();
$this->begin = false;
}
// error('执行SQL发生错误' . $err . '语句:' . $sql);
error('执行SQL发生错误' . $err);
}
}

231
core/database/Sqlite.php Normal file
View File

@@ -0,0 +1,231 @@
<?php
/**
* @copyright (C)2016-2099 Hnaoyun Inc.
* @author XingMeng
* @email hnxsh@foxmail.com
* @date 2017年8月23日
* 数据库Sqlite驱动 ,写入数据时自动启用事务
*/
namespace core\database;
use core\basic\Config;
class Sqlite implements Builder
{
protected static $sqlite;
protected $master;
protected $slave;
private $begin = false;
private function __construct()
{}
public function __destruct()
{
if ($this->begin) { // 存在待提交的事务时自动进行提交
$this->master->exec('commit;');
}
}
// 获取单一实例,使用单一实例数据库连接类
public static function getInstance()
{
if (! self::$sqlite) {
self::$sqlite = new self();
}
return self::$sqlite;
}
// 连接数据库,接受数据库连接参数,返回数据库连接对象
public function conn($cfg)
{
if (extension_loaded('SQLite3')) {
try {
$conn = new \SQLite3($cfg);
$conn->busyTimeout(15 * 1000); // 设置繁忙延迟时间
} catch (\Exception $e) {
error("读取数据库文件失败:" . iconv('gbk', 'utf-8', $e->getMessage()));
}
} else {
if (extension_loaded('pdo_sqlite')) {
error('未检测到您服务器环境的sqlite3数据库扩展请检查php.ini中是否已经开启该扩展<br>另外检测到您服务器支持pdo_sqlite扩展您也可以修改数据库配置连接驱动为pdo_sqlite试试');
} else {
error('未检测到您服务器环境的sqlite3数据库扩展请检查php.ini中是否已经开启该扩展');
}
}
return $conn;
}
// 执行SQL语句,接受完整SQL语句返回结果集对象
public function query($sql, $type = 'master')
{
$time_s = microtime(true);
if (! $this->master || ! $this->slave) {
$cfg = ROOT_PATH . Config::get('database.dbname');
$conn = $this->conn($cfg);
$this->master = $conn;
$this->slave = $conn;
}
switch ($type) {
case 'master':
if (! $this->begin) { // 存在写入时自动开启显式事务,提高写入性能
$this->master->exec('begin;');
$this->begin = true;
}
$result = $this->master->exec($sql) or $this->error($sql, 'master');
break;
case 'slave':
$result = $this->slave->query($sql) or $this->error($sql, 'slave');
break;
}
return $result;
}
// 数据是否存在模型接受完整SQL语句返回boolean数据
public function isExist($sql)
{
$result = $this->query($sql, 'slave');
if ($result->fetchArray()) {
$result->finalize();
return true;
} else {
return false;
}
}
// 获取记录总量模型接受数据库表名返回int数据
public function rows($table)
{
$sql = "SELECT count(*) FROM $table";
$result = $this->query($sql, 'slave');
if (! ! $row = $result->fetchArray(2)) {
$result->finalize();
return $row[0];
} else {
return 0;
}
}
// 读取字段数量模型接受数据库表名返回int数据
public function fields($table)
{
$sql = "SELECT * FROM $table LIMIT 1";
$result = $this->query($sql, 'slave');
if ($result) {
return $result->numColumns();
} else {
return false;
}
}
/**
* 获取表字段,接受数据库表名,返回表字段数组
*
* @param $table 表名
*/
public function tableFields($table)
{
$sql = "pragma table_info($table)";
$result = $this->query($sql, 'slave');
$rows = array();
while (! ! $row = $result->fetchArray(SQLITE3_ASSOC)) {
$rows[] = $row['name'];
}
$result->finalize();
return $rows;
}
// 查询一条数据模型接受完整SQL语句有数据返回对象数组否则空数组
public function one($sql, $type = null)
{
if (! $type) {
$my_type = SQLITE3_ASSOC;
} else {
$my_type = $type;
}
$row = array();
$result = $this->query($sql, 'slave');
if (! ! $row = $result->fetchArray($my_type)) {
if (! $type && $row) {
$out = new \stdClass();
foreach ($row as $key => $value) {
$out->$key = $value;
}
$row = $out;
}
$result->finalize();
}
return $row;
}
// 查询多条数据模型接受完整SQL语句有数据返回二维对象数组否则空数组
public function all($sql, $type = null)
{
if (! $type) {
$my_type = SQLITE3_ASSOC;
} else {
$my_type = $type;
}
$result = $this->query($sql, 'slave');
$rows = array();
while (! ! $row = $result->fetchArray($my_type)) {
if (! $type && $row) {
$out = new \stdClass();
foreach ($row as $key => $value) {
$out->$key = $value;
}
$row = $out;
}
$rows[] = $row;
}
$result->finalize();
return $rows;
}
// 数据增、删、改模型接受完整SQL语句返回影响的行数的int数据
public function amd($sql)
{
$result = $this->query($sql, 'master');
if ($result) {
return $result;
} else {
return 0;
}
}
// 最近一次插入数据的自增字段值返回int数据
public function insertId()
{
return $this->master->lastInsertRowID();
}
// 执行多条SQL模型成功返回true,否则false
public function multi($sql)
{
$sqls = explode(';', $sql);
foreach ($sqls as $key => $value) {
$result = $this->query($value, 'master');
}
if ($result) {
return true;
} else {
return false;
}
}
// 显示执行错误
protected function error($sql, $conn)
{
$err = '错误:' . $this->$conn->lastErrorMsg();
if ($this->begin) { // 存在显式开启事务时进行回滚
$this->master->exec('rollback;');
$this->begin = false;
}
// error('执行SQL发生错误' . $err . '语句:' . $sql);
error('执行SQL发生错误' . $err);
}
}