0

Please, consider the following example:

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);

?>

This code will output:

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

The problem here is, in the template.php I am considering $vars to be an array() however 1 of the elements is an Object as you can see from the json output.

Adding a simple checking in the template to verify if the ekement is an array or not would solve the problem, however I would need to this to multiple elements, elements, so, not very good =) so, I trying to find a way to prevent the error in the moment of binding the template and $vars.

Thank you

Tjoene
  • 320
  • 9
  • 18
Wils
  • 1,211
  • 17
  • 31
  • *“in case of parsing failures”* Parsing failures? You can't catch parsing failures. – Waleed Khan Feb 14 '13 at 13:55
  • 1
    @WaleedKhan, technically you can handle the output by setting `register_shutdown_function`. – Shoe Feb 14 '13 at 13:56
  • 2
    a Catchable fatal error can't be caught with a try/catch block, only by set_error_handler. See also http://stackoverflow.com/questions/2468487/how-can-i-catch-a-catchable-fatal-error-on-php-type-hinting – cmbuckley Feb 14 '13 at 13:56
  • You could possibly try to implement the ArrayAccess-Class into your object. That might circumvent your problem. – Louis Huppenbauer Feb 14 '13 at 13:56

4 Answers4

2

simply turn error_reporting off while parsing:

$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;

Note: This will only hide errors that aren't very critical.

In order to catch a Catchable Fatal Error, see this question: How can I catch a "catchable fatal error" on PHP type hinting?

You need to register an error handler using 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');

If you want to integrate you handler cleanly into other code which also sets error_handlers, you might consider restoring the error handler afterwards using restore_error_handler

Community
  • 1
  • 1
MarcDefiant
  • 6,649
  • 6
  • 29
  • 49
0

You might try checking to see if the values are an object first, and then using the PHP function to convert to an array.

Note, this section of your code:

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

After that, if I'm reading your code correctly, you have a variable possibly called $vars that could be an object. So, you could do this:

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

That should convert it to what you need. Of course, you may need to experiment a bit to make sure it fits your scenario. Thanks!

Aaron Saray
  • 1,178
  • 6
  • 19
0

You can use __toString() method in your class to avoid the error. You can set the __toString() method with any value you need, maybe return an array. http://www.php.net/manual/en/language.oop5.magic.php#object.tostring

Another option, is use array_walk :

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

Since you are using ob_start(), you can pass it a call-back that will check for any errors. It should even work with fatal errors. Inside your call-back use something like "error_get_last" to check for any error and just return false if it's not null, like so:

WARNING: I've not tested this code, but I use something similar myself.

<?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);

?>
b01
  • 4,076
  • 2
  • 30
  • 30