关于php:PHP中的输出缓冲控制

41次阅读

共计 4433 个字符,预计需要花费 12 分钟才能阅读完成。

在 PHP 中,咱们间接进行 echo、或者 print_r 的时候,输入的内容就会间接打印进去。然而,在某些状况下,咱们并不想间接打印,这个时候就能够应用输入缓冲管制来进行输入打印的管制。当然,这一套性能并不仅限出针对打印的内容,咱们还能够做其它一些操作,这个咱们放到最初再说。

革除输入

首先,咱们先来看看不让 echo 之类的内容打印输出。

ob_start();
echo 111, PHP_EOL;
echo "aaaa", PHP_EOL;
ob_end_clean();

置信有不少小伙伴应该见过 ob_start() 这个函数,它的作用就是开始一段输入缓冲管制。在 ob_start() 之后的代码中的输入语句都会进入输入缓冲区,这个时候,如果咱们调用了 ob_end_clean()、ob_clean() 或者 ob_get_clean(),则不会有任何输入了。它们三个的作用都是革除输入缓冲区的内容。具体的区别大家能够参考文章最初给出的函数阐明或者官网文档。

取得输入缓冲区的内容

ob_start();
echo 111, PHP_EOL;
echo "aaaa", PHP_EOL;
$v = ob_get_contents();
ob_end_clean();

echo $v;

下面说过,应用了 ob_end_clean() 就会革除输入缓冲区外面的内容,然而在这段代码中,咱们应用 ob_get_contents() 函数间接将缓冲区的内容赋值给了变量 \$v。这时候,$v 中就有了后面两段 echo 中的内容,也就是说,这个一套操作咱们就拿到了自身应该输入的内容,并将它保留在了变量中。这样做有什么用呢?咱们能够取得相似于 phpinfo()、var_dump() 这些间接输入函数的内容了,并且不会打印在客户端屏幕上。比方:

ob_start();
php_info();
$v = ob_get_contents();
ob_end_clean();

echo $v;

在 $v 中的内容就是 php_info() 的内容了。这就是输入缓冲管制的第二个能力。

刷新(输入)缓冲区内容

ob_start();
echo 111, PHP_EOL;
echo "aaaa", PHP_EOL;
flush();
ob_flush();

相似的,咱们在缓冲区中想要再次间接输入内容,应用 flush()、ob_flush()、ob_end_flush() 及 ob_get_flush() 就能够了,其实就是相当于让 ob_start() 之后的 echo 这类输入语句从新失效并失常输入。

另外,咱们还能够应用一个函数进行主动的刷新。

ob_implicit_flush();

ob_start();
echo 111, PHP_EOL;
echo "aaaa", PHP_EOL;

应用 ob_implicit_flush() 之后,咱们就不须要手动地调用 ob_flush() 之类的函数来刷新缓冲区内容了。

一些检测函数

ob_start();
ob_start();

echo 123, PHP_EOL;

echo ob_get_length(), PHP_EOL;
// 3

echo ob_get_level(), PHP_EOL;
// 2

print_r(ob_get_status(true));

// Array
// (//     [0] => Array
//         (//             [name] => default output handler
//             [type] => 0
//             [flags] => 112
//             [level] => 0
//             [chunk_size] => 0
//             [buffer_size] => 16384
//             [buffer_used] => 0
//         )

//     [1] => Array
//         (//             [name] => default output handler
//             [type] => 0
//             [flags] => 112
//             [level] => 1
//             [chunk_size] => 0
//             [buffer_size] => 16384
//             [buffer_used] => 17
//         )

// )

ob_get_flush();

ob_get_length() 会返回以后缓冲区外面内容的长度,这里咱们只打印了一个 123,在缓冲区中保留了 3 个字符,所以输入的正是 3。ob_get_level() 返回的是以后缓冲区的层级,请留神,咱们在下面调用了两次 ob_start(),也就是有两层的缓冲区,这个缓冲区是能够嵌套的。ob_get_status() 函数是缓冲区的状态信息,字段的阐明能够查看官网文档,这里不再赘述。

应用 ob_start() 的回调函数来进行输入缓冲区的内容替换

这是一个例子,然而能够推广到其余很性能,比方咱们能够用来进行全局的输入过滤、能够做 CSS 或 JS 文件的压缩优化等等。

ob_start(function($text){return (str_replace("apples", "oranges", $text));
});

echo "It's like comparing apples to oranges", PHP_EOL;
ob_get_flush();

// It's like comparing oranges to oranges

最初的输入后果就是将 apples 内容替换成了 oranges 内容。

增加 URL 重写器

output_add_rewrite_var('var', 'value');
// some links
echo '<a href="file.php">link</a>
<a href="http://example.com">link2</a>';

// <a href="file.php?var=value">link</a>
// <a href="http://example.com">link2</a>

// a form
echo '<form action="script.php"method="post">
<input type="text" name="var2" />
</form>';

// <form action="script.php" method="post">
// <input type="hidden" name="var" value="value" />
// <input type="text" name="var2" />
// </form>

下面的代码看出什么端倪了嘛?没错,应用 output_add_rewrite_var() 函数,咱们能够在 PHP 输入的时候为 HTML 的链接或者表单代码减少一个参数。有没有想到什么应用场景?POST 表单的 CSRF 攻打的防备。

这个函数会依据 php.ini 文件中的 url_rewriter.tags 配置项来进行增加,在默认状况下这个配置项只反对 from 表单,同时,它还能够反对 a 标签的 href、area 标签的 href、frame 标签的 src、input 标签的 src 等等。也就是说,会在这些标签绝对应的属性中主动增加字段。当然,它也有一个反函数 output_reset_rewrite_vars() 用于勾销之前减少的这个参数。

总结

对于输入缓冲管制这块还有很多好玩的货色,不过限于篇幅咱们先介绍到这里,未来踫到什么好的性能的利用咱们再独自解说。当初基于 Swoole 的利用越来越多,当咱们须要将 TP、Laravel 这类传统框架转换成反对 Swoole 的时候,往往就须要在入口文件应用输入缓冲管制来进行批改。因为传统框架根本都是间接进行 echo 之类的输入的,而在 Swoole 中,echo 这类的内容是间接打印在控制台的,这就须要咱们通过 ob_get_contents() 能力取得全副的输入再通过 response->end() 来进行理论的响应。另外,还有一些其余的场景也会用到输入缓冲管制:

  • 1. 在 PHP 中,像 header(), session_start(), setcookie() 等这样的发送头文件的函数前,不能有任何的输入,而利用输入缓冲管制函数能够在这些函数前进行输入而不报错
  • 2. 对输入的内容进行解决,例如生成动态缓存文件、进行 gzip 压缩输入,这算是较罕用的性能了
  • 3. 捕捉一些不可获取的函数输入,例如 phpinfo(), var_dump() 等等,这些函数都会将运算结果显示在浏览器中,而如果咱们想对这些后果进行解决,则用输入缓冲管制函数是个不错的办法。说的艰深点,就是这类函数都不会有返回值,而要获取这些函数的输入数据,就要用到输入缓冲管制函数
  • 4. 对一些数据进行实时的输入

最初,再给出输入缓冲管制相干的函数阐明,具体内容大家还是要多看官网文档的介绍。

  • flush — 刷新输入缓冲
  • ob_clean — 清空(擦掉)输入缓冲区
  • ob_end_clean — 清空(擦除)缓冲区并敞开输入缓冲
  • ob_end_flush — 冲刷出(送出)输入缓冲区内容并敞开缓冲
  • ob_flush — 冲刷出(送出)输入缓冲区中的内容
  • ob_get_clean — 失去以后缓冲区的内容并删除以后输入缓。
  • ob_get_contents — 返回输入缓冲区的内容
  • ob_get_flush — 刷出(送出)缓冲区内容,以字符串模式返回内容,并敞开输入缓冲区。
  • ob_get_length — 返回输入缓冲区内容的长度
  • ob_get_level — 返回输入缓冲机制的嵌套级别
  • ob_get_status — 失去所有输入缓冲区的状态
  • ob_gzhandler — 在 ob_start 中应用的用来压缩输入缓冲区中内容的回调函数。ob_start callback function to gzip output buffer
  • ob_implicit_flush — 关上 / 敞开相对刷送
  • ob_list_handlers — 列出所有应用中的输入处理程序。
  • ob_start — 关上输入管制缓冲
  • output_add_rewrite_var — 增加 URL 重写器的值(Add URL rewriter values)
  • output_reset_rewrite_vars — 重设 URL 重写器的值(Reset URL rewriter values)

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202005/source/%E8%BF%98%E6%90%9E%E4%B8%8D%E6%87%82PHP%E4%B8%AD%E7%9A%84%E8%BE%93%E5%87%BA%E7%BC%93%E5%86%B2%E6%8E%A7%E5%88%B6%EF%BC%9F.php

参考文档:

https://www.php.net/manual/zh/ref.outcontrol.php

https://www.php.net/manual/zh/session.configuration.php#ini.url-rewriter.tags

https://blog.csdn.net/xiaofan1988/article/details/43124359

===========

各自媒体平台均可搜寻【硬核项目经理】

正文完
 0