2011-10-20 60 views
0

我已經寫了一個MVC框架,並且我正在使用ob_start('error_handler')來捕捉致命錯誤。這很好用!PHP ob_start調用兩次,現在不會正確刷新

在boot.php

// Start the error-logging 
ob_start('error_logging'); 

// Run the request 
Request::run(URL::getInstance()->init()->formatURL()); 

// Flush and disable output-buffering 
ob_end_flush(); 

error_logging功能:

function error_logging($output) 
{ 

    // Get the last error 
    $trace = error_get_last(); 
    // Initialize our final array of fields explaining the error 
    $final = array(); 

    // Check if the error does not exist, return the original output unedited 
    if(!isset($trace)) return $output; 

    // Loop through or error and build our array 
    foreach($trace as $info => $value) $final[$info] = $value; 

    // Initialize our Error-class 
    $error = Error::factory(); 
    // Handle the error with the fields and build our error-message 
    $newOutput = $error->handle($final['type'] , $final['message'], $final['file'], $final['line']); 

    // Check if the new output is null, if yes set output to the original output, otherwise set it to the new output 
    $output = ($newOutput === null) ? $output : $newOutput; 

    // Return the output 
    return $output; 

} 

再次,這工作得很好,很正常,處理所有的錯誤!我不使用任何刷新或任何內部的錯誤類。

現在,我有一個控制器使用ob_start,因爲它是一個相當長的運行時間的某種方法,我想反饋給用戶正在發生的事情以及腳本的作用。我正在使用ob_flush()。

但是,在執行這個ob_start('error_logging'); ob_flush似乎不起作用。他們一直等到整個劇本完成(大約需要8分鐘)。

爲什麼?

我怎麼沖洗的一個例子是這樣的: 在控制器法:

$this->login->execute(); 

在登錄::執行:

public function execute($site = 'mobile') 
{ 

    ob_start(); 

    $this->debug->log('--------------------------------------------<br />'); 
    $this->debug->log('Logging into site: ' . ucfirst($site) . '<br />'); 

    // Initiate cookies 
    if($site == 'full') 
     $this->_initCookies(); 

    // Set up the URL 
    $url = Config::get($site) . Config::get('url_login'); 
    curl_setopt($this->curl->get(), CURLOPT_URL, $url); 

    // CURL-values 
    curl_setopt($this->curl->get(), CURLOPT_FOLLOWLOCATION, 1 ); 
    curl_setopt($this->curl->get(), CURLOPT_RETURNTRANSFER, 1 ); 
    curl_setopt($this->curl->get(), CURLOPT_POST,   1 ); 
    curl_setopt($this->curl->get(), CURLOPT_POSTFIELDS,  Config::get('postfields')); 
    curl_setopt($this->curl->get(), CURLOPT_COOKIEFILE,  'resources/tmp/cookies.txt'); 
    curl_setopt($this->curl->get(), CURLOPT_CONNECTTIMEOUT, 10); 
    curl_setopt($this->curl->get(), CURLOPT_TIMEOUT,  40); 
    curl_setopt($this->curl->get(), CURLOPT_USERAGENT,  'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.1) Gecko/20100101 Firefox/6.0.1'); 

    // Get the page returned after we've logged in 
    $this->login_html = str_get_html(curl_exec($this->curl->get())); 

    // Validate the page returned to see if we successfully logged in 
    $this->_validateLogin($site); 

    $this->debug->log('--------------------------------------------<br />'); 

    ob_end_flush(); 

    // Return $this 
    return $this; 

} 

每個$這個 - >調試 - > log()調用刷新輸出,如下所示:

public function log($string) 
{ 

    if($this->active() || $this->logging()) 
    { 

     echo str_repeat("<!-- AGENT SMITH -->", 500); 
     echo $string; 

     ob_flush(); 
     flush(); 

    } 

} 

任何想法爲什麼它不正確沖洗? 告訴我,如果你需要查看更多的代碼,我會提供它!

感謝

:::::::: SOLUTION ::::::::::

我不得不保存第一緩衝(在error_logging),結束它,開始新的一,做我的事情,然後結束那個,再次啓動第一個緩衝區並回顯保存的輸出。

難道一類是:

class Tanaxia_Buffer 
{ 

    public static $instance = null; 

    private $main = null; 
    private $previousOutput = ""; 

    public static function getInstance() 
    { 

     if(Buffer::$instance === null) 
      Buffer::$instance = new Buffer(); 

     return Buffer::$instance; 

    } 

    public function set_main($ob) 
    { 

     $this->main = $ob; 

    } 

    public function start($main = null) 
    { 

     if($main !== null) 
      $this->set_main($main); 

     ob_start($this->main); 

    } 

    public function end($type = 'clean') 
    { 

     switch($type) 
     { 

      case 'flush': ob_end_flush(); break; 
      case 'clean': ob_end_clean(); break; 

     } 

    } 

    public function start_separate() 
    { 

     $this->previousOutput = ob_get_contents(); 
     ob_end_clean(); 

     ob_start(); 

    } 

    public function end_separate($type = 'flush') 
    { 

     switch($type) 
     { 

      case 'flush': ob_end_flush(); break; 
      case 'clean': ob_end_clean(); break; 

     } 

     ob_start($this->main); 
     echo $this->previousOutput; 

     empty($this->previousOutput); 

    } 

} 

用法:

boot.php

// Start the error-logging 
Buffer::getInstance()->start('error_logging'); 

// Run the request 
Request::run(URL::getInstance()->init()->formatURL()); 

// Flush and disable output-buffering 
Buffer::getInstance()->end('flush'); 

登錄::執行():

public function execute($site = 'mobile') 
{ 

    Buffer::getInstance()->start_separate(); 

    // Everything in between 

    Buffer::getInstance()->end_separate(); 

    // Return $this 
    return $this; 

} 

完美的作品!不支持多個嵌套的ob_start,因爲它只保存1個先前的輸出。可以修復,但現在不需要!

回答

4

我猜測它與嵌套的ob_start()調用有關。我假設你想保持它們嵌套,但是如果在​​函數中調用ob_end_flush()ob_end_clean(),然後啓動下一個輸出緩衝區,它是否按照你想要的方式刷新?類似這樣的:

public function execute($site = 'mobile') 
{ 
    // save existing contents of output buffer 
    $previousOutput = ob_get_contents(); 
    // wipe the output buffer itself 
    ob_end_clean(); 
    // start a new output buffer 
    ob_start(); 

    /* SNIP all the code that wouldn't change */ 

    // flush the function's output buffer 
    ob_end_flush(); 
    // restart the old output buffer 
    ob_start("error_logging"); 
    // take whatever was in the old buffer and make sure it shows up in the new one 
    echo $previousOutput; 

    return $this; 
} 
+0

哈哈!它工作得非常好:D將用解決方案更新主文章!非常感謝! – Tanax