Web - кодинг: PHP:
Управление Выводом: Caching и сжатие динамических страниц
Автор: Luis Argerich
Перевод: Alexel
Источники: ,
Mod_gzip - Apache модуль, который сжимает статические страницы HTML,
использующие gzip, согласно IETF стандартам для браузеров, которые принимают
gzip enconding (IE, Netscape, и т.д.). Mod_gzip может ускорять время загрузки
страниц в 4-5, раз и я настоятельно предлагаю, чтобы Вы использовали mod_gzip на
вашем webserver'е. Однако из-за недостатка механизма фильтрации между модулями в
Apache 1.x.x, нет никакого способа сжать PHP вывод, используя mod_gzip. Поэтому,
мы должны строить наш собственный движок сжатия в PHP. В этой статье, я объясню,
как использовать функции управляющие выводом PHP, чтобы заставить ваши страницы
загружаться БЫСТРО!
Введение в функции контроля вывода PHP.
Одна из лучших вещей в PHP4 - то, что Вы можете передать PHP буферу весь
контент, сгенерированный в скрипте, так что ничего не будет послано браузеру,
пока Вы не решите это сделать. Вы можете применять эту особенность, чтобы
использовать заголовок и функции setcookie, везде, где Вы хотите в вашем
скрипте. Однако, это - только небольшая часть возможностей мощных функций
вывода.
<? void ob_start(void); ?>
Используется, чтобы сообщить PHP процессору о переадресации всего вывода на
внутренний буфер. Ничего не будет послано браузеру после запроса к ob_start().
<? string ob_get_contents(void); ?>
Возвращает буфер вывода в строке так, что Вы можете переслать накопленный
вывод браузеру (после отключения буферизации!).
<? int
ob_get_length(void); ?>
Возвращает длину буфера вывода.
<? void
ob_end_clean(void); ?>
Очищает буфер вывода и выключает буферизацию вывода. Вы должны использовать
эту функцию до вывода контента браузеру.
void ob_implicit_flush
([int flag]);
Используется, чтобы вкл\выкл неявный поток (default=off). Если включено, то
"поток" выполняется для каждой print/echo или команды вывода и вывод немедленно
посылается в браузер. (Директива неявной отсылки говорит PHP о том, что
выводимые данные нужно автоматически передавать браузеру после вывода каждого
блока данных. Ее действие эквивалентно вызовам функции flush() после каждого
использования print() или echo() и после каждого HTML-блока. Включение этой
директивы серьезно замедляет работу, поэтому ее рекомендуется применять лишь в
отладочных целях.- из комментариев к php.ini, прим. Alexela).
Использование Контроля вывода, чтобы сжать вывод PHP.
Вы нуждаетесь в Zlib расширении, компилируемом в PHP4, чтобы сжать вывод.
Если необходимо, см. Zlib расширение в PHP документации для установки
инструкций.
Прежде всего, инициализируйте буферизацию вывода:
<?
Ob_start (); Ob_implicit_flush (0); ?>
Затем, сгенерируйте все содержание (контент), используя print, echo, или
другое, что Вы хотите. Например:
<? print("Hey this is a
compressed output!"); ?>
После того, как страница сгенерирована, мы возвращаемся к выводу,
использующему:
<? $contents = ob_get_contents
(); Ob_end_clean (); ?>
Затем, мы должны проверить, поддерживает ли браузер сжатие данных. Если да,
браузер посылает ACCEPT_ENCODING HTTP заголовок вебсерверу в запросе. Мы можем
проверить переменную $HTTP_ACCEPT_ENCODING и проверить " gzip, deflate ":
<? if(ereg('gzip,
deflate',$HTTP_ACCEPT_ENCODING)) { // Generation of Gzipped
content } else { echo $contents; } ?>
Это просто. Структурировано и достаточно ясно, чтобы использовать. Давайте
посмотрим, как мы создадим gzipped вывод:
<? (Taken from
PHP.net) // Tell the browser that they are going to get gzip data // Of
course, you already checked if they support gzip or x-gzip // and if they
support x-gzip, you'd change the header to say // x-gzip instead,
right? header("Content-Encoding: gzip" ); // Display the header of the
gzip file // Thanks ck@medienkombinat.de! // Only display this
once echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; // Figure out the size and
CRC of the original for later $Size = strlen($contents); $Crc =
crc32($contents); // Compress the data $contents = gzcompress( $contents,
9); // We can't just output it here, since the CRC is messed up. // If I
try to "echo $contents" at this point, the compressed // data is sent, but
not completely. There are four bytes at // the end that are a CRC. Three are
sent. The last one is // left in limbo. Also, if we "echo $contents", then
the next // byte we echo will not be sent to the client. I am not sure //
if this is a bug in 4.0.2 or not, but the best way to avoid // this is to put
the correct CRC at the end of the compressed // data. (The one generated by
gzcompress looks WAY wrong.) // This will stop Opera from crashing, gunzip
will work, and // other browsers won't keep loading indefinately. // //
Strip off the old CRC (it's there, but it won't be displayed // all the way
-- very odd) $contents = substr($contents, 0, strlen($contents) - 4); //
Show only the compressed data echo $contents; // Output the CRC, then the
size of the
original gzip_PrintFourChars($Crc); gzip_PrintFourChars($Size); //
Done. You can append further data by gzcompressing // another string and
reworking the CRC and Size stuff for // it too. Repeat until
done. function gzip_PrintFourChars($Val) { for ($i = 0; $i < 4; $i ++)
{ echo chr($Val % 256); $Val = floor($Val / 256); } } ?>
Если вы хотите посмотреть это как рабочий пример, то вот весь скрипт целиком:
<? // Start the output
buffer ob_start(); ob_implicit_flush(0); // Output stuff
here... print("I'm compressed!\n"); $contents =
ob_get_contents(); ob_end_clean(); // Tell the browser that they are going
to get gzip data // Of course, you already checked if they support gzip or
x-gzip // and if they support x-gzip, you'd change the header to say //
x-gzip instead, right? header("Content-Encoding: gzip"); // Display the
header of the gzip file // Thanks ck@medienkombinat.de! // Only display
this once echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; // Figure out the size
and CRC of the original for later $Size = strlen($contents); $Crc =
crc32($contents); // Compress the data $contents = gzcompress($contents,
9); // We can't just output it here, since the CRC is messed up. // If I
try to "echo $contents" at this point, the compressed // data is sent, but
not completely. There are four bytes at // the end that are a CRC. Three are
sent. The last one is // left in limbo. Also, if we "echo $contents", then
the next // byte we echo will not be sent to the client. I am not sure //
if this is a bug in 4.0.2 or not, but the best way to avoid // this is to put
the correct CRC at the end of the compressed // data. (The one generated by
gzcompress looks WAY wrong.) // This will stop Opera from crashing, gunzip
will work, and // other browsers won't keep loading indefinately. // //
Strip off the old CRC (it's there, but it won't be displayed // all the way
-- very odd) $contents = substr($contents, 0, strlen($contents) - 4); //
Show only the compressed data echo $contents; // Output the CRC, then the
size of the
original gzip_PrintFourChars($Crc); gzip_PrintFourChars($Size); //
Done. You can append further data by gzcompressing // another string and
reworking the CRC and Size stuff for // it too. Repeat until
done. function gzip_PrintFourChars($Val) { for ($i = 0; $i < 4; $i ++)
{ echo chr($Val % 256); $Val = floor($Val / 256); } } ?>
Кэширование PHP вывода.
Когда PHP4 не существовал, и я вынужден был использовать PHP3, я был очень
заинтересован в появлении некого механизма кэширования для вывода PHP скриптов,
чтобы уменьшить нагрузку базы данных, доступ к filesystem, и т.д. Не имело
смысла делать это в PHP3, но с буферизацией вывода, это легко в PHP4.
Простой пример:
<? //Construct a filename for the
requested
URI $cached_file=md5($REQUEST_URI); if((!file_exists("/cache/$cached_file"))||(!is_valid("/cache/$cached_file")))
//здесь обратите внимание на путь к файлу $cached_file, прим.
Alexela { // is_valid validates the cache, you can check for
expiration // or particular conditions in that function. // If there's no
file or it's invalid we generate the
output ob_start(); ob_implicit_flush(0 ); // Output stuff
here... $contents =
ob_get_contents(); ob_end_clean(); $fil=fopen($cached_file,"w+"); //fwrite($fil,$contents,$strlen($contents));//опечатка
в коде, прим.
Alexela fwrite($fil,$contents,strlen($contents)); fclose($fil); }
//Output the file here we are sure the file
exists. readfile($cached_file); ?>
Это простой пример. Используя буферизацию вывода, Вы можете строить очень
продвинутую контент генерирующую систему, используя caching механизмы, различные
для различных блоков или приложений, и т.д. Это зависит от Вас.
Заключение
Функции, управляющие PHP выводом, очень полезны чтобы переадресовать вывод
скрипта на буфер и затем уже манипулировать им. Сжатие буфера для браузеров
уменьшает время загрузки в 4-5 раз. Это может также использоваться как caching
механизм, чтобы облегчить доступ к источникам данных (базы данных или файлы) и
это может иметь значение, если мы используем XML.
Думайте об этом:
Что, если мы строим движок в PHP4, используя caching, который берет данные из
источников данных (xml документы и базы данных) и динамически строит содержание
в xml . Мы можем тогда брать вывод xml и использовать XSLT, чтобы конвертировать
к любому виду представления, которое мы хотим (HTML, wap, palm, pdf, и т.д.).
PHP4, с контролем вывода и Sablotron XSLT, является совершенным для этой
архитектуры. Я написал " Шикарная architectures "- описание, основанное на xml
архитектуре, у которой есть много всего, что делать с функциями, описанными в
этой статье. Покупайте, если это издано. Я буду также писать статью о Sablotron
XSLT , как только это будет зарегистрировано и полностью годным к употреблению
под PHP4. Шлите мне ваши мысли обо всем, что Вы хотите.
При перепечатке любого материала
с сайта, видимая ссылка на источник www.warayg.narod.ru
и все имена, ссылки авторов обязательны.
© 2005
|