asArray()必须在one()/all()前调用才能生效,返回数据库原始字段数组,不触发模型事件和getter,性能优于toArray(),但需手动处理格式化、字段过滤和空值。

用 asArray() 切换查询结果格式
Active Record 默认返回对象实例,想拿纯数组就只能在 Query 阶段显式切换。核心就是调用 asArray() 方法,它必须出现在 one() 或 all() 之前,否则无效——因为 all() 已经执行并返回了对象数组。
常见错误是写成 User::find()->all()->asArray(),这会报错或静默忽略;正确写法是:
User::find()->asArray()->one(); User::find()->asArray()->all(); User::find()->where(['status' => 1])->asArray()->all();
-
asArray()接收一个布尔参数,默认true,传false等价于不调用 - 返回的数组键名是字段名(如
'id'、'created_at'),不是模型属性别名 - 关系数据(如
with('posts'))不会自动展开为嵌套数组,仍需手动处理
单条记录转数组:别漏掉 asArray() 的链式位置
findOne() 是静态快捷方法,它内部封装了 one(),但**不支持链式调用 asArray()**。所以 User::findOne($id)->asArray() 是错的——对象没有这个方法。
要获取单条数组,必须走完整 Query 流程:
User::find()->where(['id' => $id])->asArray()->one();
- 不能对
findOne()结果再调asArray(),那是对象方法,不是 Query 方法 - 如果只查主键,
User::find()->where(['id' => $id])->asArray()->one()和User::find()->asArray()->where(['id' => $id])->one()效果一样,顺序不影响 SQL,但推荐把asArray()放前面更清晰 - 注意判空:返回可能是
null,别直接用['name']访问
批量处理数组时,asArray() 比 toArray() 更轻量
有人习惯先取对象再调 $model->toArray(),这会创建一堆 ActiveRecord 实例,内存和 CPU 开销明显更大。尤其查几百条时,差异肉眼可见。
asArray() 跳过对象构造,从 PDOStatement 直接 fetch 为关联数组,省去属性赋值、事件触发、验证器初始化等全部开销。
- 查 100 条用户:
User::find()->asArray()->all()比array_map(fn($m) => $m->toArray(), User::find()->all())快 3–5 倍 -
asArray()返回的是原始数据库值(比如created_at还是 int 时间戳),不经过模型 getter 或 Formatter 处理 - 如果需要格式化,得自己做:
'created_at' => date('Y-m-d', $row['created_at']) ?: '',而不是依赖getCreatedAtFormatted()
JSON 响应里混用对象和数组容易踩的坑
控制器里设了 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON 后,直接 return $model 或 return $model->toArray() 都能工作,但混合使用就容易出问题。
比如你写了 return ['data' => User::find()->asArray()->all(), 'count' => User::find()->count()],看着没问题,但要注意:
-
asArray()结果里时间戳还是整数,前端可能解析失败;而$model->toArray()可能已通过 getter 格式化为字符串 - 如果模型定义了
fields()或extraFields(),asArray()完全无视它们——它只吐数据库字段 - 敏感字段(如
password_hash)在asArray()下照常出现,没经过fields()过滤,有泄露风险
真正交付前,得确认字段是否被过滤、时间是否可读、null 是否被妥善处理——这些都不是 asArray() 自动解决的。


















