$recursive=false仅限制对象属性的递归转换,不处理已存在的嵌套数组;对象转为一维数组,而原数组(如tags)保持原样,不受该参数影响。

因为 $recursive = false 只控制“对象转数组”时是否递归处理其属性值,**不控制嵌套数组本身**。
它只停在对象层,不停在数组层
ArrayHelper::toArray 的设计逻辑是:
- 当遇到一个 对象(如 ActiveRecord 实例),且
$recursive = false,则该对象只转为一维数组(仅直接 public 属性),不再深入其关联对象(比如$post->author不会展开); - 但当原数据里已经存在 普通数组(包括多维、嵌套数组),无论
$recursive是 true 还是 false,这些数组都会被原样保留 —— 它们本就是数组,不需要“递归转换”,也不受该参数限制。
常见误解场景
例如你传入:
$data = [
'id' => 1,
'profile' => new UserProfile(), // 对象
'tags' => ['php', 'yii2'], // 已是数组
];
即使设 $recursive = false,结果中 'tags' 仍是 ['php', 'yii2'](没变平、没丢),而 'profile' 只转成它自己的 public 属性,不会继续展开 $profile->user(如果有的话)。
想真正“禁止所有嵌套”?得手动处理
ArrayHelper::toArray 没提供“强制扁平化”或“截断嵌套数组”的开关。若需严格一维结构,可在调用后用自定义逻辑过滤:
- 遍历结果,对每个值用
is_array()判断,把嵌套数组替换为 null / 空字符串 / JSON 字符串等; - 或用
array_walk_recursive()提取所有叶子值,再重新组织键名(注意会丢失原始结构)。
对比 $recursive=true 的实际差异
设 $post->author 是一个 User 对象:
-
$recursive = true→'author' => ['id' => 123, 'name' => 'Tom'](自动展开); -
$recursive = false→'author' => User Object→ 被转为['id' => 123, 'name' => 'Tom'],但若User里还有$this->profile对象,则不会继续展开。
也就是说:它控制的是“对象链的深度”,不是“数组维度的深度”。











