10

I have my page contents saved in a database and would like to execute any php code in the string. So if my string was:

<h1>Welcome</h1><?php echo $motto?><br/>

I only want to execute echo $motto. Using eval() will try to execute <h1>Welcome</h1>.

Any way to do this?

latonz
  • 1,601
  • 10
  • 21
bmandesign
  • 347
  • 1
  • 3
  • 11
  • 1
    yes keep presentation and logic seperate. Having to do this would indicate that you might want to rethink your design choices. – dm03514 Jun 02 '12 at 22:11
  • For the way you're structuring your site, I can tell you right now this will cause problems down the line. Here's my suggestion: use Smarty, or similar, to separate templates and code. –  Jun 02 '12 at 22:13
  • This seems like you have made a really **really** bad design decision. – PeeHaa Jun 02 '12 at 22:13
  • The only thing I am trying to load is the main body. The headers, footers and sidebars are all saved in files. – bmandesign Jun 02 '12 at 22:17

3 Answers3

20

Needless to say you should find another solution ASAP. In the meantime you can eval the code like this:

$str = '<h1>Welcome</h1><?php echo $motto?><br/>'; // Your DB content

eval("?> $str <?php ");

Demo: http://codepad.org/ao2PPHN7

I can't stress that enough: eval is dangerous, and application code shouldn't be in the database. Try a template parser like Smarty, Dwoo, or my favorite: Twig.

Wesley Murch
  • 101,186
  • 37
  • 194
  • 228
2

You really shouldn't do this, but if you absolutely have to, you can do it by using this class:

class PhpStringParser
{
    protected $variables;

    public function __construct($variables = array())
    {
        $this->variables = $variables;
    }

    protected function eval_block($matches)
    {
        if( is_array($this->variables) && count($this->variables) )
        {
            foreach($this->variables as $var_name => $var_value)
            {
                $$var_name = $var_value;
            }
        }

        $eval_end = '';

        if( $matches[1] == '<?=' || $matches[1] == '<?php=' )
        {
            if( $matches[2][count($matches[2]-1)] !== ';' )
            {
                $eval_end = ';';
            }
        }

        $return_block = '';

        eval('$return_block = ' . $matches[2] . $eval_end);

        return $return_block;
    }

    public function parse($string)
    {
        return preg_replace_callback('/(\<\?=|\<\?php=|\<\?php)(.*?)\?\>/', array(&$this, 'eval_block'), $string);
    }
}

Call it like this:

$p = new PhpStringParser();
echo $p->parse($string);

Source: http://www.php.net/manual/en/function.eval.php#108091

Jeroen
  • 13,056
  • 4
  • 42
  • 63
  • The reason the main body is saved in a database is so the client can edit it in a custom windows program I have made. I am trying to set it up differently but in the mean time the site needs to go online like this. – bmandesign Jun 02 '12 at 22:19
  • 2
    What benefit does the above have compared to `ob_start();eval("?>$str");$result=ob_get_clean();`? – goat Jun 02 '12 at 22:37
2

To echo string with a variable inside use:

echo "<h1>Welcome</h1>$motto<br/>"

Or even:

echo sprintf('<h1>Welcome</h1>%s<br/>', $motto)

Here is a demo http://codepad.org/f6aALD6w

PassTeT
  • 517
  • 5
  • 8