【问题标题】:PHP Output buffering prints at end of scriptPHP 输出缓冲打印在脚本末尾
【发布时间】:2019-07-07 12:13:03
【问题描述】:

我正试图将我的大脑包裹在缓冲中,但我无法在此站点上找到任何适合我的示例。也不是来自 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 文件并手动打开输出缓冲无济于事。谁能告诉我我做错了什么?

【问题讨论】:

  • 你想让它做什么?
  • 我希望它在脚本运行时打印每个 echo 语句,而不是最后的所有内容
  • 它不会那样工作......我能想到的最接近的近似值就是使用 php 作为由 javascript 初始化的 Event Stream 的源
  • 我猜flush()应该在ob_flush()之后

标签: php buffer


【解决方案1】:

为了支持我所做的评论 - “我能想到的最接近的近似值......”我拼凑了一个演示,说明了我使用 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 有一个由输出缓冲区回调修改的标题(香蕉...) - 这种修改不会不可能在没有输出缓冲的情况下在实时文档上使用 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>

【讨论】:

    猜你喜欢
    • 2010-11-24
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    • 2011-01-19
    相关资源
    最近更新 更多