Laravel或hyperf使用Db时如何给所有的select语句增加“/*FORCE_MASTER*/”
1. Laravel5.6或hyperf1.1
2. 业务场景
目前主从复制是使用了阿里云的rds,默认select语句查询的都是从库,但有一些场景需要查询主库,阿里云查询主库的方式是在select语句前面加 “/FORCE_MASTER/”,但是项目使用的大部分是模型或db生成器查询,想实现一个可以允许链式调用查询主库的方式
3. 期望得到的结果?(有啥想法的也可以提一下,说不定可以实现)
Db::connection("xpx")
->table('users')
->forceMaster() // 加上此调用代表查询主库
->first();
期望生成的SQL为:
/*FORCE_MASTER*/ select * from `ecs_users` where `user_id` = ?
forceMaster() 这个方法的作用是期望在当前select语句中开头增加 “/FORCE_MASTER/” 字符串
4. 当前进度
目前只找到了在vendor中如何增加,但不知道怎么通过模型调用增加前缀字符串,找到的vendor中的代码及需要的改动如下:
hyperf中的文件路径为(Laravel中基本差不多):namespace Hyperf\Database\Query\Grammars;
/**
* Compile the "select *" portion of the query.
*
* @param array $columns
* @return null|string
*/
protected function compileColumns(Builder $query, $columns)
{
// If the query is actually performing an aggregating select, we will let that
// compiler handle the building of the select clauses, as it will need some
// more syntax that is best handled by that function to keep things neat.
if (! is_null($query->aggregate)) {
return;
}
$select = $query->distinct ? 'select distinct ' : 'select ';
// 在vendor中改的话是在此处增加
// $select = "/*FORCE_MASTER*/ {$select}";
return $select . $this->columnize($columns);
}
把下述代码放到
\App\Providers\AppServiceProvider::register
里面(适用于 Laravel 5.6)…
最终成果: