Код ниже почти работает, но это не то, что я действительно имел в виду:
ob_start();
echo 'xxx';
$contents = ob_get_contents();
ob_end_clean();
file_put_contents($file,$contents);
Есть ли более естественный способ?
Код ниже почти работает, но это не то, что я действительно имел в виду:
ob_start();
echo 'xxx';
$contents = ob_get_contents();
ob_end_clean();
file_put_contents($file,$contents);
Есть ли более естественный способ?
Можно писать STDOUT непосредственно в файл на PHP, что намного проще и проще, чем использование буферизации вывода.
Сделайте это в самом начале вашего script:
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$STDIN = fopen('/dev/null', 'r');
$STDOUT = fopen('application.log', 'wb');
$STDERR = fopen('error.log', 'wb');
Почему в самом начале вы можете спросить? Никаких дескрипторов файлов не нужно открывать, потому что когда вы закрываете дескрипторы стандартного ввода, вывода и файла ошибки, первые три новых дескриптора станут НОВЫМИ стандартными дескрипторами ввода, вывода и файла ошибок.
В моем примере здесь я перенаправил стандартный ввод в /dev/null и дескрипторы файла вывода и файла ошибок в файлы журнала. Это обычная практика при создании демона script в PHP.
Чтобы записать файл application.log, это будет достаточно:
echo "Hello world\n";
Чтобы записать в error.log, нужно было бы:
fwrite($STDERR, "Something went wrong\n");
Обратите внимание, что при изменении ввода, вывода и дескрипторов ошибок встроенные PHP-константы STDIN, STDOUT и STDERR будут недоступны. PHP не будет обновлять эти константы для новых дескрипторов, и им не разрешено переопределять эти константы (они называются константами по какой-то причине).
здесь способ отклонения OUTPUT, который кажется исходной проблемой
$ob_file = fopen('test.txt','w');
function ob_file_callback($buffer)
{
global $ob_file;
fwrite($ob_file,$buffer);
}
ob_start('ob_file_callback');
подробнее здесь:
http://my.opera.com/zomg/blog/2007/10/03/how-to-easily-redirect-php-output-to-a-file
Нет, буферизация вывода так же хороша, как и получается. Хотя это немного лучше, чем просто сделать
ob_start();
echo 'xxx';
$contents = ob_get_flush();
file_put_contents($file,$contents);
Вот уродливое решение, которое было полезно для проблемы, которую я имел (нужно отлаживать).
if(file_get_contents("out.txt") != "in progress")
{
file_put_contents("out.txt","in progress");
$content = file_get_contents('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
file_put_contents("out.txt",$content);
}
Основной недостаток заключается в том, что вам лучше не использовать переменные $_POST. Но вы не должны ставить его в самом начале.
Вы можете установить расширение Eio
pecl install eio
и дублировать файловый дескриптор
$temp=fopen('/tmp/my_stdout','a');
$my_data='my something';
$foo=eio_dup2($temp,STDOUT,EIO_PRI_MAX,function($data,$esult,$request){
var_dump($data,$esult,$request);
var_dump(eio_get_last_error($request));
},$my_data);
eio_event_loop();
echo "something to stdout\n";
fclose($temp);
это создает новый файловый дескриптор и перезаписывает целевой поток STDOUT
это также можно сделать с помощью STDERR
и константы STD [OUT | ERR] по-прежнему доступны
Использование eio pecl module eio очень просто, также вы можете записывать внутренние ошибки PHP, var_dump, echo и т.д. В этом коде вы можете найти несколько примеров различных ситуаций.
$fdout = fopen('/tmp/stdout.log', 'wb');
$fderr = fopen('/tmp/stderr.log', 'wb');
eio_dup2($fdout, STDOUT);
eio_dup2($fderr, STDERR);
eio_event_loop();
fclose($fdout);
fclose($fderr);
// output examples
echo "message to stdout\n";
$v2dump = array(10, "graphinux");
var_dump($v2dump);
// php internal error/warning
$div0 = 10/0;
// user errors messages
fwrite(STDERR, "user controlled error\n");
Вызов eio_event_loop используется, чтобы быть уверенным, что предыдущие запросы eio были обработаны. Если вам нужно добавить в журнал, по вызову fopen, используйте режим 'ab' вместо 'wb'.
Установить eio-модуль очень просто (http://php.net/manual/es/eio.installation.php). Я проверил этот пример с версией 1.2.6 модуля eio.
Ни один из ответов не работал для моего конкретного случая, когда мне нужен был кросс-платформенный способ перенаправления вывода, как только он был эхо-сигнал, чтобы я мог следить за журналами с помощью tail -f log.txt или другого просмотра журнала приложение. Я придумал следующее решение:
$logFp = fopen('log.txt', 'w');
ob_start(function($buffer) use($logFp){
fwrite($logFp, $buffer);
}, 1); //notice the use of chunk_size == 1
echo "first output\n";
sleep(10)
echo "second output\n";
ob_end_clean();
Я не заметил никаких проблем с производительностью, но если вы это сделаете, вы можете изменить chunk_size на большие значения.
Теперь просто хвост - файл журнала:
tail -f log.txt