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 MySQL与分页效率
Jun 04 PHP
php读取大文件示例分享(文件操作类)
Apr 13 PHP
ThinkPHP3.1新特性之对Ajax的支持更加完善
Jun 19 PHP
ThinkPHP中自定义错误页面和提示页面实例
Nov 22 PHP
PHP中require和include路径问题详解
Dec 25 PHP
PHP使用JSON和将json还原成数组
Feb 12 PHP
php数组键名技巧小结
Feb 17 PHP
用PHP的socket实现客户端到服务端的通信实例详解
Feb 04 PHP
ThinkPHP框架表单验证操作方法
Jul 19 PHP
PHP设计模式之模板方法模式定义与用法详解
Apr 02 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
PHP配置文件php.ini中打开错误报告的设置方法
Jan 09 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图片验证码代码
2008/03/27 PHP
PHP限制页面只能在微信自带浏览器访问的代码
2014/01/15 PHP
Codeigniter框架实现获取分页数据和总条数的方法
2014/12/05 PHP
通过PHP实现用户注册后邮箱验证激活
2020/11/10 PHP
PHP接入支付宝接口失效流程详解
2020/11/10 PHP
JavaScript 检测浏览器和操作系统的脚本
2008/12/26 Javascript
JavaScript游戏之优化篇
2010/11/08 Javascript
js给selected添加options的方法
2015/05/06 Javascript
JavaScript对象参数的引用传递
2016/01/14 Javascript
使用BootStrap实现表格隔行变色及hover变色并在需要时出现滚动条
2017/01/04 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
angular中实现li或者某个元素点击变色的两种方法
2017/07/27 Javascript
使用Vue CLI创建typescript项目的方法
2019/08/09 Javascript
JS通用方法触发点击事件代码实例
2020/02/17 Javascript
如何在vue中使用kindeditor富文本编辑器
2020/12/19 Vue.js
[01:03:00]DOTA2上海特级锦标赛A组败者赛 EHOME VS CDEC第一局
2016/02/25 DOTA
Eclipse + Python 的安装与配置流程
2013/03/05 Python
利用Python的Flask框架来构建一个简单的数字商品支付解决方案
2015/03/31 Python
Python类定义和类继承详解
2015/05/08 Python
基于Python Shell获取hostname和fqdn释疑
2016/01/25 Python
浅谈Python类的__getitem__和__setitem__特殊方法
2016/12/25 Python
python 以16进制打印输出的方法
2018/07/09 Python
python自动化测试之如何解析excel文件
2019/06/27 Python
python图形用户接口实例详解
2019/12/16 Python
在keras里面实现计算f1-score的代码
2020/06/15 Python
python正则表达式 匹配反斜杠的操作方法
2020/08/07 Python
10张动图学会python循环与递归问题
2021/02/06 Python
Hawes & Curtis官网:英国经典品牌
2019/07/27 全球购物
党员创先争优承诺书
2014/03/26 职场文书
老公爱的承诺书
2014/03/31 职场文书
学校春季防火方案
2014/06/08 职场文书
证券区域经理岗位职责
2015/04/10 职场文书
离婚被告答辩状
2015/05/22 职场文书
预备党员介绍人意见
2015/06/01 职场文书
初中团支书竞选稿
2015/11/21 职场文书
MySQL如何修改字段类型和字段长度
2022/06/10 MySQL