9

In PHP, I want to read a file into a variable and process the PHP in the file at the same time without using output buffering. Is this possible?

Essentially I want to be able to accomplish this without using ob_start():

<?php
ob_start();
include 'myfile.php';
$xhtml = ob_get_clean();
?>

Is this possible in PHP?

Update: I want to do some more complex things within an output callback (where output buffering is not allowed).

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Joe Lencioni
  • 10,231
  • 18
  • 55
  • 66

8 Answers8

27

A little known feature of PHP is being able to treat an included/required file like a function call, with a return value.

For example:

// myinclude.php
$value = 'foo';
$otherValue = 'bar';
return $value . $otherValue;


// index.php
$output = include './myinclude.php';
echo $output;
// Will echo foobar
Wes Mason
  • 1,611
  • 12
  • 13
  • 1
    Also pertinent is that variables set in index.php before the include are available and evaluated when you include myinclude.php. – Duncanmoo Aug 18 '13 at 11:33
9

From what I can tell in the PHP documentation, no. Why do you want to avoid output buffering?

The only way to get around this would be hacky methods involving either invoking the command line php client or doing a curl request based on what's available and what the particular requirements are.

KernelM
  • 8,776
  • 2
  • 23
  • 16
4

After reading everybody's suggestions, reading a bunch of documentation, and playing around with some things, I came up with this:

<?php
$file = file_get_contents('/path/to/file.php');
$xhtml = eval("?>$file");
?>

It's as close as I could get but it unfortunately doesn't work. The key to this is to include the closing PHP bit (?>) before the contents of the file. This will take the eval() out of PHP-evaluation mode and will treat the contents of the file starting as non-PHP code. Then if there are PHP code blocks within the file, those will be evaluated as PHP. The bummer is that it doesn't save the eval'd content in the variable, it just outputs it to the page.

Thanks for the help everybody!

Joe Lencioni
  • 10,231
  • 18
  • 55
  • 66
  • 4
    And that actually returns the output of the eval'd file? From what I read at http://us.php.net/manual/en/function.eval.php you'd still need to use output buffering. – KernelM Oct 22 '08 at 13:10
  • @JoeLencioni **NO**, if you use `return "blabla"` in **file.php**, then use `echo eval(...)` ...............please, edit your answer. – T.Todua May 03 '15 at 13:04
1

Joeri Sebrechts is correct. An equivalent and slightly easier method is available if the PHP script is HTTP accessible:

$data = file_get_contents('http://google.com/');

It should be noted that using output buffering would be easier on resources.

0

Do a curl request to the php page, essentially pretending to be the browser.

Joeri Sebrechts
  • 11,012
  • 3
  • 35
  • 50
  • This doesn't work if the file is not publicly accessible. See the answer by Rabbit ... (also `file_get_contents` is easier than cURL). – Niels Abildgaard May 27 '13 at 06:59
0

What you could do, if the file is local, is load the script into a variable as a string, then run eval on the string. Then you can do all your other stuff afterwards. Otherwise, you have to use output buffering.

Robert K
  • 30,064
  • 12
  • 61
  • 79
  • Unfortunately, that won't work because eval() evaluates PHP code whereas accessing a page will only evaluate the PHP code if it is in a PHP code block (e.g. between ) – Joe Lencioni Oct 21 '08 at 19:00
0
$fileData = file_get_contents('fileOnDisk.php');
$results = eval($fileData);

But check the documentation on eval, because you actually have to have the file you are calling return its results rather than just echo them:

http://us2.php.net/eval

Sirko
  • 72,589
  • 19
  • 149
  • 183
Zak
  • 24,947
  • 11
  • 38
  • 68
-1

Hack Alert! You could do the evaluation of the PHP yourself with a bit of hackery using preg_replace_callback to search and replace the PHP blocks.

function evalCallback($matches)
{
    // [0] = <?php return returnOrEcho("hi1");?>
    // [1] = <?php
    // [2] = return returnOrEcho("hi1");
    // [3] = ?>
    return eval($matches[2]);
}

function evalPhp($file)
{
    // Load contents
    $contents = file_get_contents($file);
    // Add returns
    $content_with_returns = str_replace(
                               "returnOrEcho"
                              ,"return returnOrEcho"
                              ,$contents);
    // eval
    $modified_content = preg_replace_callback(
                              array("|(\<\?php)(.*)(\?\>)|"
                             ,"evalCallback"
                             ,$content_with_returns);
    return $modified_content;
}

You would have to modify the PHP file you are including to use a returnOrEcho function so that it can be overloaded for this case and the normal case. In this case you want to return so that it will be picked up by the eval in the way you want, but the normal case is to echo without a return.

So for this case you would define:

function returnOrEcho($str)
{
    return $str;
}

and for the normal case you would define:

function returnOrEcho($str)
{
    echo $str;
}

In your included PHP file (or view file) you would have something like this:

<?php returnOrEcho("hi1");?>
<?php returnOrEcho("hi3"."oo");?>
<?php returnOrEcho(6*7);?>

I couldn't get preg_replace_callback inline callback working so I used a separate function, but there is an example of how to do it: preg_replace_callback() - Calback inside current object instance.

Community
  • 1
  • 1
David Newcomb
  • 10,639
  • 3
  • 49
  • 62
  • as i see, you have missed one serious thing, and you need to modify that. if in that file, there is several **ECHO**, then it is ok, but that function replaces **ECHO**s with **RETURN**s, so on the first **RETURN** the script will be ended, instead of continuing it (like it was could have been using **ECHO**) – T.Todua May 12 '15 at 18:11