PHP输出缓冲打印在脚本末尾

时间:2019-02-13 15:37:19

标签: php buffer

我正在努力使自己的大脑围绕缓冲,但是我无法在此站点上找到任何适合我的示例。也不来自php.org。

这就是我正在使用的

    ini_set( "output_buffering", "on");
    
    header( 'Content-type: text/html; charset=utf-8' );
    $x = 1;
    
    ob_implicit_flush(true);
    
    while ($x < 10) {
        ob_end_clean();
        ob_start();
        echo $x." asdfasdfasdfasdf <br />";
        flush();
        ob_flush();
        sleep(1);
        ++$x;
    }

现在,脚本仅在脚本完成运行后立即将整个脚本打印出来。我已经修改了php.ini文件,并手动打开了输出缓冲,但无济于事。有人可以告诉我我在做什么错吗?

1 个答案:

答案 0 :(得分:0)

为了支持我的评论-“我能想到的最近似...”,我整理了一个演示,演示了使用EventStream的意思-可能比所需的更为复杂但是在询问问题时无法使用输出缓冲。

如果您要复制此文件并创建一个新的php文件,请保存并运行,您应该会看到输出发生的情况。

<?php
    if( !empty( $_GET['evtstream'] ) && $_GET['evtstream']==true ){
        ob_clean();
        set_time_limit( 0 );
        ob_end_clean();

        function sse( $evtname='evt', $data=null, $retry=1000 ){
            if( !is_null( $data ) ){
                echo "event:".$evtname."\r\n";
                echo "retry:".$retry."\r\n";
                echo "data:" . json_encode( $data, JSON_FORCE_OBJECT );
                echo "\r\n\r\n";
            }
        }

        header('Access-Control-Allow-Methods: GET');
        header('Content-Type: text/event-stream');

        $i=1;
        $evt=!empty( $_GET['evt'] ) ? $_GET['evt'] : 'tick';
        $count=!empty( $_GET['count'] ) ? $_GET['count'] : 10;

        while( true ){
            if( $i > $count ) break;

            /* send some data back for the SSE listener to process */
            $payload=array(
                'date'          =>  date( DATE_ATOM ),
                'count'         =>  $i,
                'event'         =>  $evt,
                'calculation'   =>  ( rand( 10,999 ) * rand( 300, 5999 ) ) / rand( 0.25, 25 )   #some random task performed by php...
            );
            call_user_func( 'sse', $evt, $payload );

            if( @ob_get_level() > 0 ) for( $i=0; $i < @ob_get_level(); $i++ ) @ob_flush();
            @flush();

            sleep( 1 );
            $i++;
        }

        /* 
            Now that the event loop has completed the 10 iterations we 
            need to prevent the eventsource from re-establishing itself
        */
        header('Content-Type: text/html');
        header('HTTP/1.1 404 Not Found', true, 404 );
        echo 'goodbye';
        ob_end_clean();
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Output Buffering: Server Sent Events</title>
    </head>
    <body>
        <h1>Output buffering experiments</h1>
        <div></div>
        <script>
            const EVENT_NAME='ticker';
            const MAX_ITERATIONS=10;

            let evtsource = new EventSource( location.href + '?evtstream=true&evt='+EVENT_NAME+'&ts=' + ( new Date().getTime() )+'&count='+MAX_ITERATIONS );

            let oDiv=document.querySelector( 'div' );

            const create=function(data){
                let node=document.createElement('div');
                    node.innerText=data;
                return node;
            };
            const callback=function(e){
                let json=JSON.parse( e.data );
                let content=Object.keys( json ).map( k => {
                    return [k,json[k]].join('=')
                }).join('&')
                oDiv.append( create( content ) );               
            };
            const errorhandler=function(e){
                evtsource.close();
                oDiv.append( create( 'Terminated' ) );
            };

            evtsource.addEventListener( EVENT_NAME, callback, false );
            evtsource.addEventListener( 'error', errorhandler,false );
        </script>
    </body>
</html>

否则,您可以看一下output buffering的另一种用法的示例-您将看到html具有由输出缓冲区回调修改的标头(banana ...)-这种修改如果没有输出缓冲,就不能在实时文档上使用DOMDocument。

<?php
    error_reporting( E_ALL );

    function callback( $buffer ){
        if( !empty( $buffer ) ){
            $dom=new DOMDocument;
            $dom->loadHTML( $buffer );
            $h1 = $dom->getElementsByTagName('h1')->item(0);
            $h1->nodeValue='A giraffe is a large mammal from Africa';
            return $dom->saveHTML();
        }
    }
    ob_start( 'callback' );
    ob_implicit_flush(1);
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Output Buffering Example</title>
    </head>
    <body>
        <h1>Bananas are curvy yellow fruit</h1>
    </body>
</html>