48
№ 15 Октябрь '05 издается с февраля 2004 года, www.phpinside.ru Интервью: авторы dbtree и phpMyAdmin Тонкая настройка PHP Новый взгляд на Smarty

#15, Октябрь'2005 :: Тонкая настройка PHP

  • Upload
    vital-b

  • View
    232

  • Download
    2

Embed Size (px)

DESCRIPTION

HOWTO по оптимизации PHP Логирование ошибок стандартными средствами PHP Один PHP хорошо, а два лучше Наши. Кузьма Феськов и dbtree Интервью с одним из ведущих разработчиков phpMyAdmin Марком Делислом Smarty — не просто шаблоны Принципы создания proxy-сервера на PHP в интрасети. Вопросы безопасности

Citation preview

№ 15Октябрь '05

издается с февраля 2004 года, www.phpinside.ru

Интервью: авторы dbtree и phpMyAdmin

Тонкая настройка PHP

Новый взгляд на Smarty

СодержаниеЛюди Наши. Кузьма Феськов и dbtree...................................................................................................................4 Интервью с одним из ведущих разработчиков phpMyAdmin Марком Делислом..................................7Идеи Smarty — не просто шаблоны....................................................................................................................11 Принципы создания proxy-сервера на PHP в интрасети. Вопросы безопасности................................17Тема с обложки HOWTO по оптимизации PHP...................................................................................................................19 Логирование ошибок стандартными средствами PHP............................................................................41 Один PHP хорошо, а два лучше.................................................................................................................45

АнонсМы рады сообщить вам, что следующая PHP-конференция пройдет в мае 2006 г.

в Москве.

Тематика конференции•Применение PHP в веб-разработке: приёмы, методы и парадигмы программирования вPHP, полезные модули и библиотеки.

•Эффективное создание приложений: фреймворки, гибкие методологии, экстремальноепрограммирование, ТDD-методики.

•PHP и корпоративные информационные системы: разработка систем масштаба пред-приятия, интеграция корпоративных ИС.

•Будущее PHP: основные направления развития, PHP6, мультиязычные приложения,Unicode.

Совместно с конференцией пройдет серия мастер-классов

(практических занятий).

•Test driven development (TDD) — 2.5 дня: приемы, паттерны, тестирование операций сБД, рефакторинг, функциональное тестирование, использование SimpleTest иSelenium.

•Разработка расширений PHP — 0.5 дня: Объектно-ориентированные модули изнутри,портирование PHP классов на C, Zend API.

Порядок оформления заявок на участие вконференции

Авторам, желающим принять участие в конференции с устным докладом (30-60мин.), необходимо до 1 февраля 2006 отправить тезисы доклада (в виде стандартногофайла .doc или .txt произвольной формы) объемом в одну-две страницы, отражающие cо-держание представляемого доклада.

На основе тезисов будет проведен отбор докладов для включения в программу кон-ференции.

2

P

HP

In

side

#15

С

ОД

ЕРЖ

АН

ИЕ

/ А

НО

НС

Ы

Авторы докладов, прошедших рецензирование, будут уведомлены после 15 февра-ля и получат второе информационное сообщение, в котором будут изложены правилаоформления электронных версий докладов.

Тезисы докладов принимаются оргкомитетом по электронному адресу:[email protected].

Все сведения о подготовке и работе конференции, включая требования к представ-ляемым материалам, данные об участниках конференции, программа, контрольные срокии текущие объявления, будут приведены на официальном интернет-сайте конференции:http://www.phpconf.ru/

Если вы планируете участвовать в мастер-классах, просим вас учесть, что числомест на каждый мастер-класс ограничено (~24 чел.), поскольку мастер-классы ориенти-рованы на большое количество практики.

Участие в мастер-классах оплачивается отдельно от конференции и требует на-личия ноутбука c определенным ПО (Apache+MySQL+PHP5+клиент cvs).

Основные датыДо 1 февраля — прием тезисов, докладов.

20 февраля — рассылка второго информационного сообщения с предварительнымпорядком работы конференции, списком принятых докладов и перечнем требований пооформлению электронных версий.

1 марта — рассылка третьего информационного сообщения с программой работыконференции.

1 апреля — прием докладов и оплата участия по программе предварительной реги-страции (действуют скидки корпоративным участникам, от 3-х и более человек).

Середина мая - мастер-классы (3дня), рабочие дни конференции (2дня)

Наши координатыАдрес электронной почты оргкомитета: [email protected].

По вопросам спонсорского участия обращайтесь по адресу: [email protected].

Официальный сайт PHP-конференции

http://www.phpconf.ru/

3

P

HP

In

side

#15

А

НО

НС

Ы

Наши. Кузьма Феськов и dbtree

Наши. Кузьма Феськов и dbtreeИнтервьюировал: Андрей Олищук [nw]

Мы продолжаем серию статей и интервью с отечественны-ми PHP-разработчиками

Кузьма Феськов — автор современной версии библиотеки для рабо-ты с иерархическими структурами dbtree, автор и переводчик докумен-тации (к ADODB, официальный перевод к phpGacl) и статей о PHP и свя-занных технологиях, любезно согласился дать нашему журналу интер-вью.

nw: Ты являешься автором библиотеки dbtree. Откуда пришламысль развивать эту библиотеку?

Кузьма Феськов (КФ): Когда-то наткнулся на phpDBTree МаксимаПолторака. С математикой у меня к сожалению туго, и далась мне эта тео-рия не сразу, помнится даже забрасывал пару раз в дальний угол все этодело. А потом настало «просветление» и как-то все встало на свои места.Организация класса Максимом мне не подходила: слишком много своихразработок к тому времени накопилось.

Это подтолкнуло к глобальной переделке библиотеки. Работанад разными проектами шла, стали выявляться постоянно нужныеоднотипные операции, которые имели отношение к выводу дерева,но не к его обработке. Подумалось, раз эти действия так часто повто-ряются, почему они не могут стать частью библиотеки? Вот они истали ее частью, значительно расширив ее функционал. Количествоинтересующихся этой темой росло, а информации не очень-то и при-бавлялось.

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

Как вы понимаете, где публичный доступ, там и вопросы, и претензии, и просьбы– пришлось развивать. Текущая версия (2.1) на редкость получилась удачной, поток за-мечаний резко иссяк, хотя по количеству обращений вижу, что интерес наоборот возрос.Сей факт позволил мне сделать передышку и на время остановиться и подумать над даль-нейшими планами – а планы, поверьте, есть!

nw: Что умеет твоя библиотека?

КФ: Ну, разумеется, она умеет ловко управляться с деревьями, причем предлагаетнесколько простых и, отчасти, уникальных функций. В прочем, давайте по порядку:

• добавление, редактирование и удаление узлов – стандартные функции;

4

P

HP

In

side

#15

Л

ЮД

И

Очень хочетсяпоблагодаритьзарубежныхпрограммистов – нельзяне отметить ихдисциплину иэффективность их писем

Наши. Кузьма Феськов и dbtree

• перемещение узлов – здесь есть несколько интересных находок, которые позволяютрешить давнюю проблему деревьев Nested Sets, а именно – сортировку узлов в преде-лах одного родителя, что значительно облегчило жизнь программисту и менеджеру;

• изюминкой библиотеки также можно считать набор функций для вывода деревьев, этифункции легко и непринужденно позволяют организовать навигацию, если дерево ис-пользуется для организации разделов сайта, некоторые полезные моменты, например,вывод приоткрытого дерева значительно упростит жизнь при показе каталога товаровв магазине;

• безусловно, нельзя не отметить поддержку транзакций и множества (думаю, что неограниченного количества) баз данных – все это базируется на библиотеке ADODB.На сегодняшний день я предлагаю программистам удобный и простой интерфейс,благодаря которому они могут использовать PEAR::DB и любой другой класс для ра-боты с базой данных.

Думаю, что этого списка «умений» достаточно, чтобы начать ей пользоваться!

nw: Каким образом происходит работа над новым функционалом библиоте-ки? Кто-то пишет тебе feauture requests или ты реализуешь то, что необходимопрежде всего тебе?

Здесь задействованы разные пути, например, в текущей версии есть пара «за-казных» функций, написанных по просьбе Мануэля Лемоса, который живо откликнулсяна появление данной библиотеки на phpclasses.org. Разумеется, очень много мне диктуютвнутренние потребности моих проектов.

Очень хочется поблагодарить зарубежных программистов – нельзя не отметить ихдисциплину и эффективность их писем. Я конечно же получаю письма и от русскогово-рящих пользователей, однако они в подавляющем большинстве просительные иликонстатационые. Например, среднестатистический западный программист всегда четкоопишет ошибку, подробно задокументирует обстоятельства, при которых она возникла,и, иногда, предложит пути исправления. Это очень помогает развитию библиотеки и взначительной степени впрощает жизнь мне и другим пользователям. Очень надеюсь ви-деть такие же содержательные письма и от российских пользователей.

nw: Ты перевел документацию к некоторым известным библиотекам, таким кпримеру, как ADODB. Зачем тебе это? Почему ты просто не читаешь документациюи не забываешь о ней по прочтении?

Наверное сказываются два моих педагогических диплома – немогу я пройти мимо, не могу не поделиться своими знаниями. Если яв чем-то досконально разобрался – я обязательно напишу об этомстатью или переведу документацию. Во-первых, это определеннаядань уважения создателям этих библиотек – они помогли мне, а я, всвою очередь, помогаю им; во-вторых, я считаю, что становление по-настоящему профессионального программистского сообщества вРоссии невозможно без такого альтруизма, ибо книги выходят уста-ревшими, многие просто не умеют (не значит не хотят) делитьсясвоими знаниями, остаюсь я (пусть и не скромно) и другие достойные люди, которыеотдают свои знания другим.

nw: С решением каких задач тебе приходится сталкиваться как веб-разработ-чику чаще всего? В каких областях разработки ты считаешь себя наиболее компе-тентным?

По работе я очень часто сталкивался с многоязычными приложениями, поэтомуочень хорошо разбираюсь в вопросах многоязычности и всем, что с этими вопросамисвязано. Всегда с удовольствием выступаю в роли проектировщика. Достаточно хорошочуствую себя управленцем – руководство командой разработчиков.

5

P

HP

In

side

#15

Л

ЮД

И

Cтановление по-настоящемупрофессиональногопрограммистскогосообщества в Россииневозможно безальтруизма

Наши. Кузьма Феськов и dbtree

Также меня интересуют вопросы дистанционного образования и систем тестирова-ния. В остальном же – всегда интересно изучить и использовать новую технологию, до-копаться до сути вопроса. Что будет в результате? Следите за моим сайтом, как правило,мои изыскани заканчиваются статьей или переводом.

nw: Какими технологиями ты пользуешься? (СУБД, веб-серверы, шаблониза-торы, библиотеки, модули к PHP etc)

Даже не знаю, что тут и упомянуть – много средств: какие-то лучше знаю, какие-тохуже. CVS, XML, MySQL,PostgreSQL, Smarty, Curl, GetText, Iconv и так далее.

nw: Компания в которой ты трудишься, работает на зарубежных заказчиков.Есть ли разница между зарубежными заказчиками и отечественными клиентами?Отличаются ли условия работы, организационные процессы, требования, оплататруда?

Гм – не думаю, что я смогу написать в ответ что-то дельное. Компания как компа-ния – те же проблемы, что и у всех, продвижения и зарплаты также нужно добиваться.

nw: Мы узнали о твоих профессиональных интересах. А какой ты в обычнойжизни? Как проводишь свободное время? Где и как проводишь отпуска? Что лю-бишь и какую музыку слушаешь обычно?

Очень много читаю, поэтому меня часто называют занудой и заумным чудиком.Мне думается, что я просто человек своего мира – мне никогда не бывает скучно с самисобой. Между тем я очень отзывчивый, бодрый и веселый!

В свое время объездил всю Россию, сейчас осваиваю заграницу. Мое последнееприключение – Прага. Дивный город, постоянно его вспоминаю, хочу обратно!

Мой музыкальный формат – 104 FM – Наше радио – Русский рок. Также Стинг,Мадонна и разнообразная инструментальная музыка. Очень люблю радио постановки,поэтому постоянно что-то скачиваю из Интернета и слушаю – очень помогает в развитиивоображения, образного мышления – крайне рекомендую!

Мне кажется, что я умею быть отличным другом – поэтому у меня много друзей изнакомых.

Ну, вот на этом, пожалуй, я закончу саморекламную паузу! Хочется пожелать чита-телям журнала удачи, успеха и профессионализма!

6

P

HP

In

side

#15

Л

ЮД

И

Интервью с одним из ведущих разработчиков phpMyAdmin Марком Делислом

Интервью с одним из ведущихразработчиков phpMyAdmin МаркомДелислом

Интервьюировал: Arjen LentzПеревод: Андрей Олищук

Arjen Lentz - менеджер по связям с сообществом разработчи-ков в MySQL AB

Марк Делисл (Marc Delisle) - один из ведущих разработчиков популрного проектаphpMyAdmin, веб-ориентированного инструмента для администрирования MySQL. Ярасспросил Марка о MySQL, phpMyAdmin (конечно же!) и о процессах разработки в це-лом.

Arjen: Пожалуйста, расскажите о себе, немного фактов из жизни, для тех ктоне знает Марка как человека.

Marc: я разработчик программного обеспечения и системный администраторCegep de Sherbrook, колледжа расположенного в Квебеке, Канада. В этой сфере работаюс 1980 года, а это означает, что мне пришлось пережить много волн развития компьютер-ных технологий, включая разработку приложений на Cobol для Oracle, пользовательскихинтерфейсов на бейсике для терминалов и т.д. С 1998 года я, по большей части, работаюдля веба на PHP. Что касается личной жизни, то я горжусь тем, что являюсь отцомчетырех детей.

Arjen: Почему вы выбрали MySQL и когда произошло знакомство с этойСУБД?

Marc: Я начал с mSQL (Mini SQL Дэвида Хьюза) для преподавания курса по базамданных (я так же подрабатываю преподаванием) и тогда мне не хватило некоторых воз-можностей. Тогда, в 1998 я и познакомился с MySQL.

Arjen: Что вам больше всего нравится в MySQL?

Marc: Скорость и стабильность.

Arjen: ха-ха, вы наслушались наш маркетинг?

Marc: Совсем нет! Скорость и стабильность это два основных фактора для меня.

Arjen: Относительно phpMyAdmin... как начался этот проект?

Marc: Прежде всего я обратил свое внимание на MySQL-Webadmin, но вскоре обнаружил phpMyAdmin, которому на тот мо-мент было всего три месяца. Но так как я преподавал франкоговоря-щим студентам в Квебеке, мне понадобилась французская версия.Тогда я обратился к Тобиасу Ратшиллеру (Tobias Ratschiller), основа-телю проекта, с просьбой поправить код для более легкой локализа-ции phpMyAdmin.

7

P

HP

In

side

#15

Л

ЮД

И

Сейчас мы знаем, чтонеобходимореализовывать новыевозможности MySQL 4.1и 5.0, но четкого плана унас нет

Интервью с одним из ведущих разработчиков phpMyAdmin Марком Делислом

После этого я написал небольшой французский перевод и студентам понравилосьэто приложение, они даже не воспринимали его как веб-приложение.

С 1998 до 2000 года phpMyAdmin был в первой фазе разработки (в 1998 появиласьпервая мультиязычная версия). Однако в августе 2000 Тобиас перестал уделять проектувремя и в марте 2001 года была сформирована новая команда и phpMyAdmin был переве-ден на портал sourceforge.net. Я присоеднинился к этой команде в 2001 году и начал ин-тенсивную работу над версией 2.2.0 в августе 2001.

Arjen: Кто сейчас вовлечен в разработку phpMyAdmin? Кто "возглавляет"проект сейчас?

Marc: Наша команда состоит из восьми человек, двое из кото-рых являются "администраторами проекта". Все мы волонтеры. В ко-манду входят следующие разработчики: Александр Турек (Герма-ния), Гарвин Хайкинг (Германия), Робин Джонсон (Канада), МихальЦихарь (Чехия), Михаель Кек (Германия), Марсель Чопп (Швейца-рия). Проект администрируют Оливер Мюллер (Швейцария) и я.

Arjen: Я полагаю, что у вас налажен процесс разработки(пусть и неформальный) согласно которому вы определяетепути развития проекта. Каким образом вы определяете какой функционал и когдадолжен быть реализован?

Marc: В последние несколько лет у нас был некоторый определенный заранееплан, к примеру, редизайн интерфейса к версии 2.6.0 или MIME-based трансформации.Но в 2005 году этот процесс стал более неформальным. Сейчас мы знаем, что необходи-мо реализовывать новые возможности MySQL 4.1 и 5.0, но четкого плана у нас нет.

Arjen: По вашему мнению, почему phpMyAdmin завоевал такую популяр-ность? Получается, что phpMyAdmin становится стандартом для веб-ориентиро-ванного администрирования MySQL и включается во все большее количество дис-трибутивов Linux, Novell NetWare и других.

Marc: Просто система делает свою работу и содержит некото-рые дополнения в виде визуализации полей blob при просмотре та-блиц или некоторые возможности PDF. Но я не могу сказать точно,за что phpMyAdmin любят люди - за его специальные возможностиили за способность выполнять повседневные задачи. Конечно, нема-ловажным фактом для пользователей MySQL остается возможностьадминистрировать СУБД через веб-интерфейс.

Я рад этому успеху, но он не вызывает у меня удивления, потому что мы прислу-шивались к сообществу и старались быстро исправлять важные ошибки. В 2002 году яудивлялся показателю: 10 скачиваний phpMyAdmin в минуту, но теперь воспринимаюэто как обычное дело.

И еще один важный момент: я был первым человеком, который начал перевод си-стемы на другие языки и вот сейчас мы имеем 50 переводов и еще один находится в ра-боте.

Arjen: Это здорово! А какой коэффициент скачивания программы сейчас? Яправильно понимаю, что этот показатель все равно не отражает полной картины,так как phpMyAdmin установлен на серверах многих хостинг-провайдеров?

Marc: Да, вы правы, это действительно так. Хостинг-провайдер или школа могутустановить систему один раз и с ней будут работать сотни пользователей и это толькочасть от всех инсталляций. В любом случае, в 2005 году мы достигли показателя 220 -320 тысяч скачиваний за месяц.

8

P

HP

In

side

#15

Л

ЮД

И

В 2002 году я удивлялсяпоказателю 10скачиваний phpMyAdminв минуту, но теперьвоспринимаю это какобычное дело

Я был первымчеловеком, которыйначал перевод системына другие языки

Интервью с одним из ведущих разработчиков phpMyAdmin Марком Делислом

Arjen: Ого! Впечатляющие цифры. Есть ли у вас какие либо особенные планыпо поводу будущего phpMyAdmin?

Marc: Чтож, мы будем придерживаться традиций и оставиминтерфейс более менее таким как он есть сейчас, но несомненно, хо-телось бы реализовать интерфейс для управления представлением.

Кто-то советует нам создать графический механизм конфигури-рования, но на это у нас просто нет человеческих ресурсов.

Arjen: Может быть кто-то из читателей данного интервью сможет взяться заэту работу! Возможно это ужасный вопрос, но сколько времени вы тратите на раз-работку phpMyAdmin в среднем за неделю?

Marc: Это ужасно только для моей жены :) Я трачу 7-10 часов в неделю. Правдапоследнее время стало исключением, так как я был занят написанием книги оphpMyAdmin на английском, а потом на французском языках, что конечно же делал заденьги. Книга была опубликована на четырех языках и вскоре выйдет на пятом. Она до-ступна на http://phpmyadmin.net.

Я полагаю, что эта книга добавит доверия к проекту в плане документации, так какволонтеры не очень-то любят писать 250-ти страничные руководства.

Arjen: Вы участвуете еще в каких либо Open Source проектах?

Marc: Нет, phpMyAdmin мое единственное детище :)

Arjen: Конечно за исключением четырех детей из реальной жизни ;-) Что бывы могли посоветовать пользователям, которые хотят писать код для phpMyAdminили других открытых проектов? Как им принять участие?

Marc: Мой совет... нашей команде нужны хорошие баг-репорты (отчеты об ошиб-ках) и это самый лучший способ принять участие. Еще нам нужны программисты, кото-рые самостоятельно смогут разбираться в исходном коде и присылать нам большие илималенькие патчи. Но тут не бывает волшебства и контрибъюторы проявляют большующедрость, даря свое время проекту.

Arjen: Какие нововведения вы хотели бы видеть в MySQL?

Marc: Это будет сюрпризом для вас, но я как разработчик phpMyAdmin очень хо-тел бы поменьше всяких нововведений в MySQL, потому как нам придется их реализовы-вать в phpMyAdmin :)

Arjen: Могу себе представить. Но есть ли что-то такое, чего вам действитель-но не хватает?

Marc: Кое что конечно кажется нелогичным, к примеру вывод запросов SHOWCREATE TABLE и SHOW FULL FIELDS, но мы пытаемся с этим справляться.

Arjen: Я полагаю, что INFORMATION_SCHEMA в MySQL 5.0 решит этипроблемы?

Marc: Да, но здесь необходимо учитывать, что мы должны поддерживать и старыеверсии, которые остануться повсюду!

Arjen: Правильно. Может ли MySQL AB что-то сделать для вас?

Marc: Как разработчик phpMyAdmin я бы сказал, что мне очень приятно входить вего команду и отвечать на вопросы официального представителя MySQL AB. Для многихпользователей phpMyAdmin остается единственным доступным административныминструментом для работы с MySQL. Однако на таких мероприятиях как Конференцияпользователей MySQL у меня сложилось ощущение, что phpMyAdmin не имеет никакогоотношения к MySQL AB. То же самое и в обучающих курсах от MySQL AB.

9

P

HP

In

side

#15

Л

ЮД

И

в 2005 году мы достиглипоказателя 220 - 320тысяч скачиваний замесяц

Интервью с одним из ведущих разработчиков phpMyAdmin Марком Делислом

Я мечтаю о том, чтобы на сайте MySQL были упоминания о том, что существуетвот такой веб-ориентированный продукт. Даже если это не продукт от MySQL AB. Делов том, что существует большой объем консалтинговой работы для многих веб-ориентиро-ванных проектов и я догадываюсь, что большинство этих проектов работает с MySQL.

Arjen: Это очень полезная обратная связь. Мы готовим обширное решение наэту тему.

Marc: И продолжайте приглашать нас на мероприятия, посвященные LAMP :)

Arjen: Насчет этого не беспокойтесь - мы будем продолжать делать это. А сей-час - спасибо за интервью.

10

P

HP

In

side

#15

Л

ЮД

И

Smarty — не просто шаблоны

Smarty — не просто шаблоныАвтор: Кузьма Феськов

Smarty может быть не просто шаблонизатором, а еще, своегорода фреймворком для разработки веб-приложений

Скажем сразу, этот материал не будет вас учить пользоваться базовыми воз-можностями данной библиотеки. Напротив, я копну гораздо глубже. Цель этого мате-риала взглянуть на шаблонизатор Smarty с другой стороны, и увидеть в нем не простоочень удобный и мощный шаблонный движок, а некий фреймворк для разработки вашихприложений.

Часто, говоря о Smarty, незаслуженно обвиняют его в низкой производительности и«тормознутости», что ж – автор данного материала с указанными товарищами не согла-сен. Напротив, раз уж мы приняли решение использовать в своем приложении эту биб-лиотеку, я предлагаю вам на полную катушку задействовать ее возможности, отдав наоткуп шаблонизатору как вывод информации пользователю, так и управление этой ин-формацией.

Компонентная модельОдна из сильных сторон Smarty – это возможность создавать свои плагины и

расширения. Воспользуемся этой его возможностью в полной мере и попробуем реализо-вать на ее основе компонентную модель сайта.

Что такое в нашем понимании компонент? Под компонентом я буду подразумеватьобособленный блок сайта, который умеет выполнять строго определенный набор дей-ствий и, в результате своей работы, либо выводить что-либо на экран, либо готовить ка-кие-то данные для других компонентов.

Компонент – это элемент сайта, который, во-первых, точно знает какие действия онможет совершать, во-вторых, какие библиотеки для совершения этих действий ему нуж-ны. В результате сайт будет состоять из ядра - набора библиотек (классов), которые со-держат в себе какие-то низкоуровневые действия, например работают с базой, – и компо-ненты, которые подключают эти библиотеки и, в нужном порядке, вызывают те или иныеих методы.

В чем положительная сторона такого подхода?

1. вы пишите специальные классы (объекты) ядра своего сайта, они никак не зависят отвывода на экран, а просто подготавливают и обрабатывают данные, тем самым обес-печивается высокая переносимость кода и возможность его повторного использова-ния;

2. в случае командной работы, вам не надо заботиться о том, что делает соседний про-граммист, который пишет свой компонент;

3. стандартизация кода – вы можете создать интерфейс компонента и строго следоватьего требованиям, что позволит одному программисту легко разобраться в компонентедругого программиста.

Это основные преимущества данного подхода.

11

P

HP

In

side

#15

И

ДЕИ

Smarty — не просто шаблоны

Общие классыБезусловно, в каждом приложении есть набор классов, которые нужны всем, или

большинству компонентов, например, класс для работы с базой. Как поступить в такомслучае? И для этой проблемы в Smarty есть удачное решение. Впрочем, давайте по поряд-ку.

Сначала инициализируем класс Smarty:<?php /** Путь до Smarty */ define('SMARTY_DIR', '/smarty/'); /** Путь до Smarty шаблонов */ define('TEMPLATES', '/templates/'); /** Путь до Smarty компилированных шаблонов */ define('TEMPLATES_C', '/templates_c/'); require_once(SMARTY_DIR . 'Smarty.class.php'); $smarty = new Smarty; $smarty->compile_check = TRUE; $smarty->force_compile = TRUE; $smarty->template_dir = TEMPLATES; $smarty->compile_dir = TEMPLATES_C; $smarty->plugins_dir[] = LIBS_PATH; $smarty->caching = FALSE; ?>

Итак, Smarty готов к работе. Что необходимо сделать с общими классами, чтобыобеспечить доступ к ним внутри любого компонента?

Скажем, у нас есть несколько общих компонентов:

1. adodb – класс для работы с базой;

2. session – класс для работы с сессиями;

3. errors – класс для обработки ошибок;

4. variables – класс для хранения и обработки состояния массивов $_GET и $_POST.

Первым делом, нам необходимо создать объекты данных классов (параметрыконструкторов зависят от вашей конкретной реализации). В целом, это делается стан-дартным образом:<?php require_once(CLASSES_DIR . '/variables.class.php'); $vars = new Variables(); require_once(CLASSES_DIR . '/errors.class.php'); $errors = new Errors($smarty); require_once(CLASSES_DIR . '/security.class.php'); $security = new Security($adodb); // и так далее... ?>

Объекты созданы и теперь необходимо обеспечить доступ к ним в любом компо-ненте нашего приложения.

12

P

HP

In

side

#15

И

ДЕИ

Smarty — не просто шаблоны

Для этого необходимо зарегистрировать данные объекты в Smarty:<?php $smarty->register_object('adodb', $adodb); $smarty->register_object('vars', $vars); $smarty->register_object('errors', $errors); $smarty->register_object('security', $security); ?>

Для регистрации объектов мы используем метод Smarty register_object(). Послечего ваш объект станет доступным везде, где он может понадобиться. Как «достать» нуж-ный вам зарегистрированный объект мы рассмотрим в следующей части.

Функция «Компонент»К текущему моменту Smarty ничего не знает о каких-либо компонентах, и нам нам

надо научить его работать с ними. Для этого мы добавляем к синтаксису шаблонов но-вый тег – {component}. Чтобы Smarty научился обрабатывать этот тег – пишем про-стую функцию:<?php // Smarty function Component // // @author Feskov Kuzma function smarty_function_component($params, &$smarty) { $adodb = &$smarty->get_registered_object('adodb'); $vars = &$smarty->get_registered_object('vars'); $errors = &$smarty->get_registered_object('errors'); $security = &$smarty->get_registered_object('security'); if (empty($params['name'])) { $params['name'] = 'site_view'; } if (is_file(ADMIN_LIBS_PATH . '/' . $params['name'] . '.component.php')) { require(ADMIN_LIBS_PATH . '/' . $params['name'] . '.component.php'); } else { echo 'Component <strong>' . $params['name'] . '</strong> not found'; } unset($adodb, $errors, $security, $vars); } ?>

Давайте разберемся, что делает данная функция. Во-первых, она создает обработ-чик для нового тега – {component}, во-вторых, достает (get_registered_object()) и делаетдоступными вызванному компоненту зарегистрированные ранее общие объекты.

Немножко теории. Чтобы вызвать данную функцию к жизни, необходимо в любомшаблоне написать тэг {component}. Поскольку функция не выполняет никаких продук-тивных действий, и служит исключительно диспетчером компонентов, просто написать{component} недостаточно, поскольку эта команда неинформативна. Конечно, функцияне даст сбоя, и запустит принятый по умолчанию компонент 'site_view'.

13

P

HP

In

side

#15

И

ДЕИ

Smarty — не просто шаблоны

Каким образом уточнить, какой именно компонент вам требуется и как передатьему дополнительные параметры? Все очень просто, мы несколько измени вызов компо-нента в шаблоне:{component name='имя требуемого компонента' var1='значение параметра'var2='значение другого параметра'}

И так далее, как вы понимаете, name, var1, var2 – это дополнительные параметрыдля нашего компонента. Name, например, указывает имя компонента, который мы хотимвызвать, а остальные параметры – это дополнительные данные для вызываемого компо-нента, их количество может быть любым, ровно как и их имена. После того, как в шабло-не встретится указанный выше тег, произойдет вызов нашей функции, которая, в своюочередь, вызовет нужный вам компонент. Все дополнительные параметры будут доступ-ны как в нашей функции так и в вызываемом компоненте, они будут содержаться в мас-сиве $params, где ключ – это название параметра, а значение – соответственно – его зна-чение.

Мы приняли, что файлы наших компонентов именуются следующим образом:name.component.php

где name – это наш параметр name.

Функция ищет в указанной папке файл с именем, сформированным указанным об-разом и исполняет его. В случае отсутствия параметра name запускает компонент, назна-ченный по умолчанию, в противном случае – выдает ошибку.

Помимо зарегистрированных ранее общих объектов, нашим компонентам полно-стью доступна вся мощь шаблонизатора Smarty – у вас есть объект $smarty. Обращаютакже внимание, что все что вы ассигните (assign) в объект $smarty, будет также доступ-но не только вашему компоненту, но и общему (вызывающему) шаблону, а это значит,что компоненты вовсе не обязаны всегда выводить что-либо на экран, они вполне могутпередавать подготовленные данные в общий шаблон, а он, в свою очередь, может пере-дать их другому компоненту, который на основе их может что-либо вывести на экран.

Дополнительным преимуществом такого подхода оказывается возможность моде-лирования сайта путем нехитрого изменения его шаблонов – то есть получается интерес-ная взаимосвязь дизайна и логики. Мы привыкли, что логика управляет выводом, а здесь,отчасти, вывод управляет логикой.

Также отмечу, что вложенность компонентов может быть бесконечной. То естькомпонент в своей работе может запустить какой-то свой шаблон, который, в свою оче-редь, может вызвать другой компонент.

КомпонентНастало время посмотреть, что же у нас представляет собой компонент. Компонент

выполняет роль диспетчера, он будет обрабатывать действия, которые вы ему определи-те, вызывая те или иные методы разных классов.

Разумеется, ваша реализация компонента может быть полностью отлична от моей –я приведу вам лишь иллюстрирующие примеры, поскольку целью данной статьи не яв-ляется написание какого-то рабочего приложения.

Давайте предположим, что наш компонент выводит новости на главную страницу.Новостей там может быть не более 5 за раз.

14

P

HP

In

side

#15

И

ДЕИ

Smarty — не просто шаблоны

В шаблоне напишем так:{component name='news' action='view' count=5 tpl='news_mainpage.tpl'}

Параметр name указывает на нужный нам компонент, action обозначает действие,которое требуется совершить, count – это фильтр количества новостей, и tpl – названиешаблона, который будет использован для формирования вывода новостей на экран.

Теперь давайте посмотрим, как мог бы выглядеть наш компонент:<?php // News component // // @author Feskov Kuzma // Подключаем необходимый нам класс // и создаем объект require_once(CLASSES_DIR . '/news.class.php'); $news = new News($adodb); // Обрабатываем возможные действия switch ($params['action']) { // --- View news --- case 'view': // Получаем 5 последних новостей $data = $news->NewsList($params['count']); if (false === $data) { // Выводим ошибку $errors->ComponentErrPrint('Компонент news, действие ' . $params['action'], $news->ERROR); } // Проверяем - есть ли такой шаблон if(is_file(TEMPLATES . '/' . $params['tpl'])) { // Выводим новости на экран $smarty->assign('data', $data); $smarty->display($params['tpl']); } else { // Выводим ошибку $errors->ComponentErrPrint('Компонент news, действие ' . $params['action'], 'Шаблон не найден'); } break; // --- Default action --- default: // Если никакого действия не задали, выводим ошибку $errors->ComponentErrPrint('news_view', 'Неизвестное действие'); break; } ?>

Этот пример показывает упрощенную схему работы компонента. Вы вполне може-те ее развить и изменить под свои нужды.

Количество действий, которые может выполнить компонент ограничено лишь ва-шей фантазией, ровно как и количество и названия параметров, которые вы можете пере-дать из шаблона в компонент.

15

P

HP

In

side

#15

И

ДЕИ

Smarty — не просто шаблоны

Обмен данными между компонентамиНемного остановлюсь на разделении компонентов на типы: prepare – эти компонен-

ты ничего не выводят на экран, они только подготавливают данные для других компо-нентов или общего (главного) шаблона, и view – эти компоненты обязательно в результа-те своей работы что-то выводят на экран.

Давайте посмотрим, каким образом компонент prepare может подготовить данныедля компонента view.<?php // --- Фрагмент компонента prepare --- $smarty->assign('prepare_data', $prepare_data); ?>

Из данного фрагмента видно, что компонент prepare создал какой-то набор данныхи ассигнул (assign) его в главный шаблон, присвоив этим данным имя 'prepare_data'.

Теперь давайте взглянем на главный шаблон:<!-- Фрагмент главного шаблона --> <!-- Вызываем компонент prepare --> {component name='prepare'} <!-- Вызываем компонент view --> {component name='view' prepare_data=$prepare_data}

Как видно из этого фрагмента, сначала мы вызвали компонент prepare, а затемкомпонент view. В качестве параметра передали в view продукт деятельности компонентаprepare.<?php // --- Фрагмент компонента view --- print_r($params['prepare_data']); ?>

В свою очередь, компоненту view эти данные стали доступны посредствам массива$params, в котором появился новый индекс – prepare_data.

ИтогиИтак, здесь мы с вами рассмотрели несколько необычную роль шаблонизатора

Smarty в разработке приложений: поручили Smarty быть не только удобным шаблониза-тором, но и диспетчером нашего приложения, отдали ему на откуп формирование сайта.

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

Компонентная модель разработки позволяет добиться существенного разграниче-ния труда программистов, работающих в команде.

На этом все, надеюсь этот материал даст вам повод для новых изысканий и идей.

16

P

HP

In

side

#15

И

ДЕИ

Принципы создания proxy-сервера на PHP в интрасети. Вопросы безопасности

Принципы создания proxy-сервера наPHP в интрасети. Вопросыбезопасности

Автор: Роман Толкачев

Организовывая Интрасеть, Интернет-провайдер подвергает себяопределённому риску, в случае, если сервер со страницами кли-ентов виден из Интернета и на страничках можно использоватьPHP

Это, прежде всего, не риск расставания с паролями доступа (хотя и такое воз-можно), а риск быть взломанным собственными пользователями. Хочется отметить,что всё сказанное ниже чистый вымысел, герои рассказа давно умерли и т.д., и т.п.

fopen(), include()…Уже много раз, в разговоре о безопасности PHP, упоминалась деректива

allow_url_fopen. При значении On (по-умолчанию), функции include(), fopen() и смежныеполучают возможность получать содержимое по протоколам HTTP, FTP и т.д. Что же этодаёт? Многие думают, что главной дырой, в этом случае, является исполнение удалённо-го кода, но они окажутся неправы. Рассмотрим пример:

В данном случае клиент (т.е. мы/наш браузер) имеет доступ к ресурсам ИнтраНетсервера, но не к http://www.somehost.com/, потому как не хотим платить много денег, исидим в Интрасети. В то же время, любой другой пользователь Интернет может просмат-ривать ИнтраНет ресурсы. Фактически сервер имеет доступ в Интернет. PHP скрипты ис-полняются на сервере, а это значит, что на них не действует ограничение зоны просмотрастраниц, в отличии от клиента. Вот это, как раз, и позволяет абонентам сети использоватьPHP в корыстных целях. Теперь к конкретному примеру:<? $html = implode('', file('http://' . $_GET["site"])); echo $html; ?>

17

P

HP

In

side

#15

И

ДЕИ

Принципы создания proxy-сервера на PHP в интрасети. Вопросы безопасности

Если запустить http://www.mysite.prov.ru/test.php?site=somehost.com/, то мы полу-чим всё содержимое главной страницы http://somehost.com/, даже если находимся в пре-делах ИнтраСети.

Разумеется, наш скрипт должен быть на ИнтраНет HTTP сервере. Такой же меха-низм может быть приспособлен и для получения файлов (т.е. нетарифицированного ска-чивания из интернета). Решение данной проблемы состоит в отключении allow_url_fopenв файле php.ini (установка значения в off).

сURLРассмотрим второй вариант. Если провайдер достаточно умён, чтобы отключить

данную дериктиву, но в то же время не так умен для проверки всех устанавливаемыхрасширений. Итак, он всё же устанавливает cURL. Объясняю что это такое.

Это расширение позволяет совершать запросы к HTTP серверам. Много интерес-ных особенностей у данного расширения, с которыми вы можете познакомиться в офици-альном мануале. И опять существует возможность связываться с удалённым сервером че-рез ИнтраНет HTTP сервер, причём это работать будет быстрее. Аналогичный пример:<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $_GET["site"]); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec($ch); curl_close($ch); ?>

Использовать так же. Устранить данную уязвимость можно лишь удалениемрасширения cURL. Самые «трудолюбивые» могут пойти дальше и сделать прокси-сервер,который будет перенаправлять запросы браузера на скрипты. Но это, как говорится, ужесовсем другая история.

18

P

HP

In

side

#15

И

ДЕИ

HOWTO по оптимизации PHP

HOWTO по оптимизации PHPАвтор: Джон Лим (John Lim)Перевод: Кузьма Феськов

PHP очень быстрый язык программирования, но есть еще мно-жество способов оптимизации, помимо оптимизации кода

В этом материале мы объясним, почему оптимизация PHP захватывает собой го-раздо больше факторов, нежели простая оптимизация кода, и почему настройка PHPтребует понимания, каким образом работает PHP относительно других компонентоввашего сервера. Также мы займемся выявлением узких мест, связанных с этими компо-нентами и устранением их. Также мы затронем вопросы оптимизации ваших PHPскриптов, чтобы они работали еще быстрее.

Оригинал статьи здесь: http://phplens.com/lens/php-book/optimizing-debugging-php.php

Достижение высокой производительностиКогда мы говорим о хорошей производительности, мы не говорим о том, насколько

быстро ваши скрипты будут запускаться. Производительность – это набор компромисовмежду масштабируемостью и скоростью. Скрипты, настроенные, чтобы использоватьминимум ресурсов, могут быть медленнее, чем скрипты, использующие кэширование,потомучто больше копий одного и того же скрипта может быть запущено одновременнона одном сервере.

В примере ниже, A.php – спринтер – настроен для быстрого запуска, а B.php – бе-гун марафона – может бегать трусцой, почти с той же самой скоростью. При низкой за-грузке, A.php существенно быстрее, но как только трафик начинает увеличиваться, рабо-та B.php снижается лишь немного, тогда как A.php выдыхается.

19

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Давайте возьмем более реалистичный пример для дальнейших рассуждений. Пред-положим, нам необходимо написать скрипт, который должен прочитать файл размером250 кб и сгенерировать HTML, резюмирующий информацию из файла. Мы пишем двасценария, которые делают одно и тоже: hare.php, который читает файл в память целикоми обрабатывает его за один проход, и tortoise.php, который читает файл построчно несохраняя в памяти информации, больше чем одна строка. Tortoise.php будет медленнее,потому что использует многократное чтение, требует большего количества системныхвызовов.

Hare.php требует 0.04 секунды центрального процессора, а также 10 мб памяти.Tortoise.php требует 0.06 секунд процессорного времени и 5 мб памяти. Сервер распола-гает 100 мб свободной памяти и процессор на 99% свободен. Предположим, что никакойфрагментации памяти не происходит (для упрощения).

При 10 одновременных запусках скрипта, hare.php исчерпает память (10 х от 10 до100). В этой точке, tortoise.php все еще будет иметь в своем распоряжении 50 мб свобод-ной памяти. 11 запуск hare.php приведет к уменьшению производительности, посколькусистема начнет использовать виртуальную память. При этом, его первоначальная ско-рость может упасть более чем в половину. Каждый запуск hare.php на данный момент за-нимает 0.08 секунд процессорного времени. Тем временем tortoise.php все также будетзанимать свое процессорное время – 0.06 секунд.

В таблице ниже, самый быстрый сценарий выделен полужирным:

Соединения CPU-секунды призапуске одного

скрипта

CPU-секунды призапуске десяти

скриптов

CPU-секунды при запускеодиннадцати скриптов

Hare.php 0.04 0.40 0.88 (Свободная памятьзакончилась)

Tortoise.php 0.06 0.60 0.66

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

Узкие местаПример hare и tortoise (зайца и черепахи) показал нам причины узких мест. С бес-

конечной оперативной памятью hare будет быстрее всегда, чем tortoise. К сожалению,вышеупомянутая модель слишком упрощена, и есть еще много других узких мест, пре-пятствующих работе, помимо оперативной памяти:

СетьВаша сеть, вероятно, самое узкое место. Например, вы говорите, что у вас 10 Мбит

связь с интернетом, по которой вы можете скачать 1 мб данных в секунду. Если каждаястраница у вас занимает 33 кб, то обычные 33 страницы в секунду будут занимать весьваш канал.

Более тонкие узкие места в сети – это скорость отклика, например, сервера имен(DNS), или адресация нужного количества памяти для программного обеспечения сети.

20

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Центральный процессорЕсли вы контролируете загрузку центрального процессора, то увидите, что пере-

сылка обычных HTML страниц вообще не будет обременять процессор, и, в данном слу-чае, самым узким местом будет сеть. Однако, для сложных динамических web-страниц,производимых PHP, скорость вашего процессора будет ограничивающим фактором. На-личие нескольких процессоров или фермы серверов может значительно снизить подоб-ное ограничение.

Shared Memory (общедоступная память)Общедоступная память используется для связи между процессами, и хранит ресур-

сы, которые делятся между несколькими процессами, типа кэшированных данных и кода.Если общей памяти недостаточно, то любая попытка обратиться к ресурсам, использую-щим общую память, например, соединение с базой данных, или запуск кода, вызоветошибку.

Файловая системаДоступ к жесткому диску может быть в 50-100 раз медленнее, чем доступ к данным

в оперативной памяти. Кэширование файлов с использованием оперативной памяти мо-гут снизить данное ограничение. Однако, в условиях небольшого количества памяти длясистемного кэша, работа будет замедляться. Системные файлы так же могут быть сильнофрагментированными, замедляя дисковый доступ. Частое использование симлинков наUNIX системах также приводят к замедлению.

Также печально известны установки поумолчанию для доступа к диску в Linux си-стемах, которые настроены для совместимости, а не для скорости. Используйте командуhdperm, чтобы перенастроить параметры диска вашей Linux системы.

Управление процессамиВ некоторых операционных системах, например, в Windows, создание нового про-

цесса – это медленная операция. Это означает, что CGI процесс, вызываемый для каждойоперации, будет работать значительно медленнее. Запуск PHP в multi-threaded (в виде мо-дуля) режиме должно увеличить скорость ответа (примечание: старые версии PHP неу-стойчивы в данном режиме).

Избегайте переполнения вашего сервера множеством ненужных процессов. Напри-мер, если ваш сервер предназначен только для обслуживания сети, избегайте запуска(или даже вообще установки) X-Windows. На Windows-системах избегайте запускаMicrosoft Find Fast (компонент офиса), а также всякого рода screensaver'ов. Потомучтовсе это заканчивается 100% использованием процессора.

Некоторые программы вы можете рассмотреть к удалению, включая неиспользуе-мые сетевые протоколы, серверы почты, сканеры антивирусов, аппаратные драйверы длямыши, инфракрасного порта и так далее. На Unix: я подразумеваю, что вы общаетесь сосвоим сервером посредствам SSH. В этом случае, вы можете рассмотреть к удалениюследующее:

• демоны, например, telnetd, inetd, atd, ftpd, lpd, sambad

• sendmail для поступающей почты

• portmap для NFS

• xfs, fvwm, xinit, X

Также вы можете отключить запуск некоторых программ при загрузке, изменяяфайлы запуска, которые обычно хранятся в /etc/init* или /etc/rc*/init* директории.

21

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Также рассмотрите задачи, которые запускаются по крону. Посмотрите, можно лиих удалить или перенести на непиковые периоды.

Соединение с другими серверамиЕсли ваш сервер требует услуг, выполняющихся на других серверах, это тоже мо-

жет стать узким местом. Самый общий пример – это медленный сервер базы данных, ко-торый обслуживает много сложных SQL запросов от разных серверов сети.

Когда начинать оптимизацию?Многие говорят, что оптимизацию лучше отложить до тех пор, пока кодирование

не будет закончено. Этот совет имеет смысл, только если вша группа программистов вы-дает код очень высокого качества и вы уже имеете хорошее чувство рабочих параметроввашего приложения. Иначе вы подвергаете себя риску необходимости переписывать су-щественные части приложения после проведения испытаний.

Мой совет – преже чем начинать проектирование приложения, сделайте некоторыеосновные эталонные тесты аппаратных средств и программного обеспечения, чтобы по-лучить чувство максимальной работоспособности, которую вы могли бы достигнуть. То-гда, когда вы проектируете и кодируете приложение, держите желательные рабочие па-раметры в памяти, потому что на каждом этапе пути вам придется идти на компромиссымежду производительностью, функциональностью, защитой и гибкостью.

Также выберите хорошие испытательные данные. Если ваша база данных, как ожи-дается, будет хранить только 100 000 записей, избегайте тестирования ее только со 100записями, вы будете потом об этом сожалеть. Это когда-то случилось с одним из про-граммистов в моей компании: мы обнаружили медленный код значительно позже, потра-тив много времени впустую, поскольку пришлось переписать большую часть кода, кото-рый работал, но не масштабировался.

Настройка вашего сервера для PHPДалее, мы рассмотрим с вами, как оптимизировать работу с PHP двух самых рас-

пространенных web-серверов, Apache 1.3 и IIS.

Разработчики PHP заявляют, что нет никакой разницы в скорости и преимуществахмасштабирования при использовании Apache 2.0 над Apache 1.3, особенно, если PHPустановлен в виде модуля.

Apache 1.3/2.0Этот сервер доступен на Unix и Windows платформах, это самый популярный сер-

вер в мире. Apache 1.3 использует pre-forking (предразветвления) модель для обслужива-ния сети. После старта, сервер создает дочерние процессы для обслуживания каждогоHTTP запроса. Родительский процесс действует как ангел-хранитель, проверяя, что вседочерние процессы работают правильно и координирует их действия. Чем больше HTTPзапросов, тем больше дочерних процессов будет порождено, чтобы их обработать. По-скольку HTTP запросы начнут замедляться, родительский процесс уничтожает неактив-ные дочерние процессы, освобождая ресурсы для новых процессов. Красота данного под-хода в том, что это делает Apache чрезвычайно устойчивым. Даже если дочерний процессрушится, родительский и другие дочерние процессы будут изолированы от сбойного до-чернего процесса.

22

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Модель предразветвления не настолько быстра, как другие решения. Но, что каса-ется меня, то это является «суматохой ни о чем», на сервере, обслуживающем PHP сцена-рии, потомучто другие узкие места дадут сбой раньше, чем проблемы Apache станут су-щественными для сервера. Ошибкоустойчивость и надежность Apache более важныйфактор.

Apache 2.0 может работать в модульном режиме (multi-threaded). Мои эталонныетесты показали, что преимуществ этого режима не так уж много. Также будте готовы ктому, PHP расширения несовместимы, например GD и IMAP. Проверено на Apache 2.0.47(23 октября 2003).

Apcahe сконфигурирован при помощи файла httpd.conf. Следующие параметрыособенно важны при настройке дочерних процессов:

Параметр По умолчанию ОписаниеMaxClients 256 Максимальное число дочерних процессов, которые

может создать сервер. Значение поумолчанию 256означает, что одновременно может быть обработано256 HTTP запросов. Любые дальнейшие запросыбудут поставлены в очередь.

StartServers 5 Количество дочерних процессов, которые будутсозданы сразу после старта сервера.

MinSpareServers 5 Число неактивных дочерних процессов, которыедолжны быть созданы. Если число неактивныхпроцессов падает ниже этого числа, то 1 ребеноксоздается первоначально, 2 на следующую секунду, 4еще через секунду, и так далее, пока не будет создано32 дочерних процесса с интервалом в секунду.

MaxSpareServers 10 Если создано больше, чем данное число дочернихпроцессов, то эти дополнительные процессы будутостановлены.

MaxRequestsPerChild 0 Устанавливает какое число HTTP запросов ребенокдолжен обработать перед завершением. Если выустанавливаете ее в 0, то дочерний процесс никогдане умирает. Установите его в пределах от 100 до10000, если вы подозреваете утечки памяти илинеправильно использование ресурсов.

Для больших сайтов наилучшими значениями будут близкие к этим:

• MinSpareServers 32

• MaxSpareServers 64

Apache под Windows ведет себя иначе. Вместо того, чтобы использовать дочерниепроцессы, Apache использует треды. Вышеупомянутые параметры не используются. Вме-сто этого мы имеем один параметр: ThreadsPerChild который имеет значение поумолча-нию – 50. эта переменная указывает число тредов, которые могут быть порожденыApache.

Поскольку в Winodws есть только один дочерний процесс, то количество HTTPзапросов, которые он может обработать, равняется 50. Для серверов сети, которые испы-тывают более серьезные нагрузки, увеличьте этот параметр от 256 до 1024.

23

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Другие полезные параметры, которые вы можете изменить приведены ниже:

Параметр По умолчанию ОписаниеSendBufferSize Определяется

операционнойсистемой

Определяет объем буфера вывода (в байтах),используемого в TCP/IP соединениях. Этот параметрпрежде всего полезен для переполненных илимедленных сетей, когда пакеты необходимобуферизировать. В этом случае, установите этотпараметр близким к размеру самого большогопересылаемого файла. Один TCP/IP буфер будет созданпри соединении.

KeepAlive (on/off) on В оригинале HTTP спецификации, каждый HTTPзапрос должен создавать новое соединение с сервером.Keep-alive заголовок был создан, чтобы уменьшитьнагрузку на сервер. Параметр keep-alive говоритсерверу, чтобы он использовал тоже самое соединениечерез socket (сокет) для нескольких HTTP запросов.

Если у вас есть отдельные сервер, которыйобслуживает все изображения (images), то вы можетевыключить этот параметр. Подобная техника поможетзначительно сэкономить ресурсы сервера.

KeepAliveTimeOut 15 Количество секунд для удержания сокет-соединения.Это время включает в себя генерацию контента и ответклиента. Если клиент не реагирует в течение этоговремени – будет создано новое соединение.

Это значение не должно быть большим, иначе сокетбудет простаивать в этот период.

MaxKeepAliveRequests 100 Сокет-соединения будут закончены, как только ихколичество достигнет этой цифры. Установите большоезначение, но меньше MaxClients или ThreadsPerChild.

TimeOut 300 Отсоединиться, если время простоя превышает эточисло. Вы можете установить меньшее значение, есливаши клиенты имеют небольшую задержку.

LimitRequestBody 0 Максимальный размер PUT или POST. 0 – нет лимита.

Если вы не требуете DNS поиска и не используете htaccess для настройки отдель-ных директорий в Apache, вы можете задать:# выключить DNS поиск: PHP скрипты получают только IP адресHostnameLookups off# отключить проверку htaccess<Directory />AllowOverride none</Directory>

24

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Если вас не волнует безопасность папок при вызове симлинков, включитеFollowSymLinks и выключите SymLinksIfOwnerMatch, чтобы предотвратить дополни-тельный системный вызов lstat():Options FollowSymLinks#Options SymLinksIfOwnerMatch

Настройка IISНастройка производительности исходя изобращений к серверу в день.

Определяет, какое количество памяти отвестидля IIS. (Performance Tab).

Управление полосой пропуска Управляет полосой пропуска в секунду,разделенную по серверам. (Performance Tab).

Управление процессом Управляет процентом процессорного времени,доступного для процесса по серверам.(Performance Tab).

Таймаут По умолчанию – 900 секунд. Установите болеенизкое значение, если у вас локальная сеть. (WebSite Tab)

HTTP компрессия В IIS 5 вы можете сжимать динамическиестраницы, HTML и картинки. Вы можетенастроить эти параметры. Значение поумолчанию – выключено.

HTTP сжатие нужно включать для всего сервера.Чтобы включить этот параметр – нажмитеправую кнопку мыши на консоли сервера (не наодном из подсайтов), выберите Свойства(Properties). Нажмите на Вкладке Service, затемвыберите Compress application files длякомпрессии динамических данных, и Compressstatic files — для компрессии статическогоконтента.

Также вы можете изменить, настроенный поумолчанию, уровень изоляции web-сервера. Во вкладке Home Directory в Application Protection вы можете определить уро-вень изоляции. На высшем уровне изоляции ваш сайт будет работать медленнее, потому-что это будет отдельный процесс от IIS, вто время как запуск сайта в IIS процессе – самаявысока скорость, но сервер может «лечь», если в вашем скрипте есть серьезные ошибки.На данный момент я рекомендую запускать PHP сайты как CGI или с использованиемISAPI совместно с Application Protection установленной в hight (высокая).

Вы также можете использовать regedit.exe для изменения параметров IIS 5, сохра-ненных в ветке HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesInetinfoParameters.

MemCacheSize Устанавливает количество памяти, которую IISбудет использовать для кэширования своихфайлов. Поумолчанию, ISS может использовать50% установленной в компьютере памяти. Выможете увеличить этот параметр, если на машинеработает только IIS. Значение задается вмегабайтах.

25

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

MemCachedFileSize Определяет максимальный размер файла,который может быть кэширован. Размеруказывается в байтах. Значение поумолчанию –262,144 (256 кб).

ObjectCacheTTL Устанавливает время (в миллисекундах), втечение которого кэшированный объектсохраняется в памяти. Значение поумолчанию –30,000 миллисекунд (30 секунд).

MaxPoolThreads Устанавливает число нитей на процессор.Определяет, сколько CGI приложений можетбыть запущено одновременно. Значениепоумолчанию – 4. увеличьте это значение, есливы используете PHP как CGI.

ListenBackLog Максимальное количество активных живыхсоединений (Keep alive), которые ISSподдерживает в очереди соединений. Значениепоумолчанию – 15, должно быть увеличено кчислу одновременных соединений,поддерживаемых вашим сервером. Максимально– 255.

Если эти параметры отсутствуют в данной ветке реестра – будут использоватьсяпараметры поумолчанию.

Высокая производительность в Windows: IIS и FastCGIПосле большого тестирования, я считаю, что самая высокая производительность

PHP в Windows достигается использованием IIS с FastCGI. CGI – это протокол для вызо-ва внешней программы из сервера. Это дает не самую высокую скорость, потому что CGIпрограмма удаляется каждый раз после создания страницы. FastCGI изменяет этот прото-кол для достижения более высокой производительности, заставляя CGI программу оста-ваться запущенной после обработки запроса, и многократно использоваться для обра-ботки последующих запросов.

Поскольку установка FastCGI на IIS достаточно сложна, вы должны использоватьEasyWindows PHP Installer (http://phplens.com/phpeverywhere/easywindows). Он установитPHP, FastCGI и Turck MMCache для достижения лучшей производительности. Этотинсталлер также может установить PHP для Apache 1.3/2.0.

PHP 4 и Zend EngineZend Engine – это внутренний компи-

лятор и движок, использованный для созда-ния PHP 4. Созданный Zeev Suranski и AndiGutmn, Zend Engine – это сокращение от ихимен. На начальном этапе – PHP работалследующим образом:

26

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

PHP скрипт загружается в Zend Engine и компилируется в opcode. Opcode – это на-бор низкоуровневых бинарных инструкций. После запуска opcode происходит генерацияHTML и передача его клиенту. Opcode удаляется из памяти после выполнения.

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

PHP скрипт загружается в Zend Engine и компилируется в opcode. Opcode можетбыть оптимизирован с использованием необязательного оптимизатора, названного ZendOptimizer. В зависимости от скрипта, он может увеличить скорость выполнения PHPскрипта до 50%.

Раньше, после выполнения, opcode уничтожался. Теперь вы можете организоватьего кэширование, используя несколько альтернативных вариантов: продукты с открытымкодом и Zend Accelerator (раньше известен как Zend Cache), который является закрытымкоммерческим продуктом. Только кэшированный opcode совместим с Zend Optimizer иZend Accelerator. Opcode кэш ускоряет выполнение, удаляя из цепочки загрузку исходно-го скрипта и его компиляцию. Время выполнения, с использованием кэширования, можетулучшиться от 10 до 200%.

Где искать инструменты для кэширования opcode?

Zend Accelerator. Это коммерческий продукт, развитый командой Zend Engine. Оченьнадежный. Искать здесь: http://zend.com.

Вы обязательно должны протестировать программы с открытыми кодами, преждечем начинать их использовать, поскольку их работа и надежность очень зависит отзапускаемых PHP скриптов.

Turck MMCache – (http://turck-mmcache.sourceforge.net/) больше не поддерживается.Смотрите eAccelerator, который является развитием mmcache и активно развивается.

27

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Alternative PHP Cache – http://apc.communityconnect.com/.

PHP Accelerator – http://www.php-accelerator.co.uk/.

AfterBurner Cache – http://www.bwcache.bware.it/.

Один из секретов высокой производительности состоит не в том, чтобы написатьбыстрый PHP код, а в том, чтобы кэшировать результаты выполнения скрипта в файл илиобщую память. Скрипт запускается однажды, генерируемый HTML захватывается и всепоследующие обращения к скрипту приводят к показу уже готового HTML. Если требу-ется регулярное обновление данных, то необходимо указать срок жизни для кэширован-ных HTML. Кэширование HTML – это не часть PHP языка или Zend Engine – но осуще-ствляется при помощи PHP кода. Существует много классов и библиотек для организа-ции подобного. Одна из них – PEAR Cache, о которой мы поговорим в следующей части.Другой распространенный способ – библиотека Smarty.

И, наконец, HTML, отдаваемый браузеру клиента, может быть сжат. Это включает-ся добавлением следующего кода вначале вашего скрипта:<?php ob_start("ob_gzhandler"); ::: ::: ?>

Если ваш HTML очень сжимаем, то это может уменьшить размер на 50-80%, сокра-щая тем самым требования пропускного канала. Другая сторона – это необходимость вболее мощном процессоре, чтобы эффективно и быстро сжимать страницы.

HTML кэширование с использованием PEAR CachePEAR Cache – это набор классов для кэширования разнообразных типов данных,

включая HTML и картинки.

Самое распространенное использование PEAR Cache – это кэширование HTMLтекста. Чтобы использовать кэширование – задействуем Output buffering class, с кэширо-ванием всего выдаваемого текста между функциями start() и end():<?php require_once("Cache/Output.php"); $cache = new Cache_Output("file", array("cache_dir" => "cache/") ); if ($contents = $cache->start(md5("это уникальный ключ!"))) { # # Возвращаем кэшированные данные # print $contents; print "<p>Кэшированные данные</p>"; } else { # # Кэшированных данных нет, либо срок их жизни истек # print "<p>Не покидайте дом без этого:</p>"; # помещаем в кэш print "<p>Stand and deliver</p>"; # помещаем в кэш print $cache->end(10); } ?>

28

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

С тех пор, как я написал эти строки, была создана более продвинутая система кэширо-вания PEAR: Cache Lite (http://pear.php.net/package/Cache_Lite); чтобы узнать об этомподробнее, смотрите memcached (http://www.danga.com/memcached/).

Cache конструктор принимает первым параметром тип драйвера для сохранения кэ-ша. Доступны следующие драйверы: файл, база данных, общая память (смотрите папку:pear/Cache/Container). Тесты Ulf Wendel показывают, что драйвер «файл» дает наилуч-шую производительность. Второй параметр – это параметры для используемого драйве-ра. Варианты: cache_dir – это папка для сохранения кэшированных данных,filename_prefix – уникальная приставка к названию файлов для сохранения кэширован-ных данных. Что странно, время жизни кэша не является параметром для конструктора.

Для кэширования каких-то данных, вам необходимо сгенерировать уникальныйключ (id) для этих данных. В примере выше, мы использовали md5("это уникальныйключ!").

Функция start() использует ключ для поиска кэшированной копии данных. Есликонтент не был кэширован, функция вернет пустую строку. И все последующие echo иprint будут буферизироваться в кэш, до тех пор, пока не встретится функция end().

Функция end() возвращает содержимое буфера и заканчивает буферизацию вывода.Функция end() принимает в качестве первого параметра время жизни кэша. Этим пара-метром могут быть секунды или Unix таймштамп, указывающий точное время окончанияжизни кэша, или 0 – установит интервал по умолчанию – 24 часа.

Другой способ использования PEAR Cache – это сохранение значения переменныхили других данных. Для реализации этого – используйте основной Cache класс:<?php require_once("Cache.php"); $cache = new Cache("file", array("cache_dir" => "cache/") ); $id = $cache->generateID("'это уникальный ключ"); if ($data = $cache->get($id)) { print "Кэшированные данные.<br>Дата: $data"; } else { $data = "Количество памяти достаточное..."; $cache->save($id, $data, $expires = 60); print "Кэш потерян.<br>"; } ?>

Для сохранения используемых данных применяйте функцию save(). Если выбран-ный вами уникальный ключ уже существует, вы можете использовать функциюgenerateID(). Объекты и массивы могут быть сохранены благодаря использованию функ-ции serialize() внутри функции save().

Последний параметр – это время жизни кэша. Этим параметром могут быть секун-ды или Unix таймштамп, указывающий точное время окончания жизни кэша, или 0 –установит интервал по умолчанию – 24 часа. Для получения кэшированных данных ис-пользуйте функцию get().

29

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Использование тестов производительностиВыше мы свами затронули много проблем и моментов касающихся производитель-

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

Если вы хотите получить наиболее реалистичные тесты производительности веб-сервера, вам необходим инструмент, умеющий посылать разнообразные HTTP запросы.На Unix обычные инструментальные средства тестирования включают ab (сокращение отapachebench), который являются частью пакета Apache. И более нового flood(http://httpd.apache.org/test/flood). На Windows NT/2000 вы можете использоватьMicrosoft's free Web Application Stress Tool (http://webtool.rte.microsoft.com).

Эти утилиты могут делать параллельные множественные HTTP запросы моделируятем самым множество клиентов сети, и выдавать вам детальную статистику по заверше-нию теста.

Вы можете контролировать, каким образом ведет себя ваш сервер, поскольку тестыпроводятся на основе Unix с использованием "vmstat1". Он печатает информацию о ста-тусе вашего диска, виртуальной памяти, и загрузки процессора каждую секунду. Альтер-нативно вы можете использовать "top d 1" который дает вам полноэкранную индикациювсех процессов запущенных и сортированных по степени загрузки процессора каждуюсекунду.

На Windows 2000 вы можете использовать Performance Monitor или Task Managerдля просмотра статистики своей системы.

Если вы хотите проверить специфический аспект вашего кода без необходимостииспользования HTTP запросов, вы можете написать тест с использованием функцииmicrotime(), которая возвращает текущее время в микросекундах в виде строки. Следую-щая функции конвертирует это значение в число, подходящее для статистики:<?php function getmicrotime() { list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); } $time = getmicrotime(); # # Здесь тестируемый код # echo "

Время прошло: " . getmicrotime() - $time . " секунд"; ?>

Альтернативно, вы можете использовать специальные инструменты для профели-рования: APD (http://www.linuxjournal.com/article.php?sid=7213) или Xdebug(http://xdebug.derickrethans.nl/). Еще вы можете прочитать специальную статью на этутему: http://phplens.com/phpeverywhere/node/view/52.

30

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Этапы тестирования производительностиДалее, я привожу детали реального теста производительности, созданного для од-

ного из клиентов. В данном случае, клиент хотел гарантированное время отклика 5 се-кунд для любой PHP страницы, которая не делала сложных SQL запросов. Конфигурациясервера: Apache 1.3.20, PHP 4.0.6 на Red Hat 7.2 Linux. Аппаратное обеспечение: дваPentium III 933 Mhz, 1Gb RAM. HTTP запросы будут обращаться к скрипту testmysql.php.Этот скрипт читает и обрабатывает примерно 20 записей из MySql базы данных, располо-женной на другом сервере. Для простоты мы предполагаем, что вся графика грузится сдругого сервера.

Как инструмент для тестирования производительности мы использовали ab. Мы за-дали ab делать 1000 запросов (-n1000), используя 10 одновременных соединений (-c10).Вот результаты:# ab -n1000 -c10 http://192.168.0.99/php/testmysql.phpThis is ApacheBench, Version 1.3Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/Server Software: Apache/1.3.20Server Hostname: 192.168.0.99Server Port: 80Document Path: /php/testmysql.phpDocument Length: 25970 bytesConcurrency Level: 10Time taken for tests: 128.672 secondsComplete requests: 1000Failed requests: 0Total transferred: 26382000 bytesHTML transferred: 25970000 bytesRequests per second: 7.77Transfer rate: 205.03 kb/s receivedConnnection Times (ms) min avg maxConnect: 0 9 114Processing: 698 1274 2071Total: 698 1283 2185

После запуска теста производительности, он начал контролировать на стороне сер-вера использование ресурсов с использованием команды "top d 1". Параметр "d 1" указы-вает, что необходимо делать задержку в 1 секунду перед обновлением данных. Вывод по-казан ниже.10:58pm up 3:36, 2 users, load average: 9.07, 3.29, 1.7974 processes: 63 sleeping, 11 running, 0 zombie, 0 stoppedCPU0 states: 92.0% user, 7.0% system, 0.0% nice, 0.0% idleCPU1 states: 95.0% user, 4.0% system, 0.0% nice, 0.0% idleMem: 1028484K av, 230324K used, 798160K free, 64K shrd, 27196K buffSwap: 2040244K av, 0K used, 2040244K free 30360K cached PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND 1142 apache 20 0 7280 7280 3780 R 21.2 0.7 0:20 httpd 1154 apache 17 0 8044 8044 3788 S 19.3 0.7 0:20 httpd 1155 apache 20 0 8052 8052 3796 R 19.3 0.7 0:20 httpd 1141 apache 15 0 6764 6764 3780 S 14.7 0.6 0:20 httpd 1174 apache 14 0 6848 6848 3788 S 12.9 0.6 0:20 httpd 1178 apache 13 0 6864 6864 3804 S 12.9 0.6 0:19 httpd 1157 apache 15 0 7536 7536 3788 R 11.0 0.7 0:19 httpd

31

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

1159 apache 15 0 7540 7540 3788 R 11.0 0.7 0:19 httpd 1148 apache 11 0 6672 6672 3784 S 10.1 0.6 0:20 httpd 1158 apache 14 0 7400 7400 3788 R 10.1 0.7 0:19 httpd 1163 apache 20 0 7540 7540 3788 R 10.1 0.7 0:19 httpd 1169 apache 12 0 6856 6856 3796 S 10.1 0.6 0:20 httpd 1176 apache 16 0 8052 8052 3796 R 10.1 0.7 0:19 httpd 1171 apache 15 0 7984 7984 3780 S 9.2 0.7 0:18 httpd 1170 apache 16 0 7204 7204 3796 R 6.4 0.7 0:20 httpd 1168 apache 10 0 6856 6856 3796 S 4.6 0.6 0:20 httpd 1377 natsoft 11 0 1104 1104 856 R 2.7 0.1 0:02 top 1152 apache 9 0 6752 6752 3788 S 1.8 0.6 0:20 httpd 1167 apache 9 0 6848 6848 3788 S 0.9 0.6 0:19 httpd 1 root 8 0 520 520 452 S 0.0 0.0 0:04 init 2 root 9 0 0 0 0 SW 0.0 0.0 0:00 keventd

Посмотрите на «шапку» вывода. Результаты показывают, что Apache, на машине сдвумя процессорами, отработал с 0% простоя. Это очень плохо. Средняя загрузка соста-вила 9.07 за последнюю минуту (3.29 за последние 5 минут, 1.79 за последние 15 минут).Средняя загрузка – это среднее число процессов, готовых быть запущенными. Для двух-процессорного сервера любая загрузка больше 2, означает, что система будет перегруже-на процессами. Здесь вы можете видеть тесную связь между загруженностью 9.07 и коли-чеством запущенных процессов (10), которые были определены в тесте ab.

К счастью, мы располагаем большим объемом свободной оперативной памяти,приблизительно 798 160 Мб, никакой виртуальной памяти не используется.

Далее, внизу, мы можем видет процессы, упорядоченные по количеству использо-вания центрального процессора. Самые активные – это процессы Apache (httpd). Перваязадача httpd использует 7280 Кб памяти и отнимет в среднем 21.2% процессора, и 0.7%оперативной памяти. Колонка STAT показывает статус: R – работает, S – бездействует,W – означает, что процесс выгружен из памяти.

Вышеприведенные цифры показывают нам типичную пиковую нагрузку, мы мо-жем сделать некоторое планирование. Если среднее число загрузки для сервера с двумяпроцессорами 9.0, и задача отнимает для исполнения примерно одно и тоже время, тослегка загруженный сервер должен быть 9.0/2 процессора = в 4.5 раз более быстрым. Такчто HTTP запрос, который обыкновенно занимал 1.283 секунды, при пиковой нагрузкезаймет примерно 1.283/4.5 = 0.285 секунд.

Для проверки этого, мы делаем тест производительности с 2 одновременными про-цессами (вместо 10 выше). Получаем 0.281 секунды, что очень близко к предсказанномузначению 0.285!# ab -n100 -c2 http://192.168.0.99/php/testmysql.php [ some lines omitted for brevity ]Requests per second: 7.10Transfer rate: 187.37 kb/s receivedConnnection Times (ms) min avg maxConnect: 0 2 40Processing: 255 279 292Total: 255 281 332

Наоборот, удваивая количество подключений, мы можем предсказать, что среднеевремя выполнения должно удвоиться с 1.283 до 2.566 секунд. В тестах производительно-сти мы, фактически, получили 2.570 секунд.

32

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Перегрузка при 40 подключенияхПосле того, как мы запустили тест производительности с 40 запросами, сервер был

перегружен с 35% неудачных запросов. При дальнейшем расследовании было обнаруже-но, что MySql сервер отказывал в запросах с ошибкой «Слишком много подключений».

Тест производительности также указал на поведение дочерних процессов Apache.Каждый скрипт PHP использовал 2 постоянных соединения, так, на 40 запросах мы име-ли 80 постоянных подключений, что значительно ниже значения по умолчанию MySql(max_connections 100). Однако, дочерние процессы Apache, которым не переданы не-медленно новые запросы, всеравно удерживают постоянное соединение. Эти неактивныедочерние процессы породили еще более 20 постоянных соединений, которые оказались«соломкой, которая сломала спину верблюду».

Исправляем ситуациюПереведя скрипты на непостоянные соединения, мы устранили эту проблему и по-

лучили результат 5.340 секунд. Альтернативное решение состояло в том, чтобы уве-личить MySql max_connections выше, чем значение по умолчанию.

ЗаключениеВышеупомянутое исследование в очередной раз показывает нам, что оптимизация

вашей работы является чрезвычайно сложной. Это требует понимания множества про-граммных систем, включая маршрутизацию сети, стек TCP/IP, количество физической ивиртуальной памяти, количество процессоров, поведение дочерних процессов Apache, ва-ших скриптов PHP и конфигурации базы данных.

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

Из вышеприведен-ных значений, мы можемвычислить какое количе-ство соединений мы мо-жем обработать не выхо-дя за пределы желаемоговремени ответа. Предпо-лагая наличе двусто-ронней сети с временемдоступа 0.5 секунд наInternet (0.25 секунд однасторона), мы можемпредсказать.

Поскольку наш клиент хотел время ответа 5 секунд, сервер сможет обрабатыватьдо 34 одновременных подключений в секунду. Это дает на пиковой нагрузке 34/5 = 6.8страниц в секунду.

33

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Для получения максимального количества страниц для просмотра в день, мы долж-ны умножить пиковую способность в секунду на 50.000 (эта методика предложена веб-мастерами pair.com, большой хостинговой компанией), что даст нам 340 000 страниц вдень.

Оптимизация кодаТерпеливому читателю, который все еще задается вопросом, почему мы так много

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

Большинство PHP сценариев просты. Они получают небольшое количество инфор-мации о сессии, загружают некоторое количество информации из системы управленияконтентом или базы данных, форматируют соответствующий HTML и отдают результатсвоей работы HTTP клиенту. Предположим, что типичный PHP сценарий исполняется 0.1секунду, время ожидания Internet – 0.2 секунды, только 33% времени из этих 0.3 секундбудут использоваться для генерации PHP сценарием ответа. Так, если вы улучшите ско-рость своего скрипта на 20%, клиент будет видеть, что время ответа сократилось до 0.28секунд, что является незначительным усовершенствованием. Конечно сервер сможет об-работать на 20% больше запросов к одной и той же странице, что увеличивает масштаби-руемость.

Вышеприведенный пример вовсе не означает, что мы должны опустить руки и всебросить. Это означает, что мы не должны чувствовать гордость после отвоевания очеред-ного 1% скорости в своих скриптах. Мы должны тратить свое время на оптимизацию за-служивающих внимание областей нашего кода, чтобы получить более высокую отдачу.

Высокие степени оптимизацииМеста, где высокая степень оптимизации достижима, находятся внутри циклов

while и for, где каждое замедление кода увеличивается в несколько раз из-за их повторе-ния. Лучший способ для понимания этого, это рассмотреть несколько примеров:

Пример 1 Вот вам один из простых примеров, печатающих массив:

for ($j = 0;$j < sizeof($arr);$j++) echo $arr[$j] . '<br>'; Этот код может быть существенно ускорен, если переписать его следующим образом: for ($j=0, $max = sizeof($arr), $s = '';$j < $max;$j++) $s .= $arr[$j] . '<br>'; echo $s;

Для начала необходимо понять, что выражение $j < sizeof($arr) будет вычислятьсякаждый раз, пока цикл будет выполнятся. Поскольку результат этого выражения всегдапостоянен, мы переносим его в $max. Если говорить техническим языком, то это называ-ется оптимизацией инварианта цикла.

Вторая проблема заключается в том, что в PHP 4 многократный вывод на экран ко-мандой echo работает гораздо медленнее, нежели сохранения всех данных в строке и од-нократный вывод результата на экран. Это связано с тем, что echo дорогая операция, ко-торая может повлечь за собой посылку пакетов TCP/IP HTTP клиенту.

Конечно, накопление данных в строке $s имеет некоторые проблемы масштабируе-мости, поскольку расходует больше памяти.

34

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Дополнительный способ ускорить вышеприведенный код – это использование бу-феризации вывода. Это позволит накапливать информацию внутренне и потом вывестиее целиком на экран в конце выполнения скрипта. Это существенно уменьшит нагрузкуна сеть за счет использования большего количества памяти и увеличения времени ожида-ния. В части моего кода, состоящего полностью из команд echo, улучшение работы до-стигло 15%.ob_start(); for ($j=0, $max = sizeof($arr), $s = '';$j < $max;$j++) echo $arr[$j] . '<br>';

Обратите внимание, на то, что буферизация при помощи функции ob_start() можетиспользоваться как глобальная оптимизация для всех ваших скриптов. В долго выполня-ющихся сценариях вы, возможно, захотите периодически выводить содержимое буфера,чтобы иметь определенную обратную связь с HTTP клиентом. Это может быть сделанопри помощи функции ob_end_flush(). Эта функция также выключает буферизацию выво-да, так что вам необходимо будет вызвать функцию ob_start() для ее возобновления.

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

Пример 2 В следующем примере мы циклом проходим по PEAR DB recordset'у, используя

специальную форматирующую функцию для форматирования результата, а затем выво-дим его командой echo. На сей раз я протестировал производительность, время выполне-ния составило 10.2 микросекунды (я не учитывал время подключения к базе и исполне-ние SQL запроса):function FormatRow(&$recordSet) { $arr = $recordSet->fetchRow(); return '<storng>' . $arr[0] . '</storng><em>' . $arr[1] . '</em>'; } for ($j = 0;$j < $rs->numRows();$j++) { print FormatRow($rs); }

Из первого примера мы с вами узнали, каким образом можно оптимизировать цикл.Изменим код следующим образом (получим 8.7 микросекунд):function FormatRow(&$recordSet) { $arr = $recordSet->fetchRow(); return '<strong>' . $arr[0] . '</strong><em>' . $arr[1] . '</em>'; } ob_start(); for ($j = 0, $max = $rs->numRows();$j < $max;$j++) { print FormatRow($rs); }

Мои тесты производительности показали, что использование переменной $maxсэкономило 0.5 микросекунды, а ob_start() - 1.0 микросекунду. В общей сложности – 1.5микросекунды.

35

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Однако, изменяя алгоритм цикла мы можем упростить и ускорить код. В нашемслучае, мы увеличили скорость выполнения до 8.5 микросекунд:function FormatRow($arr) { return '<strong>' . $arr[0] . '</strong><em>' . $arr[1] . '</em>'; } ob_start(); while ($arr = $rs->fetchRow()) { print FormatRow($arr); }

Однако, в данном случае возможна еще одна оптимизация. Мы можем убратьфункцию форматирования (потенциально жертвуя удобством эксплуатации ради скоро-сти), чтобы сэкономить еще 0.1 микросекунду (в результате получим 8.4 микросекунды):ob_start(); while ($arr = $rs->fetchRow()) { print '<strong>' . $arr[0] . '</strong><em>' . $arr[1] . '</em>'; }

Переключаясь на использование PEAR Cache, время выполнения повысилось до 3.5микросекунд для кэшированных данных:require_once("Cache/Output.php"); ob_start(); $cache = new Cache_Output("file", array("cache_dir" => "cache/")); $t = getmicrotime(); if ($contents = $cache->start(md5("this is a unique kexy!"))) { print "<p>Cache Hit</p>"; print $contents; } else { print "<p>Cache Miss</p>"; ## ## Code to connect and query database omitted ## while ($arr = $rs->fetchRow()) { print '<strong>' . $arr[0] . '</strong><em>' . $arr[1] . '</em>'; } print $cache->end(100); } print (getmicrotime()-$t);

Ниже я суммирую методы оптимизации:

Время выполнения(микросекунды)

Описание

9,9 Первоначальный вариант без оптимизации, не учитываем время соединения сбазой и выполнение SQL запроса.

36

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

9,2 Используем ob_start()

8,7 Оптимизируем цикл при помощи $max и ob_start()8,5 Меняем тип цикла с for на while, парсим как массив в FormatRow() с

использованием ob_start()

8,4 Удаляем FormatRow() и используем ob_start()3,5 Используем PEAR Cache совместно с ob_start()

Из вышеприведенных данных вы видите, что самая существенная оптимизациябыла достигнута не простым «щипанием» кода, а глобальной оптимизацией при помощифункции ob_start(), а также радикально отличающимся алгоритмом - кэшированиемHTML.

Оптимизации объектно-ориентированной программыВ марте 2001 года я провел некоторые неофициальные тесты производительности

классов на PHP 4.0.4 pl1. Дам несколько советов, исходящих из этих результатов. Триглавных пункта:

• Инициализируйте все переменные перед их использованием.

• Разименовывайте все глобальные переменные и свойства, которые часто используют-ся в методе и помещайте значения в локальные переменные в том случае, если вы пла-нируете обращаться к их значению более чем 2 раза.

• Пробуйте помещать все часто используемые функции в производные классы.

Внимание: поскольку PHP постоянно совершенствуется, могли произойти усовершен-ствования в лучшую сторону.

Дополнительные детали• Также я пришел к выводу, что вызов метода объекта (функция определена в классе)

примерно в два раза медленнее, нежели обычный вызов функции. Что касается меня,то я считаю эту ситуацию приемлемой если сопоставлять с другими ООП языками.

• Внутри метода (следующие отношения весьма приблизительны):

• Увеличение значения локальной переменной в методе почти таже быстро, как изапрос локальной переменной в функции.

• Увеличение значения глобальной переменной почти в два раза медленнее, чем увели-чение локальной переменной.

• Увеличение свойства объекта (например, $this->prop++) примерно в три раза медлен-нее чем локальная переменная.

• Увеличение неопределенной локальной переменной примерно в 9-10 раз медленнее,чем предопределенной.

• Только определение глобальной переменной без ее использования в функции такжезамедляет работу (примерно на тоже самое время, как и увеличение локальной пере-менной). PHP, вероятно, делает проверку на существование глобальной переменной.

• Скорость обращения к методу не зависит от количества методов в классе, потому чтоя добавил еще более 10 методов в тестовый класс, что не привело к изменениям в ско-рости.

• Методы в производных классах работаю быстрее, нежели определенные в базовомклассе.

37

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

• Функции с одним параметром вызова, а также с пустым телом занимают по временистолько же, сколько занимают 7-8 операций $localvar++. Вызов подобного метода за-нимает 15 $localvar++.

Дополнение от 11 июля 2004: эти испытания были проведены почти 3 года назад. Япроверил эти данные вновь на версии 4.3.3. Вызов функции теперь занимает 20$localvar++, а вызов метода 30 $localvar++. Это может быть потому, что $localvar++ сталовыполняться быстрее или вызов функция стал медленнее.

РезюмеЧем больше вы разбираетесь в программном обеспечении, которое вы используете

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

Для PHP скриптов самое узкое место обычно – это центральный процессор. Двапроцессора, вероятно, будут лучше, чем два гигабайта оперативной памяти.

Сборка PHP с параметром configure –enable-inline-optimization позволяет сделатьмаксимально быстрый исполняемый файл.

Оптимизируйте вашу базу данных и индексы, которые чаще всего используются впараметре WHERE ваших SQL запросов. ADODB – очень популярная библиотека аб-страктного доступа – позволяет работать в режими оптимизации SQL запросов, где выможете всесторонне изучить ваши неудачные SQL запросы, а также определить, в какомскрипте они выполняются.

Используйте кэширование HTML, если ваши данные редко меняются. Даже есливаши данные меняются каждую минуту – кэширование может помочь, если данные син-хронизировать с кэшем. В зависимости от сложности кода, кэширование позволяет улуч-шить скорость до 10 раз.

Тестируйте производительность вашего сложного кода на ранних этапах (или покрайней мере его опытные образцы), таким образом вы получите чувство ожидаемых па-раметров работы, прежде чем будет слишком поздно. Попробуйте использовать реали-стические количества испытательных данных, чтобы гарантировать должную масштаби-руемость.

Рассмотрите возможности использования кэширования опкода. Это дает приростпроизводительности на 10-200% в зависимости от сложности вашего кода. Обязательносделайте стресс тестирование вашего кода, прежде чем устанавливать оптимизаторы нареально работающий сервер, поскольку некоторые из них более надежны чем другие.

Используйте ob_start() в начале вашего кода. Это даст вам повышение производи-тельности на 5-15%. Вы также можете использовать gzip сжатие для организации бы-стрых загрузок (это требует дополнительных ресурсов центрального процессора).

Рассмотрите возможность установки Zend Optimizer'а. Это бесплатное программ-ное обеспечение делает некоторую оптимизацию, но будте внимательны – некоторыескрипты фактически замедляются, когда установлен Zend Optimizer. В основном, ZendOptimizer очень полезен, когда ваш код содержит множество циклов.

Оптимизируйте код циклов. Переместите определения, по которым работает циклперед циклом.

Используйте массивы и строковые функции везде, где это возможно. Они работаютзначительно быстрее, чем написание аналогичного кода.

38

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Самый быстрый способ связать многократные небольшие строки в одну – это ис-пользовать буфер вывода (ob_start()) и печатать echo в буфер. В конце получить данныефункцией ob_get_contents. Это работает, потомучто для буферизации выделяется перво-начальный буфер в 40 кб, который растет кусками по 10 кб.

Работая с массивами и объектами используйте ссылки где это возможно. Если этокороткий скрипт, и обслуживание кода – это не проблема, вы можете использовать гло-бальные переменные для сохранения объектов и массивов.

Если у вас много скриптов, использующих переменные сессии, рассмотрите воз-можность скомпилировать PHP для использования общедоступной памяти для сессий,или используйте RAM диск для их хранения. Включите эти возможности configure –with-mm, затем перекомпилируйте PHP, а также установите session.save handler = mm в php.ini.

Для поиска подстроки, используйте самую быструю команду strpos(), preg_match()и уж затем ereg(). Точно также str_replace() быстрее чем preg_replace(), которая, в своюочередь, быстрее, чем ereg_replace().

Располагайте наиболее часто встречающиеся утверждения switch в самом верху.Если большинство случаев попадает под значение по умолчанию, определите его также всамом начале.

Обработка XML данных регулярными выражениями работает значительно бы-стрее, чем использование SAX и DOM.

Делайте unset() неиспользуемых более переменных, чтобы освободить память. Этоглавным образом полезно для ресурсов и больших массивов.

Для классов с глубокой иерархией расширенные функции работают быстрее, чемопределенные в основном классе (родительском). Рассмотрите возможность копированиячасто используемых функций из основного класса в наследующий.

Рассмотрите возможность написание вашего кода как расширение PHP или Javaкласс или COM объект, если вы нуждаетесь в сверхскорости. Будте осторожны при обме-не данными между COM и Java.

Бесполезная оптимизацияНекоторые виды оптимизации полезны. Другие – напрасная трата времени. Часто

полезность усовершенствования пренебрежимо мала. Часто, внутренние изменения вPHP делают щипковые изменения кода устаревшими.

Вот некоторые общие легенды:

Echo быстрее чем print. Считается, что echo быстрее, так как не возвращает никако-го значения, тогда как print возвращает. Из моих тестов производительности PHP 4.3 вид-но, что различие в них пренебрежительно малы. И в некоторых ситуациях print быстрееecho (когда ob_start включен).

Удаление из кода комментариев ускоряет его выполнение. Если вы используете кэ-ширование опкода, комментарии уже проигнорированы. Это миф, тянущийся со временPHP 3, когда каждая строка скрипта интерпретировалась в момент ее выполнения.

'var=' . $var быстрее чем "var=$var". Это было справедливо для PHP 4.2 и более ран-них версий. В PHP 4.3 это было устранено. Добавление от 22 июня 2004: очевидно, что вPHP 4.3 скорость была значительно увеличена, но различия устранены не полностью. Од-нако, я нахожу, что различия стали незначительными.

39

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

HOWTO по оптимизации PHP

Ускоряют ли ссылки ваш код?Ссылки не обеспечивают никакого преимущества для работы со строками, целыми

числами и другими базовыми типами данных. Например, рассмотрим следующий код:function TestRef(&$a) { $b = $a; $c = $a; } $one = 1; ProcessArrayRef($one);

И тот же самый код без ссылок:function TestNoRef($a) { $b = $a; $c = $a; } $one = 1; ProcessArrayNoRef($one);

PHP фактически не создает копии переменных, когда «обрабатывает значение», ноиспользует вместо этого очень быструю ссылку, рассчитывая все внутри себя. Так вTestRef(), $b и $c будут устанавливаться дольше, так как ссылки должны отслеживаться,в то время как TestNoRef() $b и $c только указывают на первоначальное значение $a иPHP всего лишь увеличивает число ссылок. Поэтому TestNoRef() будет выполнена бы-стрее, чем TestRef().

Напротив, функции, которые принимают массивы и объекты в качестве парамет-ров, имеют преимущества в работе, если использовать ссылки. Это происходит потому,что массивы и объекты не используют счетчик ссылок. Поэтому при использовании мас-сивов и объектов без ссылок будет создано множество копий, когда они будут обрабаты-ваться. Так следующий код:function ObjRef(&$o) { $a =$o->name; } быстрее, чем этот: $function ObjRef($o) { $a = $o->name; }

Замечание: в PHP 5 все объекты передаются по ссылке автоматически, без требова-ния явного указания &. Объектная модель PHP 5 должна быть значительно быстрее.

40

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Логирование ошибок стандартными средствами PHP

Логирование ошибок стандартнымисредствами PHP

Автор: Андрей Олищук

Одним из возможных вариантов обработки ошибок, наряду с вы-водом на экран и отправкой по почте является их логирование,или, проще говря - запись информации об ошибке в лог-файл.PHP предоставляет различные средства для ведения таких запи-сей

Зачем это нужно?Логирование ошибок - очень важный метод их обработки, который позволяет

сохранять информацию об ошибках для целей отладки, но при этом скрывать их от сто-ронних глаз. К примеру, если допустить ошибку в простейшем коде (пропущена открыва-ющая кавычка):<?php echo hello"; ?>

то по умолчанию настроенный PHP выдаст на экран что-то вроде этого:Parse error: parse error, unexpected '"', expecting ',' or ';' ind:\programms\apache\Apache\htdocs\pro.php on line 2

Из информации об этой ошибке можно нехитро "выудить" абсолютный путь к кор-невой директории сайта: d:\programms\apache\Apache\htdocs\. Конечно, это небог весть какой секрет, однако и сообщения об ошибках бывают куда более информатив-ными.

Очень опасен вывод ошибок, к примеру, при SQL-инъекциях в СУБД через веб-сайт. В таких случаях злоумышленник сможет получать такую информацию как структу-ра таблицы (имя таблицы и количество полей), имя пользователя и много другое, что по-может ему взломать плохо защищенную базу данных. Конечно, от этого следует защи-щаться прежде всего средствами самого языка, но при этом, отключение вывода ошибокна экран для публично работающего сайта является одним из средств защиты.

Однако, простое отключение сообщений об ошибках не исправит сами ошибки.Они все равно будут возникать и их придется искать и править. Для эффективного поис-ка и правки конечно же будет необходим максиммум информации о произошедшем сбоеи тут на помощь должны прийти сообщения об ошибках. Логирование как раз и позволя-ет скрывать всю информацию от посторонних глаз и при этом сохранять отладочную ин-формацию.

У логирования есть и другие полезные стороны. В большинстве случаев, в лог-файл записывается не только описание ошибки и место ее возникновения, но и дата ивремя ее возникновения. Таким образом, лог-файл можно использовать еще и как журналошибок и вести по нему всю необходимую статистику.

41

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Логирование ошибок стандартными средствами PHP

PHP предоставляет такие возможности логирования как: настройка ведения логов вphp.ini и использование функции error_log().

Настройка в php.iniВ файле php.ini есть несколько директив, отвечающих за управление выводом со-

общений об ошибках. Прежде всего, это директива error_reporting, в которой мож-но установить типы стандартных ошибок, при возникновении которых PHP будет «сигна-лизировать» на экран или в лог-файл. Подробнее о типах ошибок и соответсвующих имконстантах можно узнать из официальной документации по адресу:http://ru.php.net/manual/en/ref.errorfunc.php#errorfunc.constants.

При отладке на рабочей машине рекомендуется включать все виды ошибок. Это де-лается установкой значения директивы error_reporting в E_ALL для PHP 4 и E_ALL &E_STRICT для PHP 5 (тип ошибок E_STRICT был введен в PHP 5, представляет собойбольше рекомендации нежели ошибки и не входит в состав E_ALL).

Далее, по необходимости, можно оставить включенным или отключить вывод со-общений на экран. За это отвечает директива display_errors, которая принимает значение1, если вывод включен и 0, если отключен. Рекомендации по включению те же: для рабо-чей тестовой машины лучше оставить 1 (чтобы оперативно видеть все ошибки, возни-кающие при отладке), а для публичного сервера установить значение в 0, так как пользо-вателям нет необходимости видеть лишнюю внутреннюю информацию. Логированиефайлов никак не зависит от этой директивы и может использоваться как вместо выводасообщений об ошибках на экран, так и вместе с ними.

Теперь мы подошли непосредственно к управлению логированием. Чтобы PHP за-писывал ошибки в лог-файл нужно сделать две вещи: включить логирование и указатьпуть к лог-файлу на сервере. Все это делается выставлением значений для двух директивв php.ini: log_errors и error_log.

log_errorsЭта диретива указывает, должен ли PHP записывать информацию об ошибках в

лог-файл. Соответственно, значение может быть либо on либо off. Как несложно дога-даться, при значении on, запись логов ведется, а при off – нет.

error_logЕсли директива log_errors «включена» (т.е. имеет значение on), то именно в дирек-

тиве error_log PHP будет искать путь к лог-файлу. Данная директива принимает в каче-стве значения строку, определяющую путь к лог-файлу в файловой системе сервера. Кпримеру, в Linux это можно записать так:error_log = /home/logs/error_log

А для Windows следующим образом:error_log = "D:\Temp\phplog.txt"

При этом, лог-файл будет выглядеть примерно так:[01-Jan-2006 03:48:46] PHP Warning: mysql_num_rows(): supplied argument is nota valid MySQL result resource ind:\programms\apache\Apache\htdocs\sud\sud\classes\class.mysql.php on line 29[01-Jan-2006 03:48:48] PHP Warning: mysql_num_rows(): supplied argument is nota valid MySQL result resource ind:\programms\apache\Apache\htdocs\sud\sud\classes\class.mysql.php on line 29[01-Jan-2006 15:50:05] PHP Parse error: parse error, unexpected '"', expecting',' or ';' in d:\programms\apache\Apache\htdocs\pro.php on line 2

42

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Логирование ошибок стандартными средствами PHP

Этот формат является стандартным и может быть отпарсен для ведения статистикив автоматическом режиме.

Использование функции error_log()Настройки в php.ini хороши и одновременно плохи тем, что влияют на все PHP-

скрипты, работающие на машине. Это значит, что если вам понадобится что-то изменитьотдельно для конкретного скрипта, то придется использовать функцию ini_set(), котораяне всегда бывает разрешена хостером.

К тому же, в лог-файл иногда нужно записывать не только стандартные ошибки,такие как E_WARNING или E_ERROR, но и ошибки, присущие отдельным веб-приложе-ниям. Допустим, в лог-файл необходимо записать сообщение об ошибке, говорящей, чтотовары на складе кончились - к примеру, если значение некоторого поля в SQL-выборкеSELECT равно нулю. Если такая выборка пройдет, то для PHP-приложения не будет ни-какой ошибки – подключились к базе, передали запрос, получили результат выборки ивсе без ошибок.

Для записи пользовательского лога используем пример:error_log("Произошла ошибка", 3, "D:/Temp/app_log.txt");

Первым параметром функции идет сообщение об ошибке, далее указываетсяспособ отправки сообщения (3 - означает запись в конец лог-файла) и третим парамет-ром идет путь к лог-файлу. Более подробную информацию по функции можно найти вофициальной документации. Стоит отметить, что функцию error_log() не следует путатьс директивой error_log из php.ini.

Однако, функция error_log() автоматически не вставляет время возникновенияошибки и символы переноса строки, если второй параметр принимает значение 3. Поэто-му, эти данные будет необходимо организовывать самостоятельно и указывать их в тек-сте сообщения об ошибке.

В случае, когда необходимо вести не отдельный лог-файл PHP-приложения, а пи-сать ошибки в стандартный лог (установленный в директиве error_log файла php.ini), томожно заменить способ отправки сообщения (второй параметр функции error_log()), ука-зав вместо значения 3, значение 0. Следующий код напишет сообщение об ошибке встандартный лог, при этом автоматически подставив время и перевод строки в конце.error_log("Произошла ошибка",0);

Так как error_log() является функцией, ее можно вызывать в любом месте кода. Этоможет быть полезно для установки режимов «режим отладки» и «режим работы» для ва-ших PHP-приложений прямо в PHP-коде приложения. К примеру, Илья Альшанетский(Ilia Alshanetsky) приводит такой способ логирования ошибок в двух режимах (переводтекста и комментарии мои):<?php function sql_failure_handler($query, $error) { //Формируется строка ошибки которая состоит //из исходного SQL-запроса и //текста ошибки, возвращаемого MySQL $msg = htmlspecialchars(«Ошибка выполнения запроса: {$query}<br>Текст ошибки:{$error}»); //В любом случае пишется в лог error_log($msg,3,«/home/site/logs/sql_error_log»);

43

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Логирование ошибок стандартными средствами PHP

//Если определена константа debug //к примеру, в конфигурационном файле приложения //то функция возвращает полную строку ошибки, к примеру, для вывода на экран if (defined('debug')) { return $msg; } //В любом случае возвращается нейтральная фраза //для «чужих» посетителей return «Запрашиваемая страница временно недоступна»; } //Попытка выполнить запрос к базе, в случае неудачи //которого, будет вызвана наша функция mysql_query($query) or die(sql_query_handler($query,mysql_error())); ?>

Данный пример демонстрирует, как можно управлять логированием динамически.

ИтогКак уже было сказано, тонкая настройка конфигурационного файла php.ini и ис-

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

Кроме того, в данном материале обработка ошибок была затронута частично –только по части логирования, но в PHP есть большее количество директив и функций поуправлению выводом ошибок. Если вы хотите подробнее изучить эти возможности, тообратитесь к официальной документации и к файлу php.ini – в нем зачастую даются пояс-нения тех или иных директив.

44

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Один PHP хорошо, а два лучше

Один PHP хорошо, а два лучшеАвтор: Денис Баженов

Как совмещать четвертую и пятую версию PHP на одной маши-не. Узнайте об одном из вариантов прямо сейас

Зачем спорить? Можно все удачно совмещать!

(Рекламный лозунг компании Zannussi)

В последнее время идут жаркие дебаты о необходимости внедрения в массыPHP5. Некоторые поддерживают эту идею. Некоторым хватает тех возможностей,которые предоставляет «четверка». В этой статье я не собираюсь рассуждать о плю-сах и минусах «братьев по разуму». Я попытаюсь предложить выход для людей, кото-рые обладают собственными серверными площадками и которые хотят опробоватьPHP5 «в бою», но при этом не могут отказаться от «четверки» в силу необходимостисопровождения и разработки приложений на ее платформе.

Я опишу процесс установки PHP4 и PHP5 одновременно на один веб-сервер. Такимобразом, вы сможете работать одновременно с двумя типами скриптов. Идея состоит врегистрации SAPI библиотек интерпретатора на разные расширения файлов.

РеализацияИтак, начнем.

Для реализации будут необходимы:

• дистрибутивы PHP4 и PHP5;

• рабочий веб-сервер;

• любой бинарный редактор.

Описание будет проводиться применительно к платформе Windows + Apache/2.0.Процесс интеграции мало, чем отличается для разных операционных систем или разныхверсий Apache. Разница лишь в разных именах библиотек SAPI, с которыми вам придетсяработать, а также еще в некоторых моментах, о которых я скажу позже.

Данный подход будет работать лишь в тех случаях, когда PHP работает как модульApache или, как еще говорят, SAPI библиотека.

Просьба не путать SAPI с ISAPI. SAPI (Server API) – это термин принятый для обозна-чения API любого сервера (Apache, iPlanet и т.д.). ISAPI (Internet Server API) – это стан-дарт корпорации Microsoft на API их веб-сервера IIS.

PHP работает на веб-сервере c помощью соответствующего SAPI расширения(php4apache.dll – PHP4 для Apache/1.3 php5apache2.dll – PHP5 для Apache/2.0). Регистра-ция SAPI библиотеки в веб-сервере осуществляется следующим образом.# Для PHP4LoadModule php4_module F:/php4/sapi/php4apache2.dll# Эта строка только для линейки 1.3AddModule mod_php4.cAddType application/x-httpd-php .php

45

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Один PHP хорошо, а два лучше

# Для PHP5LoadModule php5_module F:/php5/php5apache2.dll# Эта строка только для линейки 1.3AddModule mod_php5.cAddType application/x-httpd-php .php

Библиотеки php4apache2.dll и php5apache2.dll используют один и тот же строковыйидентификатор (application/x-httpd-php) для определения зависимости между расширени-ем обрабатываемого файла и SAPI библиотекой обработчика. Именно это следует испра-вить для возможности совместной работы двух интерпретаторов.

Все копии интерпретатора, установленные на веб-сервере (в нашем случае их две)должны обладать уникальной идентифицирующей строкой типа. Я в качестве примерадля второй копии PHP возьму идентификатор «application/x-httpd-ze2». Вы можетевзять любой другой идентификатор.

Длины исходной и замещаемой строк типа в бинарных файлах должны быть равны, длясохранения общей длины файла!

Идентификатор типа зашит в библиотеках SAPI для конкретных веб-серверов. Пра-вить необходимо только библиотеку для вашего конкретного сервера.

Полный список SAPI библиотек и веб-серверов, для которых они предназначены, вы мо-жете найти в руководстве по установке интерпретатора, которое поставляется вме-сте с дистрибутивом продукта, а также на сайте разработчика http://www.php.net/.

Предположим, что «четверка» будет основной используемой версией интерпрета-тора. Значит, ее SAPI модуль можно загружать в веб-сервер.# Загружаем SAPI библиотеку# Для Apache/2.0LoadModule php4_module F:/php4/sapi/php4apache2.dll# Для Apache/1.3LoadModule php4_module F:/php4/sapi/php4apache.dll# Регистрируем SAPI библиотеку на обработку файлов *.phpAddType application/x-httpd-php .php

Теперь надо загрузить «пятерку» так, что бы веб-сервер мог отличать ее от «чет-верки». Для этого надо изменить, используемый библиотекой, идентификатор типа. Дляэтого необходимо открыть библиотеку php5apache2.dll (php5apache.dll если вы использу-ете Apache/1.3) в двоичном редакторе и заменить все вхождения строки «application/x-httpd-php» на строку «application/x-httpd-ze2». Для библиотеки php5apache2.dll(PHP/5.1b1) таких вхождений два, со смещениями 0x000048EC и 0x0000490C. Для той жебиблиотеки из дистрибутива PHP/5.0.4 смещения равны 0x000048E8 и 0x00004908 соот-ветственно.

После этого можно загружать SAPI модуль «пятерки» в Apache, используя подстав-ной идентификатор «application/x-httpd-ze2».# Для Apache/2.0LoadModule php5_module F:/php5/sapi/php5apache2.dll# Для Apache/1.3LoadModule php5_module F:/php5/sapi/php5apache.dllAddType application/x-httpd-ze2 .php5

После перезапуска веб-сервера все файлы с расширением «*.php» будут обрабаты-ваться «четверкой», а файлы «*.php5» «пятеркой».

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Один PHP хорошо, а два лучше

Конфигурирование интерпретаторовКонфигурации интерпретаторов должны различаться. Потому как они имеют

разные интерфейсы и разные модули расширений. Поэтому в конфигурационный файлвеб-сервера нужно добавить такую строчку.# Эта директива определяет путь, где находится# конфигурационный ini-файл PHP5PHPIniDir F:/php5

Теперь php.ini от «четверки» должен лежать там, где всегда, а конфигурационныйфайл «пятерки» необходимо поместить в папку F:/php5. Теперь, конфигурации интерпре-таторов можно менять независимо.

К сожалению, директиву PHPIniDir нельзя использовать вместе с Apache/1.3 (Ещеодин повод перейти на серию 2.0). Если у вас Apache/1.3, то проблему можно решить спомощью бинарного редактора. Необходимо открыть библиотеку php5ts.dll и заменитьвсе вхождения строк php.ini и php-%s.ini на что-нибудь отличное от имени конфигураци-онного файла PHP4. Я для примера возьму строки ze2.ini и ze2-%s.ini соответственно.

php-%s.ini - это строка – аргумент, которая передается функции sprintf() для генерацииальтернативного имени конфигурационного файла. В данном случае %s это имя исполь-зуемого SAPI. Например, php-cgi.ini или php-apache.ini. Более подробно о назначении аль-тернативных файлов конфигурации вы можете узнать из руководства по установкеинтерпретатора.

При замене строки php-%s.ini вы должны убедиться, что замещаемая строка, как иоригинал, содержит подстроку %s.

Теперь конфигурационный файл «пятерки» должен лежать там же где и аналогич-ный файл его младшего брата, но он должен иметь имя ze2.ini, а не php.ini.

Настройка веб-сервераСовсем не обязательно переименовывать все скрипты PHP5 в «*.php5». Если в ди-

ректории F:/htdocs/php5app находятся скрипты «пятерки», то достаточно в конфигураци-онный файл сервера добавить следующие строки.<Directory F:/htdocs/php5app>

<Files "*.php">ForceType application/x-httpd-ze2

</Files></Directory>

Теперь все файлы в этой дирректории с расширением «*.php» сервер будетрассматривать как приложения PHP5, а не PHP4.

В Apache/2.0 директива ForceType является частью модуля core (ядра веб-сервера), в товремя как в линейке 1.3 эта директива находится в модуле mod_mime. Поэтому, если выиспользуете Apache/1.3, то необходимо что бы этот модуль загружен на сервере.

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ

Один PHP хорошо, а два лучше

СтабильностьОтносительно стабильности подобного решения я не могу сказать ничего опреде-

ленного. На системах WinNT сервер Apache, обрабатывает все запросы разными потока-ми в пределах одного процесса. А это значит, что в одно адресное пространство этогопроцесса, оказываются загруженными библиотеки сразу нескольких интерпретаторов,что теоретически может приводить к самым непредсказуемым результатам. На системах*nix существует несколько моделей поведения веб-сервера, но ни одна из них не решаетпроблемы разделения адресного пространства. Гарантию стабильности, в подобных усло-виях, могут дать только программисты Zend/PHPTeam.

Отмечу лишь, что моя тестовая платформа (Apache/2.0.52 + PHP/4.3.11 +PHP/5.1b1) вела себя не очень стабильно, хотя критических ошибок все же не было. Ясклонен списывать это на «сырость» PHP/5.1b1.

ВыводыВозможно, стоит поставить «пятерку» без модификации. А «четверку» править би-

нарным редактором. Это будет правильнее, так как, скорее всего, «пятерку» вам придетсяобновлять чаще. Смысл процедуры, при этом, остается тот же.

В какой-то мере, для меня, спор о пользе PHP5 и вреде PHP4 (или наоборот? :)отпал. Приложения, разбросанные по разным папкам, работают на разных интерпретато-рах. Все определяет конфигурация веб-сервера. Это удобно для тестирования и разра-ботки до тех пор, пока будут длиться «переходные процессы».

P

HP

In

side

#15

Т

ЕМА

С О

БЛ

ОЖ

КИ