Разделы публикаций

 
     
 

Обработка real-time вывода

nectarin
217
    nectarin nectarin
Сергей NectarIn Новиков
Специализации: 1

Иногда может возникнуть задача на лету обрабатывать какой-либо пользовательский вывод, направляемый в браузер неявно (например, при работе функций readfile() или passthru()). При этом необходимо сохранять вывод в браузер в реальном времени. Для примера рассмотрим реально возникавшую задачу из моей практики.
PHP-скрипт должен запустить консольный сценарий, который в реальном времени выводит на экран проведённые операции, причём делает это небыстро. Пользователь должен так же в реальном времени наблюдать выполнение этого сценария в своём браузере, вдобавок весь вывод этого сценария нужно сохранить. Необходимо также помнить, что консольный сценарий использует символ \\n для переноса строки, тогда как в браузере необходимо применять тэг br.
Решение, как несложно догадаться, в буферизации. Здесь важны следующие моменты. Во-первых, буфер должен быть как можно меньше по объёму, чтобы максимально быстро реагировать на новые блоки текста. Во-вторых, необходимо включить автоматический сброс буфера при переполнении и немедленный вывод в браузер. И в третьих, нужно установить обработчик буферизованного вывода, который будет преобразовывать и сохранять выводимый текст.
Вот так всё это выглядит в контексте класса (показаны только ключевые методы):

/**
 * Выполнение команды, обработка вывода на лету и возврат лога работы.
 * 
 * @param string Консольная команда.
 * @return string Полный лог работы команды.
 */
public function runCommand($command) {
  // Сброс предыдущего лога.
  $this->log '';
10   
11   // Настройка немедленного и автоматического вывода.
12   ini_set('implicit_flush'true);
13   ob_implicit_flush(true);
14   
15   // Старт перехвата выходного потока. Минимальный размер буфера 2 байта (смотри описание функции ob_start()).
16   ob_start(array($this'handleLogPart'), 2);
17   
18   // Запуск команды с автоматическим выводом результата в браузер.
19   passthru($command);
20   
21   // Освобождение буфера вывода и завершение буферизации.
22   ob_end_flush();
23   
24   // Возврат сохранённого вывода.
25   return $this->log;
26 }
27 
28 
29 /**
30  * Callback для обработки лога.
31  * 
32  * @param string Часть лога, получаемая при перехвате буфером.
33  * @return string Обработанная часть лога.
34  */
35 public function handleLogPart($logPart) {
36   // Сохранение части лога.
37   $this->log .= $logPart;
38   
39   // Обработка части лога и возврат.
40   return nl2br($logPart);
41 }

Два байта это наименьший допустимый размер буфера, по крайней мере, до тех пор, пока не появится PHP 6. Поскольку в данной задаче необходимо отслеживать только символы переноса строки (1 байт), можно использовать минимальный размер буфера, чтобы сделать вывод максимально "чутким". Отслеживание и обработка блоков текста длиннее 1 байта потребует большего размера буфера и усложнённой логики для поиска этих блоков на стыках буферизованных частей.
Бывает, что некоторые браузеры не всегда хотят выводить текст сразу, как только получат. Помогает правильная разметка страницы как XHTML 1.0 Strict. Если вывод всё ещё не происходит мгновенно, проверьте, что отключена директива конфигурации output_buffering. И, пожалуй, последнее, что может помешать real-time выводу — другие вызовы ob_start() до запуска процесса.

1
Просмотров: 320
     

Новости inPHP.org Новости inPHP.org
27.05.2010   Технические работы.
По техническим причинам возможны кратковременные перебои в работе сайта проекта в период с 27.05.2010 по 1.06.2010.
02.03.2010   Доступ участников к разработке тестирований.
В тестовом режиме запущен функционал, позволяющий участникам проекта разрабатывать собственные тестирования. Разработанные сообществом тестирования не имеют ограничений официальной аккредитации и в любое время доступны любому участнику.
19.02.2010   Введён общий рейтинг участника.
В рамках программы развития проекта введён параметр общего рейтинга участника. Соответствующие изменения внесены в правила проекта. Рейтинг - один из показателей, которые будут активно использоваться в готовящемся к запуску функционале. Первое из нововведений - доступ участников к системе разработки собственных тестирований и возможность неограниченного использования тестирований, разработанных сообществом, будет запущено в течение марта 2010 года.
 
Содействуют развитию Содействуют развитию
webdev
198
    webdev webdev
Константин
Специализации: 2
Участники проекта Участники проекта
syamka
120
    syamka syamka

Специализации: 0
auswire
40
    auswire auswire

Специализации: 0
ershtad
60
    ershtad ershtad

Специализации: 0
xbelyi
100
    xbelyi xbelyi
Белый Александр
Специализации: 0
vetptzru
60
    vetptzru vetptzru

Специализации: 0
 
Статистика проекта Статистика проекта
Всего пользователей: 3050
Из них аккредитовано: 1207
Были сегодня: 17

УровеньПользователи
7481,6%
62157%
51585,2%
41665,4%
32909,5%
2411,3%
12889,4%
отсутствует184360,4%