Yii2实现跨mysql数据库关联查询排序功能代码


Posted in PHP onFebruary 10, 2017

背景:在一个mysql服务器上(注意:两个数据库必须在同一个mysql服务器上)有两个数据库:

memory (存储常规数据表) 中有一个 user 表(记录用户信息)

memory_stat (存储统计数据表) 中有一个 user_stat (记录用户统计数据)

现在在 user 表生成的 GridView 列表中展示 user_stat 中的统计数据

只需要在User的model类中添加关联

public function getStat()
{
 return $this->hasOne(UserStat::className(), ['user_id' => 'id']);
}

在GridView就可以这样使用来展示统计数据

<?= GridView::widget([
 'dataProvider' => $dataProvider,
 'columns' => [

  //其他列
  
  [
   'label' => '统计数据',
   'value' => function($model){
    return isset($model->stat->data) ? $model->stat->data : null;
   }
  ],
  
  //其他列
 ],
]); ?>

现在增加了一个需求,需要在user GridView 列表中对统计数据进行排序和筛选

若 user 和 user_stat 表在同一个数据库下我们可以这样做:

UserSearch:

public $data;
public function rules()
{/*{{{*/
 return [
  ['data'], 'integer'],
  //其他列
 ];
}/*}}}*/

public function search($params, $onlyActiveUsers = false)
{
 $query = User::find();
 $query->joinWith(['stat']);

 $dataProvider = new ActiveDataProvider([
  'query' => $query,
  'sort' => [
   'attributes' => [
    //其他列
    
    'data' => [
     'asc' => [UserStat::tableName() . '.data' => SORT_ASC],
     'desc' => [UserStat::tableName() . '.data' => SORT_DESC],
    ],
    
    //其他列
   ],
   'defaultOrder' => [
    'id' => SORT_DESC,
   ],
  ],
  'pagination' => [
   'pageSize' => 50,
  ],
 ]);

 $this->load($params);

 if (!$this->validate()) {
  $query->where('0=1');
  return $dataProvider;
 }

 $query->filterWhere([
 
  //其他列
  
  UserStat::tableName() . '.data' => $this->data
 ]);

 return $dataProvider;
}

在GridView就可以这样使用来展示统计数据,就可以排序了

<?= GridView::widget([
 'dataProvider' => $dataProvider,
 'columns' => [

  //其他列
  
  [
   'label' => '统计数据',
   'attribute' => 'data',
   'value' => function($model){
    return isset($model->stat->data) ? $model->stat->data : null;
   }
  ],
  
  //其他列
 ],
]); ?>

search 表单中添加以下列就可以筛选了

<?php $form = ActiveForm::begin(); ?>
//其他列 

<?= $form->field($model, 'data')?>

//其他列
<div class="form-group">
 <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>

然而现实是残酷的, user 和 user_stat 表并在同一个数据库下。

于是就会报出这样一个错误:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'memory.user_stat' doesn't exist
The SQL being executed was: ...

要在两个数据库(同一台服务器)上进行关联数据查询,纯SQL语句如下:

select a.*,b.* from memory.user as a,memory_stat.user_stat as b where a.id=b.user_id;

Yii2转化成 SQL 语句时默认不会在表明前添加数据库名,于是mysql在执行sql语句时就会默认此表在memory数据库下。

select a.*,b.* from memory.user as a,memory.user_stat as b where a.id=b.user_id;

于是就出现了以上报错信息。

那么,如何来解决这个问题呢?

其实很简单,只需要重写 user_stat 的 model 类下的 tableName() 方法就可以了。

// 默认是这样的
public static function tableName()
{
 return 'user_stat';
}

public static function getDb()
{
 return Yii::$app->get('dbStat');
}
// 只需要在表明前添加数据库名
public static function tableName()
{
 return 'memory_stat.user_stat';
}

public static function getDb()
{
 return Yii::$app->get('dbStat');
}
// 为了提高代码稳定性,可以这样写
public static function tableName()
{
 preg_match("/dbname=([^;]+)/i", static::getDb()->dsn, $matches);
 return $matches[1].'.user_stat';
}

public static function getDb()
{
 return Yii::$app->get('dbStat');
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP常用代码
Nov 23 PHP
php 字符串替换的方法
Jan 10 PHP
淘宝ip地址查询类分享(利用淘宝ip库)
Jan 07 PHP
php环境套包 dedeampz 伪静态设置示例
Mar 26 PHP
Laravel 5框架学习之子视图和表单复用
Apr 09 PHP
php计算年龄精准到年月日
Nov 17 PHP
详解WordPress中简码格式标签编写的基本方法
Dec 22 PHP
PHP Try-catch 语句使用技巧
Feb 28 PHP
php+mysql实现的二级联动菜单效果详解
May 10 PHP
php将html转为图片的实现方法
May 19 PHP
详解PHP5.6.30与Apache2.4.x配置
Jun 02 PHP
阿里云Win2016安装Apache和PHP环境图文教程
Mar 11 PHP
yii2 数据库读写分离配置示例
Feb 10 #PHP
php 基础函数
Feb 10 #PHP
PHP isset()与empty()的使用区别详解
Feb 10 #PHP
PHP获取当前URL路径的处理方法(适用于多条件筛选列表)
Feb 10 #PHP
Thinkphp3.2实用篇之计算型验证码示例
Feb 09 #PHP
PHP 验证身份证是否合法的函数
Feb 09 #PHP
如何打开php的gd2库
Feb 09 #PHP
You might like
php下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
php 判断数组是几维数组
2013/03/20 PHP
php目录操作实例代码
2014/02/21 PHP
分析PHP中单双引号的误区和双引号小隐患
2016/07/19 PHP
php注册审核重点解析(数据访问)
2017/05/23 PHP
php判断目录存在的简单方法
2019/09/26 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
Gambit vs ForZe BO3 第二场 2.13
2021/03/10 DOTA
用javascript编写的第一人称射击游戏
2007/02/25 Javascript
jQuery中调用WebService方法小结
2011/03/28 Javascript
jQuery fadeTo方法调整图片的透明度使用介绍
2013/05/06 Javascript
js 3种归并操作的实例代码
2013/10/30 Javascript
JQuery 传送中文乱码问题的简单解决办法
2016/05/24 Javascript
jQuery 常见小例汇总
2016/12/14 Javascript
Canvas 绘制粒子动画背景
2017/02/15 Javascript
js canvas实现橡皮擦效果
2018/12/20 Javascript
vue-cli webpack配置文件分析
2019/05/20 Javascript
详解新手使用vue-router传参时注意事项
2019/06/06 Javascript
原生JavaScript之es6中Class的用法分析
2020/02/23 Javascript
Vue数组响应式操作及高阶函数使用代码详解
2020/08/01 Javascript
vue自动添加浏览器兼容前后缀操作
2020/08/13 Javascript
[01:35]辉夜杯战队访谈宣传片—iG.V
2015/12/25 DOTA
Python实现HTTP协议下的文件下载方法总结
2016/04/20 Python
如何优雅地改进Django中的模板碎片缓存详解
2018/07/04 Python
Django 内置权限扩展案例详解
2019/03/04 Python
使用Python代码实现Linux中的ls遍历目录命令的实例代码
2019/09/07 Python
Pandas DataFrame中的tuple元素遍历的实现
2019/10/23 Python
Tensorflow tf.dynamic_partition矩阵拆分示例(Python3)
2020/02/07 Python
基于Python把网站域名解析成ip地址
2020/05/25 Python
无需压缩软件,用python帮你操作压缩包
2020/08/17 Python
香港莎莎官网Sasa.com:亚洲著名国际化妆品商城
2019/11/10 全球购物
纬创Java面试题笔试题
2014/10/02 面试题
Ajax的工作原理
2015/12/04 面试题
茶花女读书笔记
2015/06/29 职场文书
谢师宴学生致辞
2015/07/27 职场文书
安全责任协议书范本
2016/03/23 职场文书