Есть ли в PHP способ зафиксировать вывод файла PHP в переменную без использования буферизации вывода?

В PHP я хочу прочитать файл в переменную и одновременно обработать PHP в файле без использования буферизации вывода. Это возможно?

По сути, я хочу сделать это без использования ob_start():

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

Возможно ли это в PHP?

Обновление: я хочу сделать более сложные вещи в обратном вызове вывода (где буферизация вывода не разрешена).


person Joe Lencioni    schedule 21.10.2008    source источник
comment
Почему бы просто не использовать буферизацию вывода?   -  person Greg    schedule 21.10.2008


Ответы (8)


Малоизвестная особенность PHP заключается в том, что он может обрабатывать включенный/обязательный файл как вызов функции с возвращаемым значением.

Например:

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


// index.php
$output = include './myinclude.php';
echo $output;
// Will echo foobar
person Wes Mason    schedule 23.10.2008
comment
Также уместно то, что переменные, установленные в index.php до включения, доступны и оцениваются при включении myinclude.php. - person Duncanmoo; 18.08.2013

Из того, что я могу сказать в документации по PHP, нет. Почему вы хотите избежать буферизации вывода?

Единственный способ обойти это - хакерские методы, включающие либо вызов php-клиента командной строки, либо выполнение запроса curl на основе того, что доступно и каковы конкретные требования.

person KernelM    schedule 21.10.2008

Прочитав предложения всех, прочитав кучу документации и поиграв с некоторыми вещами, я пришел к следующему:

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

Это так близко, как я мог получить, но, к сожалению, это не работает. Ключом к этому является включение закрывающего бита PHP (?>) перед содержимым файла. Это выведет eval() из режима оценки PHP и будет обрабатывать содержимое файла, начиная с кода, отличного от PHP. Затем, если в файле есть блоки кода PHP, они будут оцениваться как PHP. Облом в том, что он не сохраняет содержимое eval'd в переменной, а просто выводит его на страницу.

Спасибо за помощь всем!

person Joe Lencioni    schedule 21.10.2008
comment
И что на самом деле возвращает вывод файла eval'd? Из того, что я прочитал на us.php.net/manual/en/function.eval .php вам все равно нужно будет использовать буферизацию вывода. - person KernelM; 22.10.2008
comment
@JoeLencioni НЕТ, если вы используете return "blabla" в file.php, используйте echo eval(...) ............... пожалуйста, отредактируйте свой ответ . - person T.Todua; 03.05.2015

Джоэри Себрехтс прав. Эквивалентный и немного более простой метод доступен, если PHP-скрипт доступен по HTTP:

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

Следует отметить, что использование буферизации вывода было бы проще для ресурсов.

person Community    schedule 21.10.2008
comment
Многие серверы отключают allow_furl_open, и это не вариант. - person dcousineau; 22.10.2008

Сделайте запрос curl на php-страницу, по сути, притворяясь браузером.

person Joeri Sebrechts    schedule 21.10.2008
comment
Это не работает, если файл не является общедоступным. См. ответ Кролика... (также file_get_contents проще, чем cURL). - person Niels Abildgaard; 27.05.2013

Что вы можете сделать, если файл локальный, так это загрузить скрипт в переменную в виде строки, а затем запустить eval для этой строки. После этого вы сможете заняться всеми остальными делами. В противном случае вам придется использовать буферизацию вывода.

person Robert K    schedule 21.10.2008
comment
К сожалению, это не сработает, потому что eval() оценивает PHP-код, тогда как доступ к странице будет оценивать PHP-код только в том случае, если он находится в блоке кода PHP (например, между ‹?php и ?›) - person Joe Lencioni; 21.10.2008

$fileData = file_get_contents('fileOnDisk.php');
$results = eval($fileData);

Но проверьте документацию по eval, потому что на самом деле вам нужно, чтобы файл, который вы вызываете, возвращал свои результаты, а не просто повторял их:

http://us2.php.net/eval

person Zak    schedule 21.10.2008

Предупреждение о взломе! Вы можете выполнить оценку PHP самостоятельно, применив немного хакерства, используя preg_replace_callback для поиска и замены блоков PHP.

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

Вам нужно будет изменить файл PHP, который вы включаете, чтобы использовать функцию returnOrEcho, чтобы ее можно было перегрузить для этого случая и обычного случая. В этом случае вы хотите return, чтобы eval забрал его так, как вы хотите, но нормальный случай - echo без возврата.

Итак, для этого случая вы должны определить:

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

и для нормального случая вы бы определили:

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

В вашем включенном файле PHP (или файле просмотра) у вас будет что-то вроде этого:

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

Мне не удалось заставить работать встроенный обратный вызов preg_replace_callback, поэтому я использовал отдельную функцию, но есть пример того, как это сделать: preg_replace_callback() — обратный вызов внутри текущего экземпляра объекта.

person David Newcomb    schedule 30.10.2014
comment
как я вижу, вы упустили одну серьезную вещь, и вам нужно это изменить. если в этом файле есть несколько ECHO, то это нормально, но эта функция заменяет ECHO на RETURN, поэтому на первом RETURN сценарий будет завершен, а не продолжен (как это могло бы быть с помощью ECHO) - person T.Todua; 12.05.2015