
本文介绍如何在从数据库循环构建多维关联数组时,精准剔除未初始化的子数组(如空 `id_tipo_profissional`),避免生成冗余的 `""` 键或 `null` 值,确保 json 输出结构干净、语义清晰。
在 PHP 数据处理中,尤其是从数据库按类型分组构建嵌套结构时,常见的陷阱是:未初始化的变量被强制写入数组,导致 array_filter() 无法生效——因为 array_filter() 默认仅过滤「值为 falsy」的元素,而空字符串 ""、null 或未定义变量在关联键位置(key)根本不会被该函数处理;它只作用于数组的 值(value),且对键名(key)完全无感。
你当前代码的问题根源在于:
$resultado = array_filter([
"tipo" => [
$id_tipo_profissional_1 => [ /* ... */ ], // 若 $id_tipo_profissional_1 为 null/'',此处键变成 ""
$id_tipo_profissional_2 => [ /* ... */ ],
],
]);当 $id_tipo_profissional_1 或 $id_tipo_profissional_2 未被赋值(例如某类数据在数据库中完全不存在),其值为 null 或空字符串 "",PHP 会将 ["" => [...]] 写入数组,形成非法键(空字符串键),而 array_filter() 对这个键及其整个子数组不做任何清理,因为它不是“值为 falsy 的元素”,而是“一个真实存在的键值对”。
✅ 正确解法:构建前校验,按需追加,而非“全量构造 + 事后过滤”。
立即学习“PHP免费学习笔记(深入)”;
推荐重构方式如下:
// 初始化主容器
$tipo = [];
// 仅当类型 1 数据存在时,才构建并注入
if (!empty($id_tipo_profissional_1)) {
$tipo[$id_tipo_profissional_1] = [
'id_tipo_profissional' => $id_tipo_profissional_1,
'nome_tipo_profissional' => $tipo_profissional_1,
'profissionais' => !empty($profissionais_1) ? $profissionais_1 : []
];
}
// 同理处理类型 2
if (!empty($id_tipo_profissional_2)) {
$tipo[$id_tipo_profissional_2] = [
'id_tipo_profissional' => $id_tipo_profissional_2,
'nome_tipo_profissional' => $tipo_profissional_2,
'profissionais' => !empty($profissionais_2) ? $profissionais_2 : []
];
}
// 组装最终结果(注意:这里不再用 array_filter 包裹)
$resultado = [
'tipo' => $tipo
];
return json_encode($resultado, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);? 关键优化点说明:
- 使用 !empty() 而非 if ($var):更严格地排除 null、false、0、""、[] 等所有空值,防止 0 类型 ID(虽本例为字符串 '1'/'2',但增强健壮性);
- 显式初始化 $profissionais_1 和 $profissionais_2 为空数组(建议在循环前声明:$profissionais_1 = []; $profissionais_2 = [];),避免未定义警告;
- profissionais 子数组即使为空也显式设为 [](而非 null),保证 JSON 结构一致性,前端解析更安全;
- 移除冗余的 array_filter() 包裹——它在此场景下无效且误导。
? 进阶建议(可选):
若专业类型数量可能扩展(如未来增加 type 3、4…),建议改用映射数组统一管理,提升可维护性:
$types = [];
while ($row = $stm->fetch()) {
$typeId = $row['id_tipo_profissional'];
if (!isset($types[$typeId])) {
$types[$typeId] = [
'id_tipo_profissional' => $typeId,
'nome_tipo_profissional' => $row['tipo_profissional'],
'profissionais' => []
];
}
$name = $typeId === '1'
? ucwords($row['nome'] . ' ' . $row['sobrenome'])
: ucwords($row['nome_do_escritorio']);
$types[$typeId]['profissionais'][] = [
'id_profissional' => $row['id'],
'nome' => $name
];
}
$resultado = ['tipo' => $types];这样彻底消除硬编码分支,逻辑更清晰,也天然规避空类型问题。
总结:过滤应在构建时发生,而非构建后补救。 坚持“存在即添加,缺失即跳过”的原则,配合合理初始化与严格判空,即可稳定输出符合预期的紧凑 JSON 结构。











