Индикация процесса длительной обработки на PHP для ленивых :)

21.03.2010 22:55 / Артём Волк / 1522 просмотра / ...

Иногда в веб-приложениях возникает необходимость выполнить какую-то обработку, занимающую больше нескольких секунд. В случае, если отображать процесс выполнения для пользователя нет необходимости можно обойтись скриптами, запускаемыми из командной строки (для PHP) или консольными утилитами (для ASP.NET).

Для отображения же процесса выполнения какой-то полезной работы (например, разбора и импорта большого XML-файла в БД) можно применить код на клиентской стороне, регулярно опрашивающий AJAX-запросом серверную часть. Сам процесс выполнение часть может быть реализована по разному. Начиная от отдельного thread'a (для ASP.NET) и заканчивая очередями заданий.

Самое быстрое решение для PHP, не требущее AJAX'a подсмотрено в Sypex Dumper Lite 1.0.8. Идея состоит в том, чтобы увеличить максимальное время выполнение скрипта с помощью set_time_limit() и выключить буферизацию вывода. Дополнительные заголовки применяются для отключения кеширования на клиенте:

// Заголовки для отключения кеширования в браузере	
header("Expires: Tue, 1 Jul 2003 05:00:00 GMT");	
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache");

// Увеличиваем максимальное время выполнение скрипта
set_time_limit(6000);

// Весь вывод сразу будет отсылаться в браузер
ob_implicit_flush();

for ($i = 0; $i < 60; $i++)
{
	echo '. ';
	sleep(1);
}

В оригинальной реализации подобным образом выводятся небольшие фрагменты JavaScript-кода, добавляющие сообщения в определённую область на экране.

К недостаткам решения можно отнести:

  • В случае, если включен safe mode в PHP, set_time_limit() не сработает
  • Если перед apache стоит nginx или клиент находится за прокси, страница может быть показана пользователю только после полной загрузки

Идея чем-то похожа на технику Hidden IFrame для Comet.