2013-02-14 38 views
0

請考慮下面的例子:如何防止發生錯誤時的ob_start()輸出?

的template.php:

<?php 

echo $vars['arr']; 

echo " -------- "; 

echo $vars['obj']; 

?> 

test.php的:

<?php 
$file = "template.php"; 
$vars = array('arr' => array(), 'obj' => new StdClass()); 

var_dump(json_encode($vars) ); 

function loadFile($file, $vars) 
{ 
    try 
    { 
     if (is_array($vars) && !empty($vars)) { 
      extract($vars); 
     } 

     ob_start(); 
     include $file; 
     return ob_get_clean(); 
    } 
    catch (Exception $e) 
    { 
     return false; 
    } 
} 

loadFile($file, $vars); 

?> 

這段代碼將輸出:

string(19) "{"arr":[],"obj":{}}" 
PHP Catchable fatal error: Object of class stdClass could not be converted to string in template.php 

這裏的問題是,在template.php中,我正在考慮$ vars是一個數組(),但是其中的1個元素是一個Object,正如您可以從json輸出中看到的那樣。

在模板中添加一個簡單的檢查來驗證這個ekement是否是一個數組可以解決這個問題,但是我需要這個到多個元素,元素,所以不是很好=)所以,我試圖找到一種方法來防止在綁定模板和$ vars時發生錯誤。

謝謝

+0

*「在解析失敗的情況下」*解析失敗?你無法捕捉解析失敗。 – 2013-02-14 13:55:04

+1

@WaleedKhan,在技術上你可以通過設置'register_shutdown_function'來處理輸出。 – Shoe 2013-02-14 13:56:21

+2

只能通過set_error_handler才能捕獲try-catch塊中的可捕獲致命錯誤。另請參閱http://stackoverflow.com/questions/2468487/how-can-i-catch-a-catchable-fatal-error-on-php-type-hinting – cmbuckley 2013-02-14 13:56:25

回答

2

簡單地把使用error_reporting關閉在解析:

$old_level = error_reporting(0); // no errors, preserve old error reporting level 
ob_start(); 
include $file; 
$content = ob_get_clean(); 
error_reporting($old_level); // reset error reporting level 
return $content; 

注:這隻會隱藏錯誤不是非常關鍵的。

爲了趕上捕致命錯誤,看到了這個問題:How can I catch a "catchable fatal error" on PHP type hinting?

你需要使用set_error_handler註冊錯誤處理程序:

function handleError($errno, $errstr, $errfile, $errline) { 
    // handle error 

    // return true, so the normal php handler doesn't get called 
    return true; 
} 
set_error_handler('handleError'); 

如果你想融入你處理程序乾淨地進入其他代碼也設置error_handlers,你可能會考慮恢復錯誤處理後使用restore_error_handler

0

你可能會先嚐試檢查值是否爲對象,然後使用PHP函數轉換爲數組。

請注意,您的此部分代碼:

if (is_array($vars) && !empty($vars)) { 
    extract($vars); 
} 

之後,如果我正確地讀你的代碼,你有一個變量可能名爲$瓦爾這可能是一個對象。所以,你可以這樣做:

if (is_object($vars)) { 
    $vars = get_object_vars($vars); 
} 

這應該將其轉換爲您所需要的。當然,您可能需要嘗試一下以確保它適合您的方案。謝謝!

0

你可以在你的類中使用__toString()方法來避免錯誤。你可以用你需要的任何值設置__toString()方法,也許返回一個數組。 http://www.php.net/manual/en/language.oop5.magic.php#object.tostring

另一種選擇,就是使用array_walk:

function checkObj(&$vars){ 
if (is_object($vars)) { 
    $vars = get_object_vars($vars); 
} 
} 
array_walk($vars, "checkObj"); 
0

由於使用ob_start(),你可以傳遞一個回調,將檢查是否存在錯誤。它甚至應該與致命錯誤一起工作。在你的回調裏面使用類似「error_get_last」的東西來檢查是否有錯誤,如果不爲空,就返回false,如下所示:

警告:我沒有測試過這段代碼,但是我使用了類似的東西。

<?php 
    $file = "template.php"; 
    $vars = array('arr' => array(), 'obj' => new StdClass()); 

    var_dump(json_encode($vars) ); 

    function loadFile($file, $vars) 
    { 
     try 
     { 
      if (is_array($vars) && !empty($vars)) { 
       extract($vars); 
      } 

      ob_start('errorHandler'); 
      include $file; 
      return ob_get_clean(); 
     } 
     catch (Exception $e) 
     { 
      return false; 
     } 
    } 

    function errorHandler($pBuffer) 
    { 
     $lastError = error_get_last(); 
     // Uh-oh, an error has occurred. 
     if ($lastError !== NULL) 
     { 
      return FALSE; 
     } 
     // No problems. 
     return $pBuffer; 
    } 

    loadFile($file, $vars); 

?> 
相關問題