Портал для веб-мастера

Инструменты для Бизнеса

Вход пользователей
Поиск статей
WoWeb.ru » Статьи » Программирование для Web » PHP

Использование Output Buffering в PHP

В моей первой статье было несколько интересных моментов, о которых хотелось упомянуть, однако не хотелось акцентировать внимание, потому что это уводило в сторону от основного содержимого. Но теперь, когда эти моменты являются темой для отдельной статьи, просто необходимо остановиться на них подробнее ;)

Коротко суть проблемы можно изложить так: очень часто те данные, которые вы получаете, например, из базы данных, должны фигурировать в тексте HTML-страницы гораздо ранее того участка программы, который занимается добычей этих данных. Например, заголовок страницы, задаваемый тэгом , зачастую является содержимым какого-либо поля таблицы БД, а блок программы, который обращается к БД, расположен гораздо позже вывода заголовка страницы. <P>Что делать? Ответ простой - читать документацию. На функции ob_*, начиная с ob_start()<BR>Оказывается, что в PHP есть возможность не сразу выдавать результат работы скрипта браузеру, а сохранять в специальном месте, именуемом Output Buffer (буфер вывода). При этом в PHP есть функции, которые позволяют изменять его содержимое. Еще одним аргументом за ob_start() в самом начале программы является возможность установки различных HTTP-заголовков, например, cookies, в произвольном месте скрипта, а не в самом его начале. <P>Кстати, в PHP есть возможность "сжать" (заархивировать) результат работы вашего скрипта, дабы уменьшить количество трафика, гуляющего по сети - для этого нужно вызвать функцию ob_start с параметром "ob_gzhandler": ob_start("ob_gzhandler"); Естественно, если браузер не поддерживает сжатый контент - ваша страница будет передана ему без изменений. <P>А теперь давайте от слов перейдём к конкретным примерам: <FONT color=red> <P>Внимание! Здесь и далее предполагается, что в самом начале скрипта включается буферизация вывода: <CODE><PRE><? ob_start(); ?> </PRE></CODE></FONT> <P>Пример 1: автоматическая подсветка переменных.<BR>Предположим, у вас на сайте есть статьи, посвященные PHP. Естественно, они должны содержать и примеры кода на PHP ;) Однако, если весь ваш код будет набран шрифтом одного цвета, то читать этот код будет немного затруднительно. Так давайте раскрасим код! Пусть все имена переменных будут синего цвета. А комментарии - красного (будем считать, что комментарии начинаются c //). Для этого в самом конце скрипта добавляем следующий код: <CODE><PRE><? <FONT color=blue>$x</FONT>=ob_get_contents(); <FONT color=red>// получаем содержимое output buffer</FONT> ob_clean(); <FONT color=red>// очищаем его</FONT> <FONT color=blue>$x</FONT>=preg_replace(<FONT color=green>"/(\\$[\\w]+)/si"</FONT>,<FONT color=green>"<font color=\"blue\">\\1</font>"</FONT>,<FONT color=blue>$x</FONT>); <FONT color=red>// заменяем всё, что начинается со знака $ и продолжается более, </FONT> <FONT color=red>// чем одним алфавитно-цифровым символом</FONT> <FONT color=red>// на то же самое, но обрамлённое тэгами <font> синего цвета</FONT> <FONT color=blue>$x</FONT>=preg_replace(<FONT color=green>"/(?<!:)(\\/\\/[^\\r\\n]+)[\\r\\n]/si"</FONT>,<FONT color=green>"<font color=\"red\">\\1</font>"</FONT>,<FONT color=blue>$x</FONT>); <FONT color=red>// заменяем комментарии на самих себя, но делаем их красного цвета</FONT> <FONT color=red>// (?<!:) нужно, чтобы случайно не поменять ссылки - http://webscript.ru, например.</FONT> echo <FONT color=blue>$x</FONT>; <FONT color=red>// результат на лицо, то есть в браузер ;)</FONT> ?> </PRE></CODE>Естественно, вышеприведённый пример не является идеальным - например, если в вашем тексте встретится код JavaScript, в котором нечаянно окажется комментарий, то работать он перестанет. Однако, с небольшой модификацией, именно этот пример раскрасил, хоть и не идеально, эту статью. <P>Пример 2: автоматическое распознавание URL и генерация ссылок.<BR>Предположим, у вас на сайте есть гостевая книга или форум, и какой-либо посетитель решил разместить ссылку на свой ресурс. Дабы не утруждать пользователя изучением HTML, было бы удобно сделать так, чтобы все URL, указанные пользователем, автоматически обрамлялись в соответствующие ссылки на языке HTML. Например: <PRE>http://php.net => <a href="http://php.net">php.net</a> ftp://ftp.chg.ru => <a href="ftp://ftp.chg.ru">ftp.chg.ru</a> </PRE>Так же было бы полезно преобразовывать следующие строки: <PRE>www.webscript.ru => <a href="http://www.webscript.ru">www.webscript.ru</a> ftp.chg.ru => <a href="http://ftp.chg.ru">ftp.chg.ru</a> </PRE>Приступим: <P>в самом конце вашего скрипта надо дописать следующий код: <CODE><PRE><? <FONT color=blue>$x</FONT>=ob_get_contents(); ob_clean(); <FONT color=blue>$x</FONT>=preg_replace(<FONT color=green>"/(?<!\\/)(www\\.[\\S]+)/si"</FONT>,'<a href=<FONT color=green>"http://\\1"</FONT>>\\1</a>',<FONT color=blue>$x</FONT>); <FONT color=red>// меняем всё, что начинается с www, но не следует после /, на <a href=<FONT color=green>"http://www..."</FONT>>www...</a></FONT> <FONT color=red>// тут используется <FONT color=green>"важный"</FONT> regexp - (?<!\\/) - без него уже существующие ссылки типа </FONT> <FONT color=red>// <a href=<FONT color=green>"http://www..."</FONT>> тоже бы подверглись преобразованию... </FONT> <FONT color=red>//результат получается не совсем желательным</FONT> <FONT color=blue>$x</FONT>=preg_replace(<FONT color=green>"/(?<!\\/)(ftp\\.[\\S]+)/si"</FONT>,'<a href=<FONT color=green>"ftp://\\1"</FONT>>\\1</a>',<FONT color=blue>$x</FONT>); <FONT color=red>// аналогично поступаем с ftp...</FONT> <FONT color=blue>$x</FONT>=preg_replace(<FONT color=green>"/(?<!\")(http|ftp):\\/\\/(\\S+)/si"</FONT>,'<a href=<FONT color=green>"\\1://\\2"</FONT>>\\2</a>',<FONT color=blue>$x</FONT>); <FONT color=red>// здесь мы обрабатываем строки вида (http|ftp)://что-нибудь, заменяя эту последовательность </FONT> <FONT color=red>// соответствующими тэгами HTML</FONT> echo <FONT color=blue>$x</FONT>; ?> </PRE></CODE> <P>Пример 3: автоматическая генерация ссылок на разделы вашего сайта<BR>Предположим, что вы являетесь автором какого-либо информационного ресурса, и в своих материалах достаточно часто упоминаете информацию, которая содержится в других разделах вашего сайта. Согласитесь, было бы удобно, если бы все названия разделов, упоминающиеся в тексте статьи, были ссылками на соответствующие разделы. Ну так давайте сделаем это: <CODE><PRE><? <FONT color=blue>$links</FONT>=array( <FONT color=green>"новости"</FONT>=>array(<FONT color=green>"url"</FONT>=><FONT color=green>"/news"</FONT>,<FONT color=green>"synonyms"</FONT>=><FONT color=green>"в разделе новостей,последние новости,новости сайта"</FONT>), <FONT color=green>"голосования"</FONT>=>array(<FONT color=green>"url"</FONT>=><FONT color=green>"/votes"</FONT>,<FONT color=green>"synonyms"</FONT>=><FONT color=green>"раздел голосований,проголосуй"</FONT>) ); <FONT color=red>// массив links - это описание соответствий названий разделов и их URL</FONT> <FONT color=red>// естественно, что на вашем сайте он создаётся из БД</FONT> <FONT color=red>// кроме того, для каждого раздела полезно иметь список синонимов</FONT> <FONT color=red>// а то php не силён в падежах, склонениях, спряжениях и т.д.</FONT> setlocale(LC_ALL,<FONT color=green>"ru"</FONT>); <FONT color=red>// полезно включить локаль, а то PHP не сможет отличить прописные буквы</FONT> <FONT color=red>// русского языка от их <FONT color=green>"братьев меньших"</FONT> ;)</FONT> <FONT color=blue>$x</FONT>=ob_get_contents(); ob_clean(); foreach (<FONT color=blue>$links</FONT> as <FONT color=blue>$word</FONT>=><FONT color=blue>$description</FONT>) { <FONT color=blue>$synonyms</FONT>=split(<FONT color=green>","</FONT>,<FONT color=blue>$description</FONT>['synonyms']); <FONT color=red>// берем список синонимов и помещаем их в массив </FONT> <FONT color=blue>$synonyms</FONT>[]=<FONT color=blue>$word</FONT>; <FONT color=red>// слово есть синоним самого себя</FONT> foreach (<FONT color=blue>$synonyms</FONT> as <FONT color=blue>$replace</FONT>) { <FONT color=blue>$x</FONT>=preg_replace(<FONT color=green>"/(\\W)(<FONT color=blue>$replace</FONT>)(\\W)/is"</FONT>, <FONT color=green>"\\1<a href=\""</FONT>.<FONT color=blue>$description</FONT>['url'].<FONT color=green>"\">\\2</a>\\3"</FONT>,<FONT color=blue>$x</FONT>); <FONT color=red>// заменяем все вхождения синонима на ссылку на соответствующий раздел</FONT> <FONT color=red>// сохраняя при этом старое название</FONT> } } echo <FONT color=blue>$x</FONT>; ?> </PRE></CODE>Естественно, приведённый выше пример нельзя считать окончательным - например, если у вас где-нибудь в синонимах встретится какой-то из символов, имеющих специальное значение в perl regular expressions, например, скобки, то результатом выполнения этого кусочка программы могут стать сообщения об ошибках на ваших страницах. Кроме того, приведённое выше регулярное выражение не учитывает, что название раздела уже может являться ссылкой либо её частью, и, соответственно, испортит её. <P>Но, тем не менее, эта технология, с некоторыми дополнениями, спасает автора этих строк от написания ссылок на разделы <A href="http://dmitry.rsl.ru">своего сайта</A>. Кроме того, именно с использованием output buffering становится очень простым реализация достаточно сложных вещей - например, экспорт данных в excel можно реализовать, написав буквально пару операторов (подсказка: excel умеет импортировать HTML, ну а как отрезать дизайн от экспортируемой таблицы вы, наверное, уже догадались).<!-- content ends --></P></td></tr> <tr><td height="10"> </td></tr> <tr><td bgcolor="#F7F7F7" style="border:1px dotted #EAEAEA;"> Автор: <b>Дмитрий Верещака</b> <a href="javascript:;" rel="nofollow" onclick="window.top.location.href='mai'+'lto:'+'dmi'+'try@r'+'sl.ru';return false;"><img border="0" src="//src.ucoz.ru/t/111/e.gif" align="absmiddle" title="E-mail" width="14" height="10"></a> <a rel="nofollow" href="javascript://" onclick="window.open('http://dmitry.rsl.ru'); return false;"><img border="0" src="//src.ucoz.ru/t/111/h.gif" align="absmiddle" title="Home Page" width="11" height="10"></a> · Добавлена: 2003-09-08 <br> Просмотров: <b>3803</b> · Рейтинг: <b>0.0</b><img title="0.0" border="0" src="/img/s0.gif" align="absmiddle" width="64" height="12"> <select id="rt313" name="rating" class="eRating" onchange="eRateEntry(this, 313)" autocomplete=off > <option value="0" selected>- Оценить -</option> <option value="5">Отлично</option> <option value="4">Хорошо</option> <option value="3">Неплохо</option> <option value="2">Плохо</option> <option value="1">Ужасно</option></select> </td></tr> </table> <br /> <!-- Comments --> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr><td width="60%" height="25">Всего комментариев: <b>0</b></td><td align="right" height="25"></td></tr> <tr><td colspan="2"><script> function spages(p, link) { !!link && location.assign(atob(link)); } </script> <div id="comments"></div> <div id="newEntryT"></div> <div id="allEntries"></div> <div id="newEntryB"></div></td></tr> <tr><td colspan="2" align="center"></td></tr> <tr><td colspan="2" height="10"></td></tr> </table> <div align="center" class="commReg">Добавлять комментарии могут только зарегистрированные пользователи.<br />[ <a href="/register">Регистрация</a> | <a href="javascript:;" rel="nofollow" onclick="loginPopupForm(); return false;">Вход</a> ]</div> </td></tr> </table> </td> </tr> <tr> <td><img border="0" src="/img/10.gif" width="7" height="7"></td> <td width="99%" style="border-bottom: 1px solid #BDBDBD;"><img border="0" src="/img/4.gif" width="1" height="1"></td> <td><img border="0" src="/img/11.gif" width="7" height="7"></td> </tr> </table> <!-- /Center --> <br> </td> <td valign="top"> <!-- Righter --> <!--U1RIGHTER1Z--> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td><img border="0" src="/img/12.gif" width="185" height="11"></td></tr> <tr> <td> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td bgcolor="#51B5E9"><img border="0" src="/img/13.gif" width="18" height="18"></td> <td width="100%" bgcolor="#51B5E9" class="tdmar" style="color:#FFFFFF;" align="right"><b>Категории раздела</b></td> <td bgcolor="#DFDFDF"><img border="0" src="/img/4.gif" width="7" height="18"></td></tr> </table> </td> </tr> <tr> <td width="100%" style="border-left: 1px solid #BDBDBD;padding:5px;"> <table border="0" cellpadding="0" cellspacing="1" width="100%"> <tr><td class="catsTd1"><a class="catName1" href="/publ/1">Flash</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/13">Apache</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/14">WWW</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/15">PhotoShop</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/26">Веб-дизайн</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/27">Раскрутка и реклама</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/40">Базы данных</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/46">3D графика</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/47">Хостинг</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/48">Истории веб-мастеров</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/49">Web-технологии</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/50">Сетевая безопасность</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/57">Программирование для Web</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="/publ/65">Операционные системы</a></td></tr> <tr><td height="10"><hr></td></tr> <tr><td class="catsTd1"><a class="catName1" href="javascript://" onclick="window.location.href='/publ/0-1-1-0-16';return false;">Новые статьи</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="javascript://" onclick="window.location.href='/publ/0-1-2-0-16';return false;">Лучшие статьи</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="javascript://" onclick="window.location.href='/publ/0-1-3-0-16';return false;">Популярные статьи</a></td></tr> <tr><td class="catsTd1"><a class="catName1" href="javascript://" onclick="window.location.href='/publ/0-1-4-0-16';return false;">Комментируемые статьи</a> </td></tr> </table> </td> </tr> <tr><td width="100%"colspan="2"><img border="0" src="/img/14.gif" width="185" height="9"></td></tr> <tr><td height="10"></td></tr> </table> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td><img border="0" src="/img/12.gif" width="185" height="11"></td></tr> <tr> <td> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td bgcolor="#51B5E9"><img border="0" src="/img/13.gif" width="18" height="18"></td> <td width="100%" bgcolor="#51B5E9" class="tdmar" style="color:#FFFFFF;" align="right"><b>Разделы сайта</b></td> <td bgcolor="#DFDFDF"><img border="0" src="/img/4.gif" width="7" height="18"></td></tr> </table> </td> </tr> <tr> <td width="100%" style="border-left: 1px solid #BDBDBD;padding:5px;"> <table align="center" border="0" cellspacing="1" cellpadding="0" width="100%" class="catsTable"><tr><td width="100%" class="catsTd1"><a href="/load/" class="catName1">Скрипты</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/publ/" class="catName1">Статьи</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/blog/" class="catName1">Шрифты</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/dir/" class="catName1">Флэш исходники</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/news/" class="catName1">HTML шаблоны</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/board/" class="catName1">Партнерки</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/index/0-6" class="catName1">Клипарты</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/index/0-2" class="catName1">Смайлы</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/index/0-3" class="catName1">Фоны</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/index/0-5" class="catName1">Гифы</a> </td></tr><tr><td width="100%" class="catsTd1"><a href="/index/0-4" class="catName1">Иконки</a> </td></tr></table> </td> </tr> <tr><td width="100%"colspan="2"><img border="0" src="/img/14.gif" width="185" height="9"></td></tr> <tr><td height="10"></td></tr> </table> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td><img border="0" src="/img/12.gif" width="185" height="11"></td></tr> <tr> <td> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td bgcolor="#51B5E9"><img border="0" src="/img/13.gif" width="18" height="18"></td> <td width="100%" bgcolor="#51B5E9" class="tdmar" style="color:#FFFFFF;" align="right"><b>Опрос сайта</b></td> <td bgcolor="#DFDFDF"><img border="0" src="/img/4.gif" width="7" height="18"></td></tr> </table> </td> </tr> <tr> <td width="100%" style="border-left: 1px solid #BDBDBD;padding-top:7px;padding-left:5px;padding-right:5px;" align="center"> <script>function pollnow820(){document.getElementById('PlBtn820').disabled=true;_uPostForm('pollform820',{url:'/poll/',type:'POST'});}function polll820(id,i){_uPostForm('',{url:'/poll/'+id+'-1-'+i+'-820',type:'GET'});}</script><div id="pollBlock820"><form id="pollform820" onsubmit="pollnow820();return false;"><div class="pollBlock"> <div class="pollQue"><b>Есть ли у вас свой сайт?</b></div> <div class="pollAns"><div class="answer"><input id="a8201" type="radio" name="answer" value="1" style="vertical-align:middle;" /> <label style="vertical-align:middle;display:inline;" for="a8201">Да, есть</label></div> <div class="answer"><input id="a8202" type="radio" name="answer" value="2" style="vertical-align:middle;" /> <label style="vertical-align:middle;display:inline;" for="a8202">Был</label></div> <div class="answer"><input id="a8203" type="radio" name="answer" value="3" style="vertical-align:middle;" /> <label style="vertical-align:middle;display:inline;" for="a8203">Планирую создать</label></div> <div class="answer"><input id="a8204" type="radio" name="answer" value="4" style="vertical-align:middle;" /> <label style="vertical-align:middle;display:inline;" for="a8204">Нет и не планирую</label></div> <div id="pollSbm820" class="pollButton"><input class="pollBut" id="PlBtn820" type="submit" value="Ответить" /></div> <input type="hidden" name="ssid" value="314211342756753240032" /> <input type="hidden" name="id" value="5" /> <input type="hidden" name="a" value="1" /> <input type="hidden" name="ajax" value="820" /></div> <div class="pollLnk"> <a href="javascript:;" rel="nofollow" onclick="new _uWnd('PollR','Результаты опроса',660,200,{closeonesc:1,maxh:400},{url:'/poll/5'});return false;">Результаты</a> | <a href="javascript:;" rel="nofollow" onclick="new _uWnd('PollA','Архив опросов',660,250,{closeonesc:1,maxh:400,max:1,min:1},{url:'/poll/0-2'});return false;">Архив опросов</a> </div> <div class="pollTot">Всего ответов: <b>141619</b></div> </div></form></div> </td> </tr> <tr><td width="100%"colspan="2"><img border="0" src="/img/14.gif" width="185" height="9"></td></tr> <tr><td height="10"></td></tr> </table> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td><img border="0" src="/img/12.gif" width="185" height="11"></td></tr> <tr> <td> <table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr><td bgcolor="#51B5E9"><img border="0" src="/img/13.gif" width="18" height="18"></td> <td width="100%" bgcolor="#51B5E9" class="tdmar" style="color:#FFFFFF;" align="right"><b>Наша кнопка</b></td> <td bgcolor="#DFDFDF"><img border="0" src="/img/4.gif" width="7" height="18"></td></tr> </table> </td> </tr> <tr> <td width="100%" style="border-left: 1px solid #BDBDBD;padding-top:7px;padding-left:5px;padding-right:5px;" align="center"> <a href="http://www.woweb.ru/" target="_blank"><img border="0" src="/img/woweb.gif" width="88" height="31" alt="WoWeb.ru - портал для веб-мастера"></a><br> <textarea cols=20 rows=3 style="width:140px; font-size:9px;" readonly scrolling="auto" onclick="select(this)"> <a href="http://www.woweb.ru/" target="_blank"><img border="0" src="http://www.woweb.ru/img/woweb.gif" width="88" height="31" alt="WoWeb.ru - портал для веб-мастера"></a> </textarea> </td> </tr> <tr><td width="100%"colspan="2"><img border="0" src="/img/14.gif" width="185" height="9"></td></tr> <tr><td height="10"></td></tr> </table><!--/U1RIGHTER1Z--> <!-- /Righter --> </td> </tr> </table> <!-- Footer --> <!--U1FOOTER1Z--><br><br><div align="center"></div><!--/U1FOOTER1Z--> <!-- /Footer --> </body> </html> <!-- 0.08965 (s4) -->