2013-02-14 29 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); 

?> 
相关问题