PHP大JSON字符串输出异常:需提前echo才输出的技术问询
问题分析与解决方案
我之前碰到过一模一样的情况,这绝对不是代码逻辑的Bug,而是PHP输出缓冲机制在背后搞的鬼!
问题根源
当你直接访问接口时,PHP默认的输出缓冲可能处于关闭状态,或者缓冲区的阈值没达到。你的脚本需要遍历大量数据(从ff_candidates表取所有记录),运行时间长达2-3分钟,生成的JSON内容一直被存在内存缓冲区里,直到脚本超时也没被发送到浏览器——所以你看不到任何输出。
但当你在循环前加了echo语句时,这个操作会触发PHP的缓冲刷新机制,强制把缓冲区的内容发送出去,后续生成的JSON也能跟着正常输出到客户端。
可行的解决方案
这里给你三个靠谱的解决办法,按推荐度排序:
1. 在响应方法中强制处理输出缓冲
修改你的_response方法,手动控制缓冲的清空、输出和刷新,确保JSON内容能被即时发送:
private function _response( $response, $status = 200 ) { $verbose = $this->_requestStatus( $status ); // 清空之前可能残留的缓冲内容,避免干扰 ob_clean(); // 开启输出缓冲 ob_start(); header("Content-Type: application/json"); header( 'HTTP/1.1 '.$status.' '.$verbose ); if( is_string($response) ) { $data = new stdClass(); $data->message = $response; $data->status = $status; $data->title = $verbose; } else { $data = $response; } $json = json_encode( $data ); echo $json; // 强制刷新输出缓冲,把内容推送到客户端 ob_flush(); flush(); exit(); }
2. 调整PHP配置的输出缓冲参数
如果有权限修改php.ini(比如自己的服务器),可以开启全局输出缓冲并设置合适的大小:
output_buffering = On ; 或者设置具体大小,比如4KB output_buffering = 4096
这样PHP会自动在缓冲区满的时候发送内容,不用手动处理。但如果是共享主机,这个方法可能行不通。
3. 在数据遍历循环中添加触发缓冲的操作
如果不想修改响应方法,可以在while循环里每处理一定数量的记录,就输出一个空白字符触发缓冲刷新:
while( $obj = $sql->fetchObject() ) { // 每处理100条记录就输出一个空格 static $count = 0; if ($count++ % 100 == 0) { echo ' '; ob_flush(); flush(); } $candidate = new Candidate( $this->_db, $obj->id ); $person = new stdClass(); $person->id = $candidate->get_id(); $person->name = utf8_encode($candidate->get_name()); $person->gender = $candidate->get_gender(); $candidates[] = $person; }
这个方法有点“hack”,但对于临时解决问题很有效,还能避免脚本超时。
额外提醒
另外可以检查下json_encode是否有可能失败(比如包含无法编码的字符),不过根据你描述的“加echo就能正常输出”,这个概率很低。如果担心的话,可以在$json = json_encode($data);后面加一句var_dump(json_last_error_msg());排查下。
内容的提问来源于stack exchange,提问作者poncho
相关产品推荐
相关产品推荐

