当前位置:首页 > 问答 > 正文

ThinkPHP5数据库查询那些事儿,学好了才能真用得溜,关键就在操作细节上

开始)

ThinkPHP5数据库查询那些事儿,学好了才能真用得溜,关键就在操作细节上,这篇文章就是来聊聊那些看似简单,但一不注意就会踩坑的细节,咱们不整那些高大上的理论,就说说实际开发里怎么把数据库查得又快又准。

起步别用Db类?模型才是亲儿子

很多新手图省事,一上来就用Db::name('user')这种方式直接操作表,不是说不行,但对于复杂的项目,这习惯不好,ThinkPHP5更推荐使用模型(Model),模型就像是给数据库表穿了一件外衣,它不仅代表了这张表,还能定义各种关联关系和行为。

你有个用户表user,就创建一个User模型类,这样做的好处太多了:代码更清晰,所有对用户表的操作都集中在User模型里,不会散落在各个控制器中,以后改起来方便,模型能自动完成数据验证、自动写入时间戳(比如create_timeupdate_time),非常省心,最重要的是,处理表关联关系时,模型的优势是Db类没法比的,第一个细节就是:养成使用模型的习惯

ThinkPHP5数据库查询那些事儿,学好了才能真用得溜,关键就在操作细节上

查询构造器:你的SQL翻译官

无论是用Db类还是模型,核心工具都是查询构造器,它让你能用PHP方法链式调用的方式来“写”SQL,避免了直接拼接SQL字符串的繁琐和安全隐患(比如SQL注入),但怎么链,有讲究。

  1. 链式操作的顺序大部分情况下无所谓,但where要早:像field(指定查询字段)、order(排序)、limit(限制条数)这些方法,你放在链子的前面还是后面,最终生成的SQL是一样的,但where条件最好早点写,这样逻辑上更清晰,一看就知道你要查什么。
  2. where方法的三种姿势:这是最常用的,也是最容易迷糊的。
    • 表达式查询(最常用)where('字段名', '操作符', '值'),比如where('age', '>', 18),如果操作符是等于,可以简写成where('字段名', '值'),比如where('status', 1)
    • 数组查询(条件多时很整洁)where(['status' => 1, 'age' => ['>', 18]]),把一个条件的数组传进去,代码看起来非常干净。
    • 闭包查询(构造复杂OR条件的神器):这是关键细节!当你想要(status = 1 AND age > 18) OR (name like '%张三%')这样的复杂条件时,闭包就派上用场了。
      ->where(function ($query) {
          $query->where('status', 1)->where('age', '>', 18);
      })->whereOr(function ($query) {
          $query->where('name', 'like', '%张三%');
      })

      用闭包把要“抱团”的条件包起来,逻辑一下就清晰了。

find()select(),别傻傻分不清

ThinkPHP5数据库查询那些事儿,学好了才能真用得溜,关键就在操作细节上

这也是新手常犯的错误。

  • find()查一条数据,它返回的直接是一个一维数组(或者模型对象),就算数据库里有10条符合条件的数据,它也只拿第一条,所以它后面不能跟count()delete()等方法,通常用于根据主键查询,比如User::get(1)(模型写法,相当于find(1))。
  • select()查多条数据,它返回的是一个二维数组的集合(或者模型对象的集合),哪怕结果只有一条,你可以对它进行遍历等操作。

口诀:找一条用find,找一堆用select

获取值:小心“对象”和“数组”的坑

ThinkPHP5的查询结果默认是“对象”形式(模型对象或者stdClass对象),你可以通过toArray()方法把它转成数组,但这里有个细节:如果你用的是Db类查出来多条数据(select),直接dump出来看着像数组,但其实每个元素都是对象,当你用Db::name('user')->select()得到一个结果集$users,想取第一条数据的名字时,应该用$users[0]->name,而不是$users[0]['name'],如果想用数组方式访问,可以在查询时加个->select()->toArray(),或者修改数据库配置的result_typearray,这个细节不注意,页面就会报错“Cannot use object of type stdClass as array”。

ThinkPHP5数据库查询那些事儿,学好了才能真用得溜,关键就在操作细节上

关联查询:模型的终极武器

为什么强调用模型?关联查询是最大理由,用户”有多个“文章”,在User模型里,你可以定义一个articles方法:

public function articles()
{
    return $this->hasMany('Article', 'user_id');
}

定义好后,神奇的事情发生了,你想查某个用户和他写的所有文章,不用写复杂的JOIN SQL,直接:

$user = User::with('articles')->find(1);
// 然后通过 $user->articles 就能拿到这个用户的所有文章数组

这种“预载入”查询(with方法)效率很高,因为它用一条SQL查用户,再用一条SQL批量查出了所有相关文章,避免了N+1查询问题(即循环用户列表时,每循环一次都查一次数据库),这是ThinkPHP5模型关联设计的精髓所在。

性能细节:你忽略了吗?

  1. 只查需要的字段:千万别动不动就select()不传参数,那意味着SELECT *,如果表字段很多,而你只需要两三个,大量的数据传输和PHP内存分配就浪费了,用field('id, name, title')明确指定字段。
  2. 用好索引:数据库层面的优化更重要,你的where条件和order排序的字段,如果是常用的,一定要在数据库里建立索引,否则数据量一上来,查询就会慢得像蜗牛。

ThinkPHP5的数据库查询,入门容易,但想“用得溜”,就得在这些细节上下功夫:首选模型、玩转查询构造器(特别是闭包)、分清findselect、注意结果集类型、善用关联查询、时刻惦记着性能,把这些细节都摸透了,你的代码才会既健壮又高效。 结束)