thinkphp 简单的跨数据库连接,不支持多表操作。

前几天正在开发的某个项目突然告知他们想把前后台的数据库分离,客户的会员量在50W左右。他们的需求是一个数据库只能存在一个数据服务器上,所以不能用mysql主从复制。数据库是局域网连通的。

当时考虑了他们的数据结构,因为客户的功能需求特别简单,只是注册会员买东西算奖金。所以很少涉及到一对多关联。

所以当时采用了通过修改数据库连接的方式对其它数据库的数据进行操作。具体代码如下:

\thinkphp\library\think\db\Query.php 里的__construct  方法

/**
* 构造函数
* @access public
* @param Connection $connection 数据库对象实例
* @param Model $model 模型对象
*/
public function __construct(Connection $connection = null, $model = null)
{
$this->connection = $connection ?: Db::connect([], true);
//会员数据库连接 生成新的连接
$this->userconnection= Db::connect(Config('usercon'));
$this->prefix = $this->connection->getConfig('prefix');
$this->model = $model;
// 设置当前连接的Builder对象
$this->setBuilder();
}

通过操作的表来判断查询和执行语句的数据库连接

public function query($sql, $bind = [], $master = false, $class = false)
{
$options = $this->parseExpress();
//判断数据库连接 
  if(in_array($options['table'],Config('usertable'))){
   return $this->userconnection->query($sql, $bind, $master, $class);
  }else{
   return $this->connection->query($sql, $bind, $master, $class);
  }
}

/**
* 执行语句
* @access public
* @param string $sql sql指令
* @param array $bind 参数绑定
* @return int
* @throws BindParamException
* @throws PDOException
*/
public function execute($sql, $bind = [])
{
$options = $this->parseExpress();
//判断数据库连接 
  if(in_array($options['table'],Config('usertable'))){
   return $this->userconnection->execute($sql, $bind, $this);
  }else{
   return $this->connection->execute($sql, $bind, $this);
  }
}

/**

* 获取最近插入的ID
* @access public
* @param string $sequence 自增序列名
* @return string
*/

public function getLastInsID($sequence = null)

{
  $options = $this->parseExpress();
  //判断数据库连接 
  if(in_array($options['table'],Config('usertable'))){
   return $this->userconnection->getLastInsID($sequence);
  }else{
   return $this->connection->getLastInsID($sequence);
  } 
}

/**
* 获取最近一次查询的sql语句
* @access public
* @return string
*/
public function getLastSql()
{
  $options = $this->parseExpress();
// //判断数据库连接 
  if(in_array($options['table'],Config('usertable'))){
   return $this->userconnection->getLastSql();
  }else{
   return $this->connection->getLastSql();
  }
}

/**
* 执行数据库事务
* @access public
* @param callable $callback 数据操作方法回调
* @return mixed
*/
public function transaction($callback)
{

return $this->connection->transaction($callback);
}

/**
* 启动事务
* @access public
* @return void
*/
public function startTrans()
{
$this->userconnection->startTrans();
$this->connection->startTrans();
}

/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return void
* @throws PDOException
*/
public function commit()
{
$this->connection->commit();
$this->userconnection->commit();
}

/**
* 事务回滚
* @access public
* @return void
* @throws PDOException
*/
public function rollback()
{
$this->connection->rollback();
$this->userconnection->rollback();
}

/**
* 获取数据表信息    
* @access public
* @param mixed $tableName 数据表名 留空自动获取
* @param string $fetch 获取信息类型 包括 fields type bind pk
* @return mixed
*/
public function getTableInfo($tableName = '', $fetch = '')
{

if (!$tableName) {
$tableName = $this->getTable();
}
if (is_array($tableName)) {
$tableName = key($tableName) ?: current($tableName);
}

if (strpos($tableName, ',')) {
// 多表不获取字段信息
return false;
} else {
$tableName = $this->parseSqlTable($tableName);
}

// 修正子查询作为表名的问题
if (strpos($tableName, ')')) {
return [];
}

list($guid) = explode(' ', $tableName);
$db = $this->getConfig('database');
if (!isset(self::$info[$db . '.' . $guid])) {
if (!strpos($guid, '.')) {
$schema = $db . '.' . $guid;
} else {
$schema = $guid;
}
// 读取缓存
if (!App::$debug && is_file(RUNTIME_PATH . 'schema/' . $schema . '.php')) {
$info = include RUNTIME_PATH . 'schema/' . $schema . '.php';
} else {
//判断数据库连接 
    if(in_array($tableName,Config('usertable'))){
      $info = $this->userconnection->getFields($guid);
    }else{
      $info = $this->connection->getFields($guid);
    }
$info = $this->connection->getFields($guid);
}
$fields = array_keys($info);
$bind = $type = [];
foreach ($info as $key => $val) {
// 记录字段类型
$type[$key] = $val['type'];
$bind[$key] = $this->getFieldBindType($val['type']);
if (!empty($val['primary'])) {
$pk[] = $key;
}
}
if (isset($pk)) {
// 设置主键
$pk = count($pk) > 1 ? $pk : $pk[0];
} else {
$pk = null;
}
self::$info[$db . '.' . $guid] = ['fields' => $fields, 'type' => $type, 'bind' => $bind, 'pk' => $pk];
}
return $fetch ? self::$info[$db . '.' . $guid][$fetch] : self::$info[$db . '.' . $guid];
}

 

 

这样在进行数据操作的时候,tp会自动判断当前的sql语句要在那个数据库上执行。

亲测有效。。。写的不好,请多多指教。。。

转载于:https://www.cnblogs.com/waczq/p/9358430.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值