数据查询

简单数据查询:

$this->db()->get('user-id-1'); //select * from pre_user where id = 1;
$this->db()->get('user-name-abc'); //select * from pre_user where name='abc';
多个条件
$this->db()->get('user-id-1-name-abc'); //id和name为and关系
$this->db()->get('user-id-1-name-abc', false); //id和name为or关系
$this->db()->get('user-id-1-name-abc', true, true);//id和name为and关系。且在数据库主从读写分离时强制从主库读(适用于对实时要求高的时候主从架构强制读主库)
$this->db()->get('user-id-1-name-abc', true, false, 'u_');//指定表前缀为u_。假定配置中配置的表前缀不为u_。这边可单独指定前缀

get方法默认最多取1000条数据,如果大于1000条请使用select方法或chunk方法,参考下文

特殊说明

在这边要特殊说明 $this->db() 这边的db()方法,在配置文件章节中我们看到在normal.php中有配置项default_db这个配置,它是默认连接的数据库集群,如果我们的业务中有需要连接多个数据库集群呢? 这时只要在normal.php中添加相关的数据库配置项如

'default_db' => [
    'driver' => 'MySql.Pdo', //数据库驱动
    'master' => [
        'host' => 'localhost', //数据库主机
        'username' => 'root', //数据库用户名
        'password' => '', //数据库密码
        'dbname' => 'test', //数据库名
        'charset' => 'utf8', //数据库编码
        'tableprefix' => 'h_', //数据表前缀
        'pconnect' => false, //是否开启数据库长连接
        'engine' => ''//数据库引擎
    ],
    'slaves' => [], //从库配置

    //查询数据缓存时间,表数据有变动会自动更新缓存。设置为0表示表数据没变动时缓存不过期。
    //这边设置为3600意思是即使表数据没变动也让缓存每30s失效一次,这样可以让缓存空间更合理的利用.
    //如果不想启用缓存直接配置为false
    'cache_expire' => 30,//查询数据缓存时间
],
'game_db' => [
    'driver' => 'MySql.Pdo', //数据库驱动 或者MongoDB.MongoDB使用MongoDB驱动
    'master'=> [
        'host' => 'localhost', //数据库主机
        'username' => 'root', //数据库用户名
        'password' =>'', //数据库密码
        'dbname' => 'test', //数据库名
        'charset' => 'utf8', //数据库编码
        'tableprefix' => 'g_', //数据表前缀
        'pconnect' => false, //是否开启数据库长连接
        'engine'=>''//数据库引擎
    ],
    'slaves'=> [],

    //查询数据缓存时间,表数据有变动会自动更新缓存。设置为0表示表数据没变动时缓存不过期。
    //这边设置为3600意思是即使表数据没变动也让缓存每30s失效一次,这样可以让缓存空间更合理的利用.
    //如果不想启用缓存直接配置为false
    'cache_expire' => 30,
],

然后在写查询语句的时候直接 $this->db('game_db')即可,不写则为调用default_db配置的数据库集群。当然了如果数据库配置是从其它渠道过来的比如从db来的,也可在调用db()方法时直接传入数组

复合查询

获取多行
 $this->db()->table('user')
    ->columns('id', 'name')
    ->where('id', 1)
    ->whereGt('id', 7)
    ->orderBy('id', 'desc')
    ->select(0, 10);
//生成的语句 SELECT id, name FROM pre_user WHERE id = 1 AND id > 7 ORDER BY id DESC LIMIT 0, 10;

->where(['id' =>1, 'name'=>'name'], true)//where支持传数组生成`id`=1 AND`name`='name'
->where(['id' =>1, 'name'=>'name'], false)//where支持传数组生成`id`=1 OR `name`='name'
$this->db()->table('user')
    ->columns(['id' => 'user_id', 'name'])
    ->lBrackets()
        ->whereLike('name', false, '哈哈', true)
        ->whereNotLike('name', true, 'abc', false)
    ->rBrackets()
    ->_or()
    ->lBrackets()
        ->whereGte('id', 7)
        ->whereIn('id', array(1, 3, 5, 50, 100, 500))
        ->whereLt('id', 20)
        ->whereBetween('id', 1, 1000)
    ->rBrackets()
    ->groupBy('level')
    ->having('id', '>', 10)
    ->limit(0, 1)
    ->select();

    //v2.7.7起这条语句可以写为
    $this->db()->table('user')
            ->columns(['id' => 'user_id', 'name'])
            ->_and(function () {
                $this->db()->whereLike('name', false, '哈哈', true)
                    ->whereNotLike('name', true, 'abc', false);
            })
            ->_or(function () {
                $this->db()->whereGte('id', 7)
                    ->whereIn('id', array(1, 3, 5, 50, 100, 500))
                    ->whereLt('id', 20)
                    ->whereBetween('id', 1, 1000);
            })
            ->groupBy('status')
            ->having('id', '>', 10)
            ->limit(0, 1)
            ->select();
            //对比两种写法可发现(_and/_or方法支持传入闭包。闭包内执行的语句为查询分组)

//生成的语句 SELECT id AS user_id, name FROM pre_user WHERE (name LIKE '哈哈%' AND name NOT LIKE '%abc') OR ( id >= 7 AND  id IN (1, 3, 5, 50, 100, 500) AND id < 20 AND id BETWEEN 1 AND 1000 ) GROUP BY level HAVING id > 10 LIMIT 0, 1;

select(0, 1),等价于limit(0, 1)->select()。所以一般情况直接使用select即可 默认如果直接->select() 不传条数、也不调用limit的话select只查100条数据。这个主要是为了防止没显式传条数的时候查全表会把数据库搞挂了。查大批量的数据比如一次查个大几万几十万建议使用chunk方法

只获取一行

v2.7.2+可用

 $this->db()->table('user')
    ->where('id', 1)
    ->getOne();

//相当于select(0, 1) && return $result[0];
只获取第一行的某个字段

v2.7.3+可用

 $this->db()->table('user')
    ->where('id', 1)
    ->getOneValue('name');
//相当于getOne(0, 1) && return $result['name'];
获取某列值的列表

v2.7.3+可用

 $this->db()->table('user')
 ->whereGt('id', 1)
 ->plunk('name');
//返回的数组为 ['name1', 'name2'...]
 $this->db()->table('user')
 ->whereGt('id', 1)
 ->plunk('name', 'id');
//返回的数组为 ['id1' => 'name1', 'id2' => 'name2'...]
组块结果集

v2.7.3+可用

如果你需要处理成千上百条数据库记录,可以使用chunk方法,该方法一次获取结果集的一小块,然后传递每一小块数据到闭包函数进行处理。

 $this->db()->table('user')
     ->whereGt('id', 10)
     ->chunk(100, function($users) {
        foreach ($users as $user) {
            // 处理结果集...
        }
    });
//以100条数据为单位分批处理。假设共有1w条数据。则上面的匿名函数会被调用100次

你可以通过从闭包函数中返回false来终止组块的运行:

 $this->db()->table('user')
     ->whereGt('id', 10)
     ->chunk(100, function($users) {
        foreach ($users as $user) {
            // 处理结果集...
            return false;
        }
    });

连接

$this->db('game_db')->table(array('user' => 'u'))
    ->join(array('group' => 'g'), 'u.gid = g.id')
    ->leftJoin(array('acl' => 'a'), 'a.uid = u.id')
    ->rightJoin(array('order' => '0'), 'o.uid = u.id')
    ->select();
// 生成的语句 SELECT * FROM user as u INNER JOIN group AS g ON u.gid = g.id LEFT JOIN acl AS a ON a.uid = u.id  RIGHT JOIN order AS o ON o.uid = u.id;

自动注入表名,表前缀

在以上的操作上我们都要手动执行$this->db('xxx')->table('xxx', 'xxx_');如果在一个model里有多个方法,那么每一个我方法们都要执行一次$this->db()->table()。为了简化这个操作。可以直接使用快捷方法或者执行$this->mapDbAndTable()

class ApiLogModel extends Model
{
    protected $db = 'game_db';//连接标识//默认为default_db

    protected $table = 'apilog';//表名,不带前缀 

    protected $tablePrefix = 'pre_';//假设配置中的前缀不为pre_,这边单独配置表前缀
}

在上面的代码中。我们声明了要连接的dbgame_db。操作的表为apilog。表前缀为pre_,执行$this->mapDbAndTable()相当于执行了$this->db($this->db)->table($this->table, $this->tablePrefix);。当一个model中有多个方法时mapDbAndTable可以有效减少代码量,同时将表名和特殊的表前缀声明为model的属性便于后期修改。


上面基本上覆盖了大部分查询的情况,其它api在IDE中$this->db()->即会自动提示或者查看api手册

results matching ""

    No results matching ""