asArray()比toArray()快得多,因前者跳过AR实例化直接生成PHP数组,后者需创建对象并触发属性赋值、事件、关系初始化等开销;仅当需fields()定制、关联数据导出或访问器逻辑时才用toArray()。

直接用 asArray() 获取原始数组,确实比先取 AR 对象再用 array_map(...->toArray()) 快得多——这不是错觉,是 Yii2 底层机制决定的。
asArray 跳过对象实例化
asArray() 让 Query 直接从 PDO 结果集读取数据,生成纯 PHP 数组,完全不创建 ActiveRecord 实例。而 toArray() 必须先 new 出 100 个 AR 对象,触发属性赋值、事件、关系初始化(哪怕没用到),光是构造函数和属性映射就吃掉大量时间。
toArray 隐含开销远超表面
每个 ActiveRecord::toArray() 默认会:
- 检查
fields()和extraFields()方法(即使空实现也调用) - 遍历所有声明的属性,做类型转换和过滤
- 若启用
$expand(如关联字段),还会递归执行查询或懒加载 - 触发
beforeAction类似行为(如afterFind事件)
什么时候必须用 toArray?
只有真需要以下能力时才值得多花这几毫秒:
- 字段名经
fields()动态定制(比如权限控制下隐藏某些字段) - 要导出关联模型数据(
with('profile', 'orders')+toArray(['profile', 'orders'])) - 依赖 AR 的访问器(
getFullName())、格式化逻辑(getAttributeLabel())或业务规则
高效替代方案
如果只要基础字段且想保持一定可读性,推荐组合使用:
-
asArray()+ 手动键名映射(如['user_id' => 'id', 'full_name' => 'name']) - 查关联数据时,用
joinWith()+asArray()拼宽表,避免 N+1 和对象膨胀 - 复杂格式需求,写独立的 DTO 类或数组转换器,不耦合 AR 生命周期


















