要快速实现用户列表查询、订单筛选和销量统计,应熟练使用ActiveRecord链式查询:findOne()查单条,find()->all()查全部,where()支持数组/操作符语法,count()/sum()等返回标量,column()需配合asArray()保持数值类型,findBySql()和with()分别处理原生SQL与关联预加载。

要在Yii2项目中快速查出用户列表、按条件筛选订单、统计销量总数,又不想写原始SQL或反复调试Query Builder,就得吃透ActiveRecord的查询方法链——它把数据库操作封装成可读性强、可链式调用的对象方法。
基础单条与批量查询
直接用主键查单条记录最常用:调用findOne($id),例如User::findOne(123)会生成SELECT * FROM user WHERE id = 123并返回一个User对象。
findAll()已废弃,统一用find()->all()替代;若需查全部用户,写User::find()->all()即可,返回User对象数组。
注意:【findOne()内部会自动加status=1等默认条件(如果模型里定义了】,比如你重写了findByCondition()或在rules()中设了默认scope,结果可能为空——此时应检查模型类中的find()是否被覆写过。
带条件的查询构建
方法一:使用数组条件语法
User::find()->where(['status' => 1, 'type' => 'vip'])->all()生成WHERE status = 1 AND type = 'vip'。
方法二:使用操作符数组(支持like、in、between等)
User::find()->where(['like', 'name', '张'])查姓名含“张”的用户;['in', 'id', [1,5,8]]查ID在指定列表里的记录。
方法三:链式组合多条件
第一步:User::find()初始化查询对象;
第二步:→where(['status' => 1])设定基础过滤;
第三步:→andWhere(['>=', 'created_at', '2025-01-01'])追加时间范围;
第四步:→orderBy('updated_at DESC')按更新时间倒序;
第五步:→limit(20)只取前20条;最后调用all()执行。
这一步不能漏掉all()或one(),否则只是构建了查询对象,根本不会发SQL到数据库。
聚合与标量结果获取
count()直接返回整数:如User::find()->where(['status' => 1])->count()得活跃用户总数。
sum('amount')计算字段总和,average('score')算平均分,max('price')找最高价——这些方法返回的是PHP标量值,不是AR对象。
scalar()取第一行第一列,常用于SELECT COUNT(*)之后;column()取整列值,返回一维数组,比如User::find()->select('email')->column()得到所有邮箱列表。
【column()默认返回的是字符串数组,若字段是int类型且需要保持数字类型,必须配合asArray()->column()使用】,否则数值会被转成字符串。
原生SQL与复杂查询
方法1:用findBySql()
User::findBySql("SELECT u.*, p.title FROM user u LEFT JOIN profile p ON u.id = p.user_id")->all()——注意:返回的是User对象,但JOIN字段p.title不会自动映射到User属性里,得用asArray()才能拿到完整字段。
方法2:用createCommand()执行纯SQL
Yii::$app->db->createCommand("UPDATE user SET status = 0 WHERE last_login bindValue(':date', '2024-01-01')->execute()——这是非AR方式,不触发模型事件和验证,适合后台批处理。
方法3:混合使用with()做关联预加载
Order::find()->with('customer', 'items.product')->where(['status' => 'paid'])->all()——一次查出订单+客户信息+商品详情,避免N+1查询。注意:with()括号里写的是关系名,不是表名,必须在Order模型里正确定义getCustomer()等getter方法。


















