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 抓取网页图片并且另存为的实现代码
Mar 24 PHP
PHP错误抑制符(@)导致引用传参失败Bug的分析
May 02 PHP
理解和运用PHP中的多态性[译]
Aug 02 PHP
PHP 中检查或过滤IP地址的实现代码
Nov 27 PHP
PHP 使用MySQL管理Session的回调函数详解
Jun 21 PHP
探寻PHP脚本不报错的原因
Jun 12 PHP
PHP的反射类ReflectionClass、ReflectionMethod使用实例
Aug 05 PHP
ThinkPHP模版中导入CSS和JS文件的方法
Nov 29 PHP
php并发加锁示例
Oct 17 PHP
PHP互换两个变量值的方法(不用第三变量)
Nov 14 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
Feb 07 PHP
Yii框架where查询用法实例分析
Oct 22 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采集中国代理服务器网的方法
2015/06/16 PHP
一个js实现的所谓的滑动门
2007/05/23 Javascript
通过Jquery遍历Json的两种数据结构的实现代码
2011/01/19 Javascript
jQuery建立一个按字母顺序排列的友好页面索引(兼容IE6/7/8)
2013/02/26 Javascript
在页面中js获取光标/鼠标的坐标及光标的像素坐标
2013/11/11 Javascript
AngularJs实现ng1.3+表单验证
2015/12/10 Javascript
BootStrap响应式导航条实例介绍
2016/05/06 Javascript
详解javascript获取url信息的常见方法
2016/12/19 Javascript
js实现下一页页码效果
2017/03/07 Javascript
JS实现商品筛选功能
2020/08/19 Javascript
基于vue2.0的活动倒计时组件countdown(附源码下载)
2018/10/09 Javascript
关于微信公众号开发无法支付的问题解决
2018/12/28 Javascript
详解vue后台系统登录态管理
2019/04/02 Javascript
小程序登录/注册页面设计的实现代码
2019/05/24 Javascript
Vue.js实现大屏数字滚动翻转效果
2019/11/29 Javascript
python使用Image处理图片常用技巧分析
2015/06/01 Python
Perl中著名的Schwartzian转换问题解决实现
2015/06/02 Python
给Python入门者的一些编程建议
2015/06/15 Python
带你认识Django
2019/01/15 Python
Django实现跨域的2种方法
2019/07/31 Python
python TK库简单应用(实时显示子进程输出)
2019/10/29 Python
python 统计文件中的字符串数目示例
2019/12/24 Python
解决import tensorflow as tf 出错的原因
2020/04/16 Python
python+excel接口自动化获取token并作为请求参数进行传参操作
2020/11/10 Python
德国机车企业:FC-Moto
2017/10/27 全球购物
巴西美妆购物网站:Kutiz Beauté
2019/03/13 全球购物
OSPREY LONDON官网:英国本土皮具品牌
2019/05/31 全球购物
第一范式(1NF)、第二范式(2NF)和第三范式(3NF)之间的区别是什么?
2016/04/28 面试题
校园网站的创业计划书范文
2013/12/30 职场文书
《黄山奇石》教学反思
2014/04/19 职场文书
我的理想演讲稿
2014/04/30 职场文书
2014小学数学教师个人工作总结
2014/12/18 职场文书
交警失职检讨书
2015/01/26 职场文书
文言文辞职信
2015/02/28 职场文书
改进工作作风心得体会
2016/01/23 职场文书
python - asyncio异步编程
2021/04/06 Python