php中应使用http_build_query()处理数组参数,它自动按rfc1738编码为标准get格式(如foo[0]=a&bar[name]=john),确保$_get正确解析;手动拼接或json_encode后urlencode会导致无法识别和解码失败。

PHP中直接用http_build_query()处理数组参数
PHP原生就支持将数组转成GET参数格式,核心函数是http_build_query()。它会自动把嵌套数组展开为foo[0]=a&foo[1]=b&bar[name]=john这类标准格式,浏览器和后端都能正确解析。
常见错误是手动拼接或用json_encode()再urlencode——这样生成的参数既不能被$_GET自动识别,也容易因特殊字符引发解码失败。
- 一维数组:
http_build_query(['id' => 123, 'tags' => ['php', 'web']])→id=123&tags[0]=php&tags[1]=web - 关联子数组:
http_build_query(['user' => ['name' => 'tom', 'age' => 25]])→user[name]=tom&user[age]=25 - 注意:该函数默认使用
PHP_QUERY_RFC1738编码规则,若需RFC3986(如对接某些API),加第三个参数PHP_QUERY_RFC3986
接收端必须用$_GET原样读取,别用$_REQUEST或file_get_contents('php://input')
GET参数本质是URL查询字符串,PHP在请求开始时已将其解析并填入$_GET超全局变量。数组结构会自动还原——只要发送端用http_build_query(),接收端直接访问$_GET['tags'][0]或$_GET['user']['name']即可。
容易踩的坑:
立即学习“PHP免费学习笔记(深入)”;
-
$_REQUEST可能混入POST或cookie数据,导致键名冲突或覆盖 -
php://input对GET请求始终为空,强行读取会返回空字符串 - 没开启
magic_quotes_gpc(PHP
复杂嵌套或需要自定义键名时,先扁平化再调用http_build_query()
如果数组结构太深(比如三维以上)、或想把data.items.0.name转成data_items_0_name这种扁平键名,http_build_query()无法直接满足。这时要自己写递归扁平函数,再传给它。
示例思路:
function flatten_array($arr, $prefix = '') { $result = []; foreach ($arr as $key => $value) { $new_key = $prefix === '' ? $key : $prefix . '_' . $key; if (is_array($value)) { $result += flatten_array($value, $new_key); } else { $result[$new_key] = $value; } } return $result; } // 然后:http_build_query(flatten_array($my_data))
注意:扁平化会丢失原始数组层级语义,仅适用于双方约定好格式的内部系统,不推荐用于通用API。
URL长度限制和敏感数据风险必须人工判断
http_build_query()只管编码,不管长度。实际GET请求受浏览器和服务器双重限制(通常2KB–8KB),数组过大时会截断或报414错误。调试时可用strlen()提前检查:
$query = http_build_query($params); if (strlen($query) > 6000) { die('GET参数超长'); }- 含密码、Token、用户标识等敏感字段绝不能走GET,哪怕已urlencode——URL会被代理、CDN、日志明文记录
- 若必须传复杂数据,改用POST + JSON body,或前端用
localStorage暂存ID,后端查库还原
真正麻烦的从来不是怎么转,而是想清楚这个数组到底该不该出现在URL里。