In PHP, is there a way to capture the output of a PHP file into a variable without using output buffering?
Asked Answered
P

8

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

Pantagruel answered 21/10, 2008 at 18:25 Comment(1)
Why not just use output buffering?Cuthbertson
H
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
Hominid answered 23/10, 2008 at 10:6 Comment(1)
Also pertinent is that variables set in index.php before the include are available and evaluated when you include myinclude.php.Briquet
F
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.

Footle answered 21/10, 2008 at 18:30 Comment(0)
P
5

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!

Pantagruel answered 21/10, 2008 at 23:0 Comment(2)
And that actually returns the output of the eval'd file? From what I read at us.php.net/manual/en/function.eval.php you'd still need to use output buffering.Footle
@JoeLencioni NO, if you use return "blabla" in file.php, then use echo eval(...) ...............please, edit your answer.Hispid
N
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.

Niobic answered 21/10, 2008 at 19:6 Comment(1)
Many servers disable allow_furl_open and this will not be an option.Psychodynamics
R
0

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

Ravi answered 21/10, 2008 at 18:31 Comment(1)
This doesn't work if the file is not publicly accessible. See the answer by Rabbit ... (also file_get_contents is easier than cURL).Mulish
C
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.

Constipation answered 21/10, 2008 at 18:50 Comment(1)
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 <?php and ?>)Pantagruel
O
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:

https://www.php.net/eval

Operant answered 21/10, 2008 at 22:52 Comment(0)
P
-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.

Punchdrunk answered 30/10, 2014 at 15:23 Comment(1)
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 ECHOs with RETURNs, so on the first RETURN the script will be ended, instead of continuing it (like it was could have been using ECHO)Hispid

© 2022 - 2024 — McMap. All rights reserved.