PHP缓冲区数据输出到界面–仿Discuz安装向导

  •   
  • 4192
  • PHP
  • 0
  • super_dodo
  • 2013/09/12

当在项目中尤其是执行时间比较久的页面(尤其是与服务器之间的交互,或者是安装\新建一些文件数据表的情况下),使用者如果看到页面没有回馈信息,会造成使用者因执行时间过长无反馈而误解为程序页面卡住,导致关闭页面,以至于程序页面不能正常进行,同时会造成不必要的失误或导致错误.Q20130912091628

为了规避这种错误,我们向Discuz学习,仿照他执行安装数据库时候的页面,不断的生成数据表,输出到浏览器,供使用者了解.下面直接上代码(dodo使用了2种方法)

<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title>PHP缓冲区数据输出到界面--仿Discuz安装向导</title>
	<style type="text/css">
		body{color:#666; font:12px/1.5 'Microsoft Yahei';}
		.container{overflow:hidden; margin:0 auto; width:700px; border:1px solid #B5CFD9;}
		.main{padding:20px 20px 0; background:#F7FBFE;}
		.main h3{color:#F92672;}
		#notice{overflow:hidden;margin:20px;padding:5px;height:300px; border:1px solid #B5CFD9;}
	</style>
	<script type="text/javascript">
		//javascript方法,可改用jQuery的方法
		function showmessage(message) {
			document.getElementById('notice').innerHTML += message + '<br/>';
			document.getElementById('notice').scrollTop = 100000000;
		}
	</script>
</head>
<body>
	<div class="container">
		<div class="main">
			<div id="notice"></div>
			<?php
			/****方法1:借助Javascript的方法***/
			//模拟初始化数据表
			for($i=1;$i<=30;$i++){
				showjsmessage("建立数据表 {$i} ... 成功");
				sleep(rand(0,1));
			}

			//检测完成后显示的信息
			function showjsmessage($message){
				echo '<script type="text/javascript">showmessage(\''.addslashes($message).' \');</script>'."\r\n";
				ob_flush(); 	//两者的顺序保持此顺序
				flush();
			}

			/****方法2:直接PHP实现,不需要借助javascript***/
			for($i=0;$i<10;$i++){
				echo '<h3>This is Step '.$i.'...........</h3>';
				ob_flush();
				flush();
				sleep(rand(0, 1));
			}
			?>
		</div>
	</div>
</body>
</html>

补充解释一下缓冲区的两个函数:ob_flush/flush在手册中的描述, 都是刷新输出缓冲区, 并且还需要配套使用, 所以会导致很多人迷惑….

其实, 他们俩的操作对象不同, 有些情况下, flush根本不做什么事情..ob_*系列函数, 是操作PHP本身的输出缓冲区.所以, ob_flush是刷新PHP自身的缓冲区.而flush, 严格来讲, 这个只有在PHP做为apache的Module(handler或者filter)安装的时候, 才有实际作用. 它是刷新WebServer(可以认为特指apache)的缓冲区.一些版本的IE只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。

所以, 正确使用俩者的顺序是. 先ob_flush, 然后flush,当然, 在其他sapi下, 不调用flush也可以, 只不过为了保证你代码的可移植性, 建议配套使用。