数据库

    直接操作 Db 对象

    1. $db = Db::getNewInstance();
    2. // 读库
    3. $db = Db::getNewInstance($poolName, QueryType::READ);
    4. // 写库
    5. $db = Db::getNewInstance($poolName, QueryType::WRITE);
    6. // 获取数据库连接实例,每个RequestContext中共用一个
    7. $db = Db::getInstance();
    8. // 读库
    9. $db = Db::getInstance($poolName, QueryType::READ);
    10. // 写库
    11. $db = Db::getInstance($poolName, QueryType::WRITE);
    12. // 释放连接,回归连接池
    13. Db::release($db);
    14. $returnValue = Db::use(function(IDb $db){
    15. // 操作 $db
    16. return 'imi';
    17. }); // imi

    IMI 中数据库查询连贯操作都来自于查询器,查询器的创建方式:

    1. use Imi\Db\Db;
    2. $query = Db::query();

    手动控制事务:

    1. // 开启事务
    2. Db::getInstance()->beginTransaction();
    3. // 提交事务
    4. Db::getInstance()->commit();
    5. // 回滚事务
    6. Db::getInstance()->rollBack();

    获取连接顺带自动开启/提交/回滚事务:

    1. Db::transUse(function(IDb $db){
    2. });
    3. Db::transUse(function(IDb $db){
    4. }, $poolName, QueryType::WRITE);

    获取连接后,想要使用某个连接,执行事务操作,自动开启/提交/回滚事务:

    1. $db = Db::getInstance();
    2. Db::trans($db, function(IDb $db){
    3. });

    自动事务处理

    @Transaction 注解,类:Imi\Db\Annotation\Transaction

    这个注解可以加在任意方法上,在方法调用前开启事务,在方法中抛出异常时回滚事务,方法成功返回时提交事务。

    @Transaction

    @Transaction(autoCommit="自动提交事务true/false,默认为true")

    事务嵌套(默认)

    @Transaction(type=TransactionType::NESTING)

    该方法必须在事务中被调用

    @Transaction(type=TransactionType::REQUIREMENT)

    如果当前不在事务中则开启事务

    @Transaction(type=TransactionType::AUTO)

    部分回滚:

    @Transaction(rollbackType=RollbackType::PART, rollbackLevels="回滚层数,默认为1")

    指定表 (table/from)

    1. // 指定表名
    2. Db::query()->table('tb_test');
    3. // 指定表名并且设置别名
    4. Db::query()->table('tb_test', 'test');
    5. // 指定表名和数据库名
    6. Db::query()->table('tb_test', null, 'db1');
    7. // 传入参数原样代入到SQL中
    8. Db::query()->tableRaw('tb_test');

    distinct

    1. // 结果唯一
    2. Db::query()->distinct();
    3. // 结果不唯一
    4. Db::query()->distinct(false);

    指定字段 (field)

    1. // 指定一个字段
    2. Db::query()->field('id');
    3. // 指定多个字段,也支持设置别名。空格和as都支持
    4. Db::query()->field('id', 'name1 name', 'age1 as age');
    5. // 和上面的用法等同
    6. Db::query()->field(['id', 'name1 name', 'age1 as age']);
    7. // 传入参数原样代入到SQL中
    8. Db::query()->fieldRaw('id, name1 name, age1 as age');

    条件 where

    where

    1. // id = 1
    2. Db::query()->where('id', '=', 1);
    3. // id > 1
    4. Db::query()->where('id', '>', 1);
    5. // title like '%test%'
    6. Db::query()->where('title', 'like', '%test%');
    7. // id between 1 and 10
    8. Db::query()->where('id', 'between', [1, 10]);
    9. // id not between 1 and 10
    10. Db::query()->where('id', 'not between', [1, 10]);
    11. // or id = 1
    12. Db::query()->where('id', '=', 1, 'or');
    13. Db::query()->orWhere('id', '=', 1);

    TP 风格 where

    1. // select * from `tb_test` where (`id` = 1 or (`id` = 2 ) and `title` like '%test%' and `age` > 18 and (`id` = 2 or (`id` = 3 ) ) )
    2. Db::query()->from('tb_test')->whereEx([
    3. 'id' => 1,
    4. 'or' => [
    5. 'id' => 2,
    6. ],
    7. 'title' => ['like', '%test%'],
    8. 'age' => ['>', 18],
    9. 'and' => [
    10. 'id' => 2,
    11. 'or' => [
    12. 'id' => 3,
    13. ]
    14. ]);

    whereRaw

    1. // 传入参数原样代入到SQL中
    2. Db::query()->whereRaw('id >= 1');
    3. // 传入参数原样代入到SQL中,并且为or条件
    4. Db::query()->whereRaw('id >= 1', 'or');
    5. Db::query()->orWhereRaw('id >= 1');

    whereBrackets

    1. // where id = 1 or (age < 14)
    2. Db::query()->where('id', '=', 1)->whereBrackets(function(){
    3. // 直接返回字符串
    4. return 'age < 14';
    5. }, 'or');
    6. // where id = 1 or (age < 14)
    7. Db::query()->where('id', '=', 1)->whereBrackets(function(){
    8. // 直接返回字符串
    9. return new \Imi\Db\Query\Where\Where('age', '<', 14);
    10. }, 'or');
    11. Db::query()->where('id', '=', 1)->orWhereBrackets(function(){
    12. // 直接返回字符串
    13. return new \Imi\Db\Query\Where\Where('age', '<', 14);
    14. });

    whereStruct

    1. // or age < 14
    2. Db::query()->whereStruct(new \Imi\Db\Query\Where\Where('age', '<', 14), 'or');
    3. Db::query()->orWhereStruct(new \Imi\Db\Query\Where\Where('age', '<', 14));

    其它

    1. // or age between 1 and 14
    2. Db::query()->whereBetween('age', 1, 14, 'or');
    3. Db::query()->orWhereBetween('age', 1, 14);
    4. // or age not between 1 and 14
    5. Db::query()->whereNotBetween('age', 1, 14, 'or');
    6. Db::query()->orWhereNotBetween('age', 1, 14);
    7. // or age in (1,2,3)
    8. Db::query()->whereIn('age', [1, 2, 3], 'or');
    9. Db::query()->orWhereIn('age', [1, 2, 3]);
    10. // or age not in (1,2,3)
    11. Db::query()->whereNotIn('age', [1, 2, 3], 'or');
    12. Db::query()->orWhereNotIn('age', [1, 2, 3]);
    13. // or age is null
    14. Db::query()->whereIsNull('age', 'or');
    15. Db::query()->orWhereIsNull('age');
    16. // or age is not null
    17. Db::query()->whereIsNotNull('age', 'or');
    18. Db::query()->orWhereIsNotNull('age');

    JSON 字段支持

    join

    1. // select * from tb_test1 left join tb_test2 on tb_test1.aid = tb_test2.bid
    2. Db::query()->table('tb_test1')->join('tb_test2', 'tb_test1.aid', '=', 'tb_test2.bid');
    3. // select * from tb_test1 left join tb_test2 as test2 on tb_test1.aid = test2.bid
    4. Db::query()->table('tb_test1')->join('tb_test2', 'tb_test1.aid', '=', 'test2.bid', 'test');
    5. // select * from tb_test1 right join tb_test2 on tb_test1.aid = tb_test2.bid and tb_test1.age > 14
    6. Db::query()->table('tb_test1')->join('tb_test2', 'tb_test1.aid', '=', 'tb_test2.bid', null, new \Imi\Db\Query\Where\Where('tb_test1.age', '>', '14'), 'right');
    7. // select * from tb_test1 left join tb_test2 on tb_test1.aid = tb_test2.bid
    8. Db::query()->table('tb_test1')->joinRaw('left join tb_test2 on tb_test1.aid = tb_test2.bid');
    9. // 下面三种用法,第5个参数都支持传Where
    10. // left join
    11. Db::query()->table('tb_test1')->leftJoin('tb_test2', 'tb_test1.aid', '=', 'tb_test2.bid');
    12. // right join
    13. Db::query()->table('tb_test1')->rightJoin('tb_test2', 'tb_test1.aid', '=', 'tb_test2.bid');
    14. // cross join
    15. Db::query()->table('tb_test1')->crossJoin('tb_test2', 'tb_test1.aid', '=', 'tb_test2.bid');

    order

    1. // order by id asc, age desc
    2. Db::query()->order('id')->order('age', 'desc');
    3. // order by id desc
    4. Db::query()->orderRaw('id desc');

    group by

    1. // group by id, name
    2. Db::query()->group('id', 'name');
    3. // group by sum(id)
    4. Db::query()->groupRaw('sum(id)');

    having

    having()用法同where()

    havingRaw()用法同whereRaw()

    havingBrackets()用法同whereBrackets()

    havingStruct()用法同whereStruct()

    1. // limit 900, 100
    2. Db::query()->page(10, 100);
    3. // limit 10, 1
    4. Db::query()->offset(10)->limit(1);
    5. // limit 1
    6. Db::query()->limit(1);

    查询执行

    查询记录

    查询单行

    1. $result = Db::query()->table('tb_test')->select();
    2. $result->get(); // 数组

    查询多行

    1. $result = Db::query()->table('tb_test')->select();
    2. $result->getArray(); // 数组内嵌套数组
    3. $result->getArray($className); // 数组内嵌套$className对应的类对象
    4. $result->getRowCount(); // 获取查询出的记录行数

    聚合函数

    1. // count(*)
    2. Db::query()->table('tb_test')->count();
    3. // count(id)
    4. Db::query()->table('tb_test')->count('id');
    5. // sum(id)
    6. Db::query()->table('tb_test')->sum('id');
    7. // avg(id)
    8. Db::query()->table('tb_test')->avg('id');
    9. // max(id)
    10. Db::query()->table('tb_test')->max('id');
    11. // min(id)
    12. Db::query()->table('tb_test')->min('id');
    13. // 其它自定义:test(id)
    14. Db::query()->table('tb_test')->aggregate('test', 'id');

    插入记录

    1. // insert into tb_test(name, age) values('yurun', 666)
    2. $result = Db::query()->table('tb_test')->insert([
    3. 'name' => 'yurun',
    4. 'age' => 666,
    5. ]);
    6. // insert into tb_test values('yurun', 666)
    7. $result = Db::query()->table('tb_test')->insert([
    8. 'yurun',666,
    9. ]);
    10. $result->isSuccess(); // SQL是否执行成功
    11. $result->getLastInsertId(); // 获取最后插入的ID
    12. $result->getAffectedRows(); // 获取影响行数

    批量插入

    1. $result = Db::query()->from('test')->batchInsert([
    2. ['name'=>'a'],
    3. ['name'=>'b'],
    4. ['name'=>'c'],
    5. ]);
    6. $result->isSuccess(); // SQL是否执行成功
    7. $result->getAffectedRows(); // 获取影响行数

    更新记录

    1. // update tb_test set name = 'yurun', age = 666 where id = 1
    2. $result = Db::query()->table('tb_test')->where('id', '=', 1)->update([
    3. 'name' => 'yurun',
    4. 'age' => 666,
    5. ]);
    6. // $result使用方法同上

    替换数据

    1. // replace into tb_test set id = 1, name = 'yurun', age = 666
    2. $result = Db::query()->table('tb_test')->replace([
    3. 'id' => 1,
    4. 'name' => 'yurun',
    5. 'age' => 666,
    6. ]);

    递增/递减

    1. // score 递增 1
    2. $result = Db::query()->table('tb_test')
    3. ->where('id', '=', 1)
    4. ->setFieldInc('score')
    5. ->update();
    6. // score 递增 10
    7. $result = Db::query()->table('tb_test')
    8. ->where('id', '=', 1)
    9. ->setFieldInc('score', 10)
    10. ->update();
    11. // score 递减 1
    12. $result = Db::query()->table('tb_test')
    13. ->where('id', '=', 1)
    14. ->setFieldDec('score')
    15. ->update();
    16. // score 递减 10
    17. $result = Db::query()->table('tb_test')
    18. ->where('id', '=', 1)
    19. ->setFieldDec('score', 10)
    20. ->update();

    update/insert/replace时使用表达式

    1. // update tb_test set score = score + 1 where id = 1
    2. $result = Db::query()->table('tb_test')
    3. ->where('id', '=', 1)
    4. ->setFieldExp('score', 'score + 1')
    5. ->update();

    删除记录

    1. // delete from tb_test where id = 1
    2. $result = Db::query()->table('tb_test')->where('id', '=', 1)->delete();
    3. // $result使用方法同上

    参数绑定

    复杂的查询时,难免需要拼接 SQL,这时候就需要参数绑定来防止注入了!

    1. // where id = 123
    2. $result = Db::query()->whereRaw('id = ?')->bindValue(1, 123);
    3. $result = Db::query()->whereRaw('id = :val')->bindValue(':val', 123);
    4. // 批量绑定
    5. $result = Db::query()->bindValues([
    6. ':name' => 'yurun',
    7. ':age' => 666,
    8. ])->execute('select * from tb_test where name = :name and age = :age');
    1. $result = Db::query()->table('tb_test')->select();
    1. $success = $result->isSuccess(); // true/false

    获取最后插入的ID

    用于获取新增记录的自增字段值

    1. $lastInsertId = $result->getLastInsertId(); // int

    获取影响行数

    1. $rows = $result->getAffectedRows();

    update 时,如果没有值被改变,可能会返回0

    返回一行数据

    返回数组

    1. $dataArray = $result->get();

    返回对象

    实例化这个类时,把数组传入构造方法

    1. $dataArray = $result->get(XXXModel::class);

    返回数组列表

    成员为数组

    1. $list = $result->getArray();

    成员为对象

    1. $list = $result->getArray(XXXModel::class);

    获取一列

    1. $ids = Db::query()->field('id')->select()->getColumn();
    2. // 结果格式:[1, 2, 3]

    获取标量结果

    1. $name = Db::query()->field('name')->where('id', '=', 1)->select()->getScalar();

    获取记录行数

    得到取回多少条记录

    1. $rowCount = $result->getRowCount();

    获取执行的SQL

    1. $statement = $result->getStatement(); // \Imi\Db\Interfaces\IStatement