#16, Декабрь'2005 :: ajax и php

54
№ 16 Ноябрь - Декабрь '05 издается с февраля 2004 года, www.phpinside.ru Ajax и PHP Учебник по созданию компонент Joomla! Новогодний выпуск Вакансии от PHPClub.ru Бонус 1 Бонус 2

Upload: vital-b

Post on 10-Mar-2016

230 views

Category:

Documents


2 download

DESCRIPTION

Ajax и PHP без использования XmlHttpRequest Ошибки начинающих TDD-практиков Основы использования PHP для работы с FTP Сборка PHP 5 с драйверами mysql и mysqli одновременно Учебник по созданию компонент Joomla!

TRANSCRIPT

Page 1: #16, Декабрь'2005 :: Ajax и PHP

№ 16Ноябрь - Декабрь '05

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

Ajax и PHP

Учебник по созданиюкомпонент Joomla!

Новогодний выпуск

Вакансии отPHPClub.ru

Бонус 1

Бонус 2

Page 2: #16, Декабрь'2005 :: Ajax и PHP

СодержаниеБиржа труда....................................................................................................................................................... 2Тема с обложки Ошибки при использовании Ajax................................................................................................................8 Sajax - реализация Ajax в PHP................................................................................................................... 10 Ajax и PHP без использования XmlHttpRequest...................................................................................... 16Идеи Ошибки начинающих TDD-практиков..................................................................................................... 21 Основы использования PHP для работы с FTP........................................................................................28 Сборка PHP 5 с драйверами mysql и mysqli одновременно....................................................................33 Учебник по созданию компонент Joomla!................................................................................................35

Биржа трудаВ этом номере вместо слова редактора мы решили обратить ваше внимание на си-

туацию на рынке труда PHP-разработчиков.

Огромное спасибо клубу разработчиков http://phpclub.ru за организованный опрос,целью которого является определение тенденций на рынке нашего труда. Результатыопроса на 16 декабря 2005 мы приводим здесь.

Результаты голосованияХотим обратить внимание, что опрос продолжается и мы убедительно просим и

вас принять в нем участие. Конечно в том случае, если программирование на PHP прино-сит вам какой либо доход. Данные по ответам каждого участника не разглашаются. Есливы решите оставить комментарии – все в ваших руках. Голосование находится здесь:http://phpclub.ru/talk/showthread.php?s=&threadid=77541&rand=18

А сейчас, промежуточные результаты:

2

P

HP

In

side

#16

С

одер

жан

ие

/ Б

ирж

а тр

уда

1

да

нет14

86

0

20

40

60

80

100

Процентов от 100%

Повысился мой суммарный доход по сравнению с 2004 годом

данет

Page 3: #16, Декабрь'2005 :: Ajax и PHP

3

P

HP

In

side

#16

Б

ирж

а тр

уда

1

да

нет

3862

0

20

40

60

80

Процентов от 100%

Менял работу в течении последнего года

данет

1

да

нет

66

34

0

20

40

60

80

Процентов от 100%

Наша фирма набирает еще web-программистов

данет

1

да

нет

68

32

0

20

40

60

80

Процентов от 100%

У нас жесткое разделение по должностям программист,верстальщик,тестировщик

данет

Page 4: #16, Декабрь'2005 :: Ajax и PHP

4

P

HP

In

side

#16

Б

ирж

а тр

уда

47

53

020406080

100

Процентов от 100%

1

да

нет

Стало больше проектов по сравнению с 2004годом

данет

50

50

0

50

Процентов от 100%

1

да

нет

Планирую повышать уровень web-программинга на семинарах, конференциях,

мастерклассах

данет

Page 5: #16, Декабрь'2005 :: Ajax и PHP

Вакансии от phpclub.ruWeb - Программист, Москва ($1500)

В компанию "Компания "Рутек"" (Russia,Москва) требуется Web - ПрограммистЗарплата от $1500;Занятость Полная (основное место работы);Возраст:от 22 до 35;Пол:не имеет значения;Образование:Незаконченное высшее; Опыт работы:1 годЯзыки и технологии: Perl, CGI, PHP, Операционные системы: Unix, Прочие требования: В российскую компанию приглашается Web-программист. Требования:Знание Perl, PHP, SQL; Опыт работы в среде UNIX; Опыт совместной работы над проектами вколлективе; Умение разбираться в чужом коде; Высшее (или неполное высшее) техническоеобразование; Технический английский. Обязанности: Разработка и сопровождение программного обеспечения для Web-интерфейсов.Условия работы: 1200$ на испытательный срок, 1500$ после испытательного срока, мед.страховка, возможность обучения.Контактная информация: Елена Тёлина, (495) 10 10 789, .WEB-сайт компании : http://www.rutech.ru/Вакансия предоставлена прямым работодателем 15-12-2005 и будет актуальна до 14-01-2006

Cпециалист, Москва ($1600)

В компанию "Inform-Mobil" (Russia,Москва) требуется специалистЗарплата от $1600;Занятость Полная (основное место работы);Возраст:от 25 до 40;Пол:не имеет значения;Образование:не имеет значения; Опыт работы:не имеет значенияЯзыки и технологии: C, C++, .Net, Perl, CGI, PHP, Python, UML, XML, XSL, XSLT, СУБД: MS SQL Server, MySQL, PostgreSQL, Операционные системы: Linux, Прочие требования: Все перечисленные технологии являются 'желательными'. С произвольнымих набором придётся сталкиваться в рамках должности. Единственными обязательнымитребованием является профессиональное владение парадигмой ООП.Обязанности: Исследование и разработка инфраструктурных средств организации и автоматизациразработки программного обеспеченияУсловия работы: Постоянно растущий соц. пакет (питание, спорт, ...), возможность карьерногороста, интересные задачи.Контактная информация: Борис Безруков, (096)995-8-995 доб., .WEB-сайт компании : http://www.immo.ru/Вакансия предоставлена прямым работодателем 15-12-2005 и будет актуальна до 14-01-2006

5

P

HP

In

side

#16

Б

ирж

а тр

уда

Page 6: #16, Декабрь'2005 :: Ajax и PHP

Руководитель Отдела тестирования, Москва ($1500)

В компанию "Прямой работодатель" (Russia,Москва) требуется Руководитель ОтделатестированияЗарплата от $1500;Занятость Полная (основное место работы);Возраст:от 23 до 40;Пол:не имеет значения;Образование:не имеет значения; Опыт работы:1 годЯзыки и технологии: C, C++, Java, Perl, CGI, PHP, СУБД: PostgreSQL, Операционные системы: Unix, Прочие требования: Общие представления обо всех основных средствах и методикахтестирования, глубокое знание какой-либо из систем тестирования, понимание принциповпостроения ПО, опыт на руководящей позиции от 1 года, опыт внедрения тестирования и развитияего процессов, желателен опыт создания и руководства командами, отвечающими за тестирование,общее представление о PHP, Perl, MySQL, PosgreeSQL, Java, C ++, разработке Web-сервисов,продвинутый пользователь * nix. Обязанности: Hуководство, планирование и контроль за тестировщиками, переход отприемочного тестирования к многоаспектному тестированию продуктов, создаваемых компанией,внедрение средств и методик автоматизированного тестирования, обучение тестировщиковметодологии и инструментальным средствам Условия работы: Работа в г.Юбилейном Московской области /15-20 мин от м.ВДНХ/, соц.пакет /корпоративный транспорт, бесплатное питание, спорт/. Контактная информация: Марина, Светлана, 739-94-17, 995-8-995, .Вакансия предоставлена прямым работодателем 14-12-2005 и будет актуальна до 13-01-2006

Web разработчик / архитектор, Санкт-Петербург ($700)

В компанию "TRADEBOX.RU" (Russia,Санкт-Петербург) требуется Web разработчик /архитекторЗарплата от $700;Занятость Полная (основное место работы);Возраст:от 24 до 40;Пол:не имеет значения;Образование:не имеет значения; Опыт работы:2 годаЯзыки и технологии: C, C++, HTML, DHTML, CSS, Java, JScript, VBScript, PHP, XML, XSL,XSLT, СУБД: MySQL, Операционные системы: Windows, Прочие требования: Серьезный опыт работы с PHP и C++. Обязанности: Разработка новых сервисов для проекта TRADEBOX.RU, поддержка проекта.Условия работы: Офис находится в 5 минутах от м. Горьковская.Контактная информация: Дмитрий, (812) 336-16-90, .WEB-сайт компании : http://www.tradebox.ru/Вакансия предоставлена прямым работодателем 14-12-2005 и будет актуальна до 13-01-2006

6

P

HP

In

side

#16

Б

ирж

а тр

уда

Page 7: #16, Декабрь'2005 :: Ajax и PHP

Программист, Киев ($500)

В компанию "ВОЙП" (Ukraine,Киев) требуется ПрограммистЗарплата от $500;Занятость Полная (основное место работы);Возраст:от 22 до 40;Пол:не имеет значения;Образование:Высшее; Опыт работы:2 годаЯзыки и технологии: C, C++, Perl, CGI, PHP, СУБД: MySQL, Операционные системы: Linux, Прочие требования: Профессиональные навыки: • Уверенные практические знания двух изперечисленных языков программирования: PHP5, Perl или С/C++ • MySQL 4.0+/5, умение строитьи оптимизировать сложные запросы • Опыт работы и разработки приложений под Linux/FreeBSD •Знание концепций ООП в целом и умение применять их на практике • Уверенное знаниеписьменного английского языка Желательно: • Навыки тестирование ПО • Навыки работы ссистемой контроля версий (Subversion, CVS) • Базовые знания стека протоколов TCP/IP ипротоколов уровня приложений в частности • Базовые знания Apache • Базовые знанияHTML/XHTML Личностные качества: • умение работать в команде • способность оцениватьвременные затраты на работу • умение вести документацию по написанному коду • способностьпридерживаться едиКонтактная информация: Олег Витальевич, .Вакансия предоставлена прямым работодателем 15-12-2005 и будет актуальна до 20-12-2005

Ведущий веб-программист, Минск ($600)

В компанию "АДТ" (Belarus,Минск) требуется ведущий веб-программистЗарплата от $600;Занятость Полная (основное место работы);Возраст:от 25 до 30;Пол:мужчина;Образование:Высшее; Опыт работы:3 годаЯзыки и технологии: HTML, DHTML, CSS, JScript, VBScript, Perl, CGI, PHP, XML, XSL, XSLT, СУБД: MySQL, Oracle, Прочие требования: В московскую компанию разработчик веб-приложений (холдинговаяструктура), в связи с открытием филиала компании в г. Минске требуется ведущий веб-программист, требования: опыт руководства группой программистов от 1 года, программированиепод веб от 2 лет, PHP, Javascript, CSS, MySQL, наличие портфолио, желателен опыт работы сOracle. Приветствуется опыт работы с UNIX на уровне пользователя. Обязанности: Руководство группой разработчиков, написание приложение и поддержка под вебУсловия работы: З/п 500-600$ от кандидата, полная занятость, график работы с 10-19.00, вариантудаленной работы не рассматривается, место работы г. Минск. При заинтересованности резюме на[email protected]Контактная информация: Ходакова Анастасия, 095-000-00-00, .Вакансия предоставлена прямым работодателем 15-12-2005 и будет актуальна до 04-01-2006

7

P

HP

In

side

#16

Б

ирж

а тр

уда

Page 8: #16, Декабрь'2005 :: Ajax и PHP

Ошибки при использовании Ajax

Ошибки при использовании AjaxАвтор: Алекс БосвортПеревод: Григорий Федоринов

В последнее время мы много слышим об Ajax. В основном это хвалебные оды. Но есть и другая сторона медали...

Ajax это удивительная технология, позволяющая создавать вебприложения ново-го поколения такие как maps.google.com, colr.org и backpackit.com. Но Ajax также опас-ная технология для вебразработчиков, она добавляет множество UI (прим. пер. пользо-вательский интерфейс) проблем, и проблем загрузки сервера.

Я собрал список наиболее часто совершаемых ошибок при разработке на Ajax :

Не создаются визуальные эффекты произведенного действия Если я произвел действие, которое должно быть отработано AJAX, вы должны

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

Отсутствие кнопки «Возврат» действия Кнопка «Возврат» это одна из наиболее востребованных возможностей стандарт-

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

Изменение состояния ссылок (GET запросы) Как я рассказывал в одной из своих предыдущих статей, Ajax-приложения вно-

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

Мелькание и замена частей страницы неожиданно для пользователя Первая буква в аббревиатуре АJAX обозначает asynchronous (асинхронный).

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

8

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 9: #16, Декабрь'2005 :: Ajax и PHP

Ошибки при использовании Ajax

Не использовать ссылки «Послать другу» и «Добавить в избранное» Возможность «Послать другу» для того чтобы он увидел то, что вижу я и воз-

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

Большой программный код замедляет браузер Ajax это путь для того чтобы сделать приложения javascript более интересными,

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

Изобретение новых приемов управления для пользователя Большая ошибка которую легко совершить при использовании Ajax это: 'Клик-

нув мышью на объекте, не всегда вызывается результат, который ты ожидаешь'. Конечно,продвинутые пользователи знают что если нажать и удерживать курсор на div то егоможно перенести в другое место, но остальные пользователи знают об этом потому чтоэто не используется в общей практике пользователей, таким образом вы увеличиваетесложность и время обучения пользователя, это всегда негативный фактор для любогоприложения.

Не каскадные изменения других частей страницы Ajax/Javascript дает вам специфическое управление над содержанием страницы,

это позволяет легко получить фокус над одной областью и теряет управление над други-ми встроенными картинками. В качестве примера это Backpackit заголовок (прим. Пере-водчика - Все эти возможности на сайте http://www.backpackit.com/, который позволяетпечатать свои статьи "). Если вы изменяете заголовок страницы, то незамедлительно ме-няется заголовок, они даже меняют заголовок справа, но не меняют тег title. C Ajax выдолжны менять полную картину, когда делаете локальные изменения.

Асинхронно выполняемые операции С Ajax вы можете редактировать множество полей форм практически в одно вре-

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

Прокрутка страницы дезориентирует пользователя Другая проблема показа текста в уже загруженной странице происходит при про-

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

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

http://sourcelabs.com/ajb/archives/2005/05/ajax_mistakes.html

9

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 10: #16, Декабрь'2005 :: Ajax и PHP

Sajax – реализация Ajax в PHP

Sajax – реализация Ajax в PHPАндрей Олищук

На данный момент в сети можно найти множество фреймворкови библиотек для работы с Ajax в PHP. Sajax – одна из них

Технология Ajax начала плотно входить в реалии PHP-разработки. В сети сталипоявляться различные библиотеки и даже фреймворки для работы с Ajax. Об одной изтаких библиотек сейчас и пойдет речь.

Что такое SajaxSajax – это инструмент для разработки веб-приложений с использованием техноло-

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

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

Вариант Sajax для PHP работает как обычная библиотека, которую можно подклю-чать к вашему коду посредствами команд include и require.

Библиотеку Sajax можно скачать с официального сайта:

http://www.modernmethod.com/sajax/download.phtml.

Пример для быстрого стартаРассмотрим простейший пример применения Sajax, чтобы понять как это работает.

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

Этот пример будет простейшим, поэтому в нем, во избежание усложнения материа-ла прибегнем к смешению PHP, JavaScript и HTML кода в одном пробном файле, назовемего test1.php.

Для начала, подключим библиотеку Sajax и создадим PHP-функцию, которая будетсчитывать данные из файла.<? require("Sajax.php"); function gettext_php() { if ($text = file_get_contents("data.txt")) { return $text; } else { return "Ошибка. Возможно файл пуст или отсутствует"; } } ?>

10

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 11: #16, Декабрь'2005 :: Ajax и PHP

Sajax – реализация Ajax в PHP

Далее, добавим вызовы функций Sajax, которые необходимы для того, чтобы нашафункция gettext_php() стала видна для JavaScript.

Теперь код в test1.php будет выглядеть вот так: <? require("Sajax.php"); function gettext_php() { if ($text = file_get_contents("data.txt")) { return $text; } else { return "Ошибка. Возможно файл пуст или отсутствует"; } } //Инициализируем Sajax sajax_init(); //Экспортируем в JavaScript следующие PHP-функции sajax_export("gettext_php"); sajax_handle_client_request(); ?>

На этом «серверная» часть кода заканчивается, но так как мы для простоты решиливсе писать в одном файле, то «клиентскую» часть запишем сюда же. После закрывающе-го тега ?> необходимо дописать обычный HTML-код с небольшой вставкой.<html> <head> <title>Пример 1</title> <script type="text/javascript"> <?php sajax_show_javascript();

?> function AjaxDo() { x_gettext_php(set_result); } function set_result(result) { document.getElementById('_show_file_').innerHTML = result; } </script> </head> <body> <input type="button" value="Прочесть файл" x_onClick="AjaxDo()"> <div name="_show_file_" id="_show_file_"> </body></html>

Что содержится в этом коде?

Сам HTML, я думаю, будет понятен без объяснений – это обычная кнопка «Про-честь файл» и пустой тег <div> с именем «_show_file_». Все самое интересное содержит-ся в JavaScript коде. Как мы видим, после тега <script> производится вызов -PHP-функ-ции sajax_show_javascript() - она необходима для генерации служебных функций-враппе-ров. Далее в коде JavaScript идут две функции: AjaxDo() и set_result(), написанные нами.

Функция AjaxDo() срабатывает по нажатию кнопки «Прочесть файл» (она прописа-на в ее атрибуте x_onClick). Тут же производится вызов функции x_gettext_php(). Этовраппер (JavaScript-оболочка) той самой функции, которую мы написали на PHP немногоранее и назвали gettext_php. В Sajax, для вызова функции-враппера берется названиеPHP-функции и подставляется префикс «x_», т.е. если наша PHP-функция называласьgettext_php(), то ее враппер в JavaScript будет называться x_gettext_php().

11

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 12: #16, Декабрь'2005 :: Ajax и PHP

Sajax – реализация Ajax в PHP

В качестве параметра передается наименование JS-функции set_result(). Все что де-лает эта функция – добавляет на страничку новый HTML, посредством атрибутаinnerHTML для элемента _show_file_. Т.е. просто дописывает новый HTML-код на стра-ничку.

Перед тем как попробовать выше приведенный код в действии, необходимо будетсоздать текстовый файл data.txt, в который можно записать любой текст. Именно этоттекст и должен быть выведен в результате выполнения скрипта.

Теперь, если мы запустим файл test1.php и нажмем на кнопку «Прочесть файл», тониже этой кнопки появится текст, записаный вами ранее в data.txt, либо фраза "Ошибка.Возможно файл пуст или отсутствует" в том случае, если вы забыли его создать или со-здали, но не записали в него какой либо текст.

Это довольно простой, но уже вполне убедительный пример.

Чат средствами PHP5, Sajax и SmartyВсе что мы рассмотрели выше – это довольно полезно, но не демонстрирует спосо-

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

Для работы этого примера нам соответственно понадобится дистрибутив Smarty,который можно взять с сайта http://smarty.php.net. Будем считать, что с этим шаблониза-тором вы уже знакомы и он установлен в вашей системе.

В процессе работы нам потребуется создать два файла – шаблон (назовем егоchat.tpl) и, так называемый, контроллер, т.е. PHP-файл который будет оперировать дан-ными и передавать их в шаблон Smarty. Назовем этот файл chat.php.

Начнем с создания контроллера:<? //Подключаем Sajax require "Sajax.php"; //Подключаем Smarty. Не забудьте указать ваши пути require "D:/programms/apache/htdocs/smarty/Smarty.class.php"; //Инициализируем Smarty //Обратите внимание на то, что во избежание конфликтов мы //будем использовать ограничители тегов Smarty <{ и }> вместо стандартных { и } $smarty = new Smarty; $smarty->Smarty(); $smarty->template_dir = "D:/programms/apache/htdocs/templates/"; $smarty->compile_dir = "D:/programms/apache/htdocs/templates_c/"; $smarty->config_dir = "D:/programms/apache/htdocs/config/"; $smarty->cache_dir = "D:/programms/apache/htdocs/cache/"; $smarty->left_delimiter = "<{"; $smarty->right_delimiter = "}>"; //Функция записи ника и сообщения в общий файл function add_line($msg_text) { //обрезаем теги и добавляем перенос строки и перевод каретки $msg = strip_tags($msg_text) . "\r\n"; //Пишем в конец файла file_put_contents("data.txt",$msg,FILE_APPEND); } //Функция вывода содержимого файла на экран

12

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 13: #16, Декабрь'2005 :: Ajax и PHP

Sajax – реализация Ajax в PHP

function refresh() { $lines = file("data.txt"); return join(" ", array_slice($lines, -25)); } //Инициализация Ajax $sajax_request_type = "GET"; sajax_init(); //Перечисляем функции для экспорта в JavaScript sajax_export("add_line", "refresh"); sajax_handle_client_request(); //Получаем JS-враппер PHP-функций в виде строки $sajax_wrappers = sajax_get_javascript(); //Присваеваем эту строку Smarty-переменной $WRAPPERS $smarty->assign("WRAPPERS",$sajax_wrappers); //Выводим шаблон chat.tpl $smarty->display("chat.tpl"); ?>

Итак, чем отличается этот код от того, который был рассмотрен ранее, в примере свыводом текста из файла на экран? Прежде всего, здесь появился код для работы соSmarty. Мы инициализировали объект $smarty и указали его первичные настройки – путик служебным директориям. Затем мы поменяли стандартные делимитеры (теги) Smartyна <{ и }>. Это сделано на всякий случай, во избежание конфликтов между символами{ } в синтаксисе Smarty и JavaScript. Вы можете решить эту проблему иным образом.

После этого были созданы две функции (записи и чтения из файла) и инициализи-рован Sajax.

Насколько мы помним из предыдущего примера, JavaScript-врапперы для PHP-функций генерируются динамически функцией sajax_set_javascript(). Однако, даннаяфункция выводит JavaScript на экран, а в нашем случае необходимо этот код передать вшаблон в Smarty-переменную $WRAPPER. Для этого, вместо sajax_set_javascript() нужноиспользовать sajax_get_javascript(). Разница между sajax_set_javascript() иsajax_get_javascript() примерно та же, что и между методами Smarty – display() и fetch(). Впервом случае функция выводит код на экран, а во втором случае она возвращает его дляприсвоения переменной.

Теперь посмотрим на шаблон chat.tpl:<html><head> <title>Пример 2</title> <script> <{$WRAPPERS}> function refresh_cb(new_data) { document.getElementById("wall").innerHTML = new_data; setTimeout("refresh_page()", 1000); } function refresh_page() { x_refresh(refresh_cb); } function add_cb() { // we don't care.. }

13

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 14: #16, Декабрь'2005 :: Ajax и PHP

Sajax – реализация Ajax в PHP

function add() { var line; var handle; handle = document.getElementById("handle").value; line = document.getElementById("line").value; if (line == "") return; x_add_line("[" + handle + "] " + line, add_cb); document.getElementById("line").value = ""; } </script></head><body x_onLoad="refresh_page();"> <form name="f" action="#" x_onSubmit="add();return false;"> <input type="text" name="handle" id="handle" value="Ник" x_onFocus="this.select()" style="width:130px;"> <input type="text" name="line" id="line" value="Ваше сообщение" x_onFocus="this.select()" style="width:300px;"> <input type="button" name="check" value="Отправить" x_onClick="add(); return false;"> <div id="wall"></div> </form></body></html>

В примере были созданы два поля для ввода ника и сообщения, а так же кнопка«Отправить». При нажатии этой кнопки, ник и текст сообщения записываются в файлdata.txt. Вывод на экран данных этого файла осуществляется один раз в секунду без пе-резагрузки страницы. Это делается функцией x_refresh(), враппером нашей PHP-функцииrefresh().

Sajax и кириллические кодировкиЕсли запустить предыдущий пример на выполнение и в качестве ника или сообще-

ния ввести кириллический текст, то вы имеете шанс получить «кракозябры» вместо этоготекста.

Это обусловлено тем, что Sajax использует при передаче данных метод JavaScriptescape(), который превращает специальные символы (в их число входят и киррилическиебуквы в данном случае) в символы вроде %u0431. Это происходит по причине «любви»escape() к юникоду.

Для поправки положения достаточно немного изменить наш шаблон chat.tpl и заме-нить в нем восьмую строку:document.getElementById("wall").innerHTML = new_data;

на следующую, подставив функцию декодирования unescape():document.getElementById("wall").innerHTML = unescape(new_data);

Теперь в браузере будет выводиться информация в правильной кодировке, однако вфайле data.txt все данные будут по прежнему хранится в закодированном виде (это отно-сится к кириллице). Если такой вариант вас не устраивает, то достаточно открыть файлSajax.php (собственно файл библиотеки Sajax), найти там сто тридцать пятую строку:

14

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 15: #16, Декабрь'2005 :: Ajax и PHP

Sajax – реализация Ajax в PHP

x.open(sajax_request_type, uri, true);

И заменить ее на следующую, подставив unescape():x.open(sajax_request_type, unescape(uri), true);

Теперь и в файл data.txt все будет записано в правильном виде.

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

15

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 16: #16, Декабрь'2005 :: Ajax и PHP

Ajax и PHP без использования XmlHttpRequest

Ajax и PHP без использованияXmlHttpRequest

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

Еще один способ динамической загрузки контента безобновления веб-страницы

Ajax стал одним из самых больших «открытий» за последний год и успел стать«умным словечком», что-то вроде Web 2.0. Как известно, Ajax может использоватьсядля разных целей и он на самом деле ускоряет работу веб-приложений. Эта технологияуже сейчас используется многими популярными сайтами, один из которых GMail (по-чтовый сервис Google). Помимо него можно привести примеры таких сайтов как Ta-DaList (http://www.tadalist.com/) и Fliсkr (http://www.flickr.com/). Даже Microsoft поддаетсяветру перемен и пытается перевести свои веб-приложения на эту технологию.

ВведениеСам способ реализации Ajax-приложений очень завязан на объекте

XmlHttpRequest. Большинство современных браузеров, таких как Firefox, уже имеютвстроенную поддержку этого объекта, но другие браузеры могут ее не иметь. К примеру,IE 6.0 поддерживает этот объект, однако он реализован в виде элемента ActiveX, что приопределенных настройках браузера может привести к тому, что пользователь будет ви-деть окно предупреждения об опасности ActiveX элемента или приложение не сработаетвовсе.

В этом руководстве я продемонстрирую вам, как использовать Ajax без необходи-мости работы с объектом XmlHttpRequest.

ОсновыЕсли мы не можем использовать XmlHttpRequest, то необходимо найти иной

способ подключать контент из другой странички без перезагрузки и прибегания к другимобъектам или нестандартным средствам. Отличным кандидатом на эту роль является тег<script>, который позволяет подключать внешние JavaScript файлы. Что если вместообычного JS-файла, мы попытаемся подключить PHP-файл, который генерирует и выдаеткод на JavaScript. Такой файл может выглядеть вот так:<?php $html = '<b>Это контент нашего движка Ajaxe</b>'; ?> div = document.getElementById('contentdiv'); div.innerHTML = '<?php echo $html; ?>';

Как только файл будет подключен к тэгу <script>, он попытается выполнитьinnerHTML для элемента div с ID равным ‘contentdiv’.

16

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 17: #16, Декабрь'2005 :: Ajax и PHP

Ajax и PHP без использования XmlHttpRequest

Тут возникает одна проблема – этот файл не должен быть подключен при загрузкестраницы, так как ему необходимо подключиться только после нажатия какой либо кноп-ки или иного события. Для этого создадим небольшой скрипт на JavaScript, что-то вродеэтого:// Получаем url для подключенияurl = document.x_location.href;xend = url.lastIndexOf("/") + 1;var base_url = url.substring(0, xend); function ajax_do (url) {// Начинается с http?if (url.substring(0, 4) != 'http') {url = base_url + url;}// Создаем новый JS элементvar jsel = document.createElement('SCRIPT');jsel.type = 'text/javascript';jsel.src = url;// Дописываем элемент к документуdocument.body.appendChild (jsel);}

Этот скрипт первым делом получает текущую директорию URL, и таким образоммы имеем базовый URL. Функция ajax_do() делает остальную работу. Первым делом онаопределяет, переданный в нее URL относится к другому домену, или является относи-тельным путем внутри своего.

Затем создается новый элемент с помощью функции createElement(). После этого,устанавливается атрибут src элемента script и элемент добавляется к телу документа, приэтом, подгружая нужный файл на который он ссылается.

Теперь нам нужна только обычная HTML-страничка, которая будет осуществлятьAjax-вызовы. К примеру:<html> <head> <title>Demo 1 - Основы</title> <script type="text/javascript" src="engine.js"></script> </head> <body> <div id="contentdiv"> </div> <input type="button" x_onClick="ajax_do ('page1.php');" value="Получитьконтент" /> </body></html>

Если вы попробуете этот пример в действии, то заметите, что он работает так жекак и «традиционный» Ajax и даже, вероятно, немного лучше в браузере IE. Правда сле-дует учесть, что в IE уровень безопасности не должен быть выше чем Medium (Средний).

Получение контентаЧтобы подключить обычный контент с другой странички (который не является

JavaScript-кодом) нам потребуется только дополнительный PHP-скрипт, который помо-жет решить некоторые проблемы.

17

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 18: #16, Декабрь'2005 :: Ajax и PHP

Ajax и PHP без использования XmlHttpRequest

Этот PHP-скрипт должен получать содержимое странички и затем отдавать его ввиде корректного JavaScript для установки innerHTML элемента.

Файл getfile.php может выглядеть следующим образом:<?php // Get URL and div if (!isset($_GET['url'])) { die(); } else { $url = $_GET['url']; } if (!isset($_GET['el'])) { die(); } else { $el = $_GET['el']; } // Make sure url starts with http if (substr($url, 0, 4) != 'http') { // Set error echo 'alert(\'Security error; incorrect URL!\');'; die(); } // Try and get contents $data = @file_get_contents($url); if ($data === false) { // Set error echo 'alert(\'Unable to retrieve "' . $url . '"\');'; die(); } // Escape data $data = str_replace("'", "\'", $data); $data = str_replace('"', "'+String.fromCharCode(34)+'", $data); $data = str_replace ("\r\n", '\n', $data); $data = str_replace ("\r", '\n', $data); $data = str_replace ("\n", '\n', $data); ?> el = document.getElementById('<?php echo $el; ?>'); el.innerHTML = '<?php echo $data; ?>';

Как вы можете видеть, первым делом получается содержимое файла с использова-нием функции file_get_contents() и затем выводится обычный JavaScript для установкисвойства innerHTML.

Функция Ajax-движка, которая будет работать с PHP-скриптом выглядит следую-щим образом:function ajax_get (url, el) {// Has element been passed as object or id-string?if (typeof(el) == 'string') {el = document.getElementById(el);} // Valid el?if (el == null) { return false; }// Does URL begin with http?if (url.substring(0, 4) != 'http') {url = base_url + url;}// Create getfile URLgetfile_url = base_url + 'getfile.php?url=' + escape(url) + '&el=' + escape(el.id);// Do Ajaxajax_do (getfile_url);return true;}

18

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 19: #16, Декабрь'2005 :: Ajax и PHP

Ajax и PHP без использования XmlHttpRequest

Первым делом функция проверяет, существует ли указанный элемент, затем созда-ет URL к файлу getfile.php, подключает страничку с помощью знакомой нам ajax_do()функции. Это просто и это работает!

Пример: Форма с использованием AjaxДавайте попробуем использовать наш движок для создания простой формы, кото-

рая будет автоматически проверять правильность заполнения полей, основываясь на сер-верном скрипте. Моя форма выглядит так:<html> <head> <title>Form Demo - Showing an Ajax Form</title> <script type="text/javascript" src="engine.js"></script> </head> <script type="text/javascript"> function submit_form() { // Get form values var name = document.getElementById('name').value; var email = document.getElementById('email').value; var website = document.getElementById('website').value; // Construct URL url = 'handle_form.php?name=' + escape(name) + '&email=' +escape(email) + '&website=' + escape(website); ajax_get (url, 'result'); } </script> <body> <div id="result"> </div> <b>Name: </b><input type="text" name="name" id="name" /> <b>Email: </b><input type="text" name="email" id="email" /> <b>Website: </b><input type="text" name="website" id="website" /> <input type="button" x_onClick="submit_form();" value="Send Form" /> </body></html>

А мой обработчик формы выглядит так:<?php // Check variables if (empty($_GET['name'])) { die ('<span style="color:red;">Please fill in your name!</span>'); } if (empty($_GET['email'])) { die ('<span style="color:red;">Please fill in your email address!</span>'); } if (empty($_GET['website'])) { die ('<span style="color:red;">Please fill in your website!</span>'); } echo 'Success! Your form has been submitted!'; ?>

Теперь попробуйте эти скрипты в работе. Для этого оставьте одно из полей пу-стым.

19

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 20: #16, Декабрь'2005 :: Ajax и PHP

Ajax и PHP без использования XmlHttpRequest

ЗаключениеВ этом руководстве я показал вам иной метод использования Ajax. Этот метод не

имеет тех недостатков, которые есть у XmlHttpRequest, что само по себе хорошо, но унего есть и собственные недостатки. К примеру, он не способен обрабатывать $_POSTпеременные – только $_GET.

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

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

Вы можете легко расширить этот простой пример и развить его до настоящегодвижка, который сможет работать со всеми браузерами и будет обрабатывать различныеситуации. Я тестировал свои примеры в Firefox, IE6 и Opera 7.1 и они не сработали толь-ко в Opera, но я думаю что это можно исправить (В Opera 8.5 все сработало – прим.Перев.).

http://www.phpit.net/article/ajax-php-without-xmlhttprequest/

20

P

HP

In

side

#16

Т

ема

с об

лож

ки

Page 21: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

Ошибки начинающих TDD-практиковСергей Юдин

Концепция Test Driven Development (TDD) может стать неэффек-тивной, если ее неправильно использовать. И наоборот, в рукахмастера она будет мощным оружием

С момента проведения PHP-конференции в Киеве в мае 2005 года прошло доста-точно много времени. Тогда мы (я и Павел Щеваев) постарались приложить максимумусилий для популяризации идеи TDD среди PHP-разработчиков. За время после конфе-ренции мы намного продвинулись вперед в плане TDD, и взгляд на некоторые вещи у насизменился. Я признаю, что мой доклад на тему «Целесообразность модульных тестов»получился немного однобоким. Вообще на конференции было очень много сказано о плю-сах тестирования, как здорово тесты помогают в разработке и рефакторинге, в про-фессиональном развитии программистов, но слишком мало – о минусах. О минусах иочень больших минусах тестирования, которые могут проявиться, если трактовать ииспользовать TDD неправильно.

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

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

Правильно понимаем TDD Начнем с того, что большинство разработчиков неправильно понимает идею

TDD. Самое типичное недоразумение, связанное с TDD: «Мы используем в своей работеSimpleTest или PhpUnit, значит, мы работаем в стиле TDD.» Этот совсем не обязательно.Люди, которые пишут (или пытаются написать) модульные тесты для своих классов – необязательно занимаются TDD.

Как-то в одной из TDD-рассылок я наткнулся на некую классификацию способовприменения модульных тестов разработчиками:

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

21

P

HP

In

side

#16

И

деи

Page 22: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

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

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

Только первый вариант можно считать полноценным TDD. Второй вариант – этотак называемая методика test-first development, то есть TDD без первой D – driven. Третийвариант никакого отношения к самому TDD не имеет, а должен применяться параллель-но в виде приемочных тестов.

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

Это вовсе не TDD и даже не test-first. Когда вы занимаетесь TDD, вы должны стре-миться минимизировать размер контекста, в котором вы работаете. Это относится как ктесту, так и к рабочему коду. Мы обычно пишем тесты очень мелкими шагами и не пыта-емся представить, как будет выглядеть окончательный код. Это позволяет очень раноувидеть зеленую линию и обойтись без debug сессии при начальном запуске тестов. Дажеесли и так понятно, как будет выглядеть все остальные тесты и сам рабочий код класса,мы предпочитаем написать короткий тест, затем небольшую часть рабочего кода. Затемможно двигаться быстрее и увереннее.

Конечно, каждый самостоятельно может определять, что для него «небольшиешаги», но общая рекомендация такая – старайтесь сокращать промежутки между запус-ками тестов. При активной разработке мы обычно запускаем тесты раз в 2-3 минуты идаже чаще. Это позволяет проверять написанный код сразу же, не теряя контекста, тоесть, помня все детали только что измененного кода.

Рассмотрим «активный» и «приемочный» способы использования тестов (см.выше). Мы начинали свою практику TDD именно с «активного» способа применения мо-дульных тестов, рисуя UML-диаграммы, а затем старались при помощи тестов реализо-вать свои задумки в коде. Но постепенно мы отказались от повседневного примененияэтой практики. Дело в том, что если разрабатывать, ставя во главу test-ability, то есть воз-можность протестировать код, то полученная реализация всегда будет отличаться заду-манной, а время, затраченное на детальную проработку дизайна, становится жаль.

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

В конце концов, TDD никак не может заменить аналитические способности разра-ботчика, его умение предугадывать развитие проекта. Но TDD реально позволяет вы-браться из ситуации архитектурного тупика (design deadlock), когда вообще непонятно,как должна выглядеть реализация.

22

P

HP

In

side

#16

И

деи

Page 23: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

«Приемочный» способ использования тестов искажает смысл понятия «модуль».Обычно в данном случае разработчик пишет тесты на классы высших уровней (фасады).В этом случае понятие модуля (unit) становится слишком большим, поэтому тест стано-вится бесполезным при поиске ошибок. Такой тест зачастую увеличивается в размере иусложняется, его становится тяжелее читать и понимать. Такой критерий как test-abilityздесь уже не играет главной роли, поэтому влияние тестов на дизайн будет значительноменьше, чем в традиционном TDD.

Обязательным условием успешного внедрения TDD является фаза рефакторинга.После получения рабочего кода и зеленой полосы необходимо обязательно критическипосмотреть на код и сделать хотя бы несколько шагов для улучшения читабельности ипонятности кода. Идеально, если после рефакторинга код вообще бы не требовал inlineкомментариев. Важно также как можно чаще при этом запускать тесты, чтобы не сталки-ваться с красной полосой. В книге Мартина Фаулера «Рефакторинг: улучшение дизайнасуществующего кода» техника рефакторинга описана очень подробно.

Правильно внедряем TDD Разработку через тестирование никак нельзя освоить за пару недель. По нашему

опыту и опыту некоторых других разработчиков на первоначальное изучение методик те-стирования уходит где-то 3-4 месяца. Еще полгода-год нужно на перестройку сознанияразработчика. Итого – около года, иногда дольше. Почитайте книги по TDD – это 60%код и еще 35% - комментарии к ним и 5% теории. TDD – это набор лучших практик (bestpractices), самым лучшим образом зарекомендовавших себя в разработке программногообеспечения. Многие из них нужно попробовать на себе, чтобы понять их важность. TDDдолжен стать каждодневной реалией вашего рабочего процесса.

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

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

Многие разработчики (и мы в том числе) заметили, что внедрять TDD лучшевсего или на новом проекте (можно учебном), или же с отдельных классов. Мы вообщене рекомендуем начинать внедрение TDD на реальных коммерческих проектах, особеннона больших и со сложным наследием. Без унаследованного кода (legacy code) внедрятьTDD намного проще, так как в этом случае есть возможность полностью контролироватьситуацию и принимать какие угодно решения.

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

23

P

HP

In

side

#16

И

деи

Page 24: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

Идеально, если на начальном этапе внедрения TDD вы не будете ограниченысроками. Первое время при внедрении TDD происходит значительное снижение скоростиработы – где-то в 2-3 раза, поэтому многие разработчики срываются и пишут код без те-стов. После того, как вы освоите большинство продвинутых методик тестирования, ско-рость снова возрастет и даже будет выше, чем раньше.

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

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

Если же у вас появились серьезные проблемы с тестами, посмотрите на списокнаиболее часто появляющихся запахов тестового кода – может быть вы наткнулись наодин или сразу нескольких из них. Это позволит понять причины своих неудач и не бро-сить начатое. Список запахов тестового кода доступен в разделе TDD по адресуhttp://phpclub.ru/faq/wakka.php?wakka=TDD/TestCodeSmells.

Расширяем свои познания об ООП TDD и ООП идут рука об руку. Поэтому TDD очень плохо подходит для разра-

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

Как-то на форуме сайта sitepoint.com я наткнулся на очень интересное высказы-вание Маркуса Бейкера (создателя пакета для тестирования SimpleTest) насчет объектно-ориентированного программирования. Суть этого высказывания сводится к тому, чтобольшинство разработчиков начинает использование ООП, не разобравшись до конца(или вообще не разобравшись) в его сути.

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

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

24

P

HP

In

side

#16

И

деи

Page 25: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

Мы начинали практику TDD осенью 2003 года с типичной ситуации, описаннойМаркусом Бейкером. У нас была своя доморощенная CMS, где каждый класс был бого-подобным, везде встречались такие модные словечки, как Factory, Singleton, Fa?ade и т.д.Но это была ужасная система. И в этой ситуации мы начали внедрение TDD. Угадайте кчему мы пришли через полгода? Практически к тому же самому!

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

Вот список книг, которые любой TDD-практик просто обязан прочитать (mustread) и иметь в любой момент на своем столе:

• Э. Гамма и др. «Design patterns» (GOF).

• М. Фаулер «Refactoring: Improving the Design of Existing Code».

• М. Фаулер «Patterns of Enterprise Applications Architecture».

• Р. Мартин «Agile software development».

Все эти книги есть на русском языке. Я уверен, что по мере совершенствования ва-ших навыков модульного тестирования вам захочется перечитать эти книги не раз и недва. Также очень полезной оказалась книга V. Manson «Junit In Action», к сожалению еепока нет на русском языке. Несмотря на то, что она написана для Java, многие идеи, опи-санные в этой книге, применимы к любому языку. Более полный список книг вы можетенайти в разделе TDD по адресу http://phpclub.ru/faq/wakka.php?wakka=TDD/TDDBooks

Любой продвинутый TDD-практик (да в принципе любой программист) долженотлично понимать, что такое зависимости между отдельными классами и подсистемами,как эти зависимости снижать, какие при этом могут использоваться методики, что такоеклиент-ориентированный API и т.д. Вы должны стремиться к пониманию сутибольшинства базовых патеров, например, Декоратор или Стратегия, в каких случаях ихследует применять.

Мне лично очень сильно помогла в плане ООП развития книга Р.Мартина «Бы-страя разработка программ» (Agile software development). Кстати, когда мы только начи-нали практику TDD, нам казалось, что мы очень отлично подкованы в плане ООП, одна-ко оказалось, что это далеко не так. Кстати, это заметили не только одни мы. Люди, кото-рые имеют опыт программирования 5 и более лет, по прошествии лишь 3-4 месяцев прак-тики TDD признают, что тесты заставили их посмотреть на многие вещи другими глаза-ми. Написание тестов очень наглядно показывают целесообразность многих ООП мето-дик, которые многие знают и так, но эти знания лежат у них обычно мертвым грузом.

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

25

P

HP

In

side

#16

И

деи

Page 26: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

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

TDD – это не самоцель Тесты – это не вещь в себе. Но часто разработчики впадают в крайность – это си-

туация, когда тестам начинают уделять повышенное внимание. Разработчики пишутслишком много тестов, проверяют все и вся. И это однажды перерастает в разработкуориентированную на тесты (testing oriented development anti-pattern).

Джемс Гринвуд так описывает этот анти-паттерн: «Когда неопытные или введен-ные в заблуждение программисты продолжают писать тесты, хотя в этом нет никакогосмысла с практической или финансовой точки зрения. При этом они думают, что это иесть TDD и, добавляя в систему все новые и новые тесты, они увеличивают еестоимость». Думается, что комментировать это определение нет смысла.

Попробую описать другой случай, когда тесты становятся самоцелью и мешаютразвитию проекта. Иногда это связывают с запахом «Чрезвычайное упования на мок-объекты», но иногда причина кроется в другом. Мы сталкивались с данной проблемойдостаточно давно, но последствия дают о себе знать до сих пор. Суть ее такова: у нас былкод, который очень трудно поддавался тестированию, так как он не был создан с учетомtest-ability. Но, не понимая сути TDD, мы вместо того, чтобы искать причины в дизайнесистемы, делали все возможное, чтобы просто написать тесты.

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

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

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

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

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

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

26

P

HP

In

side

#16

И

деи

Page 27: #16, Декабрь'2005 :: Ajax и PHP

Ошибки начинающих TDD-практиков

Теперь пришло небольшое прозрение. Сейчас я понимаю, что это всего лишьинструмент, а то, как этот инструмент используется, зависит от человека, который этоинструмент держит в руках. В чьих-то руках он может приносить много пользы, а в дру-гих - много вреда. Если вам нравится все то, что сулит TDD, то будьте готовы к жертвам:это и потеря скорости разработки в первое время, и жесткая дисциплина и самоконтроль,интенсивное обучение и т.д. Все эти жертвы потом с лихвой окупятся. Многие же не вы-держивают и возвращаются к прежнему стилю работы. Но, по нашему мнению, а такжепо мнению некоторых знакомых нам TDD-практиков, как только разработчик почувство-вал зависимость от «зеленой полосы», узнал, что такое полный контроль за кодом, тоесть стал инфицированным тестами (test-infected), он уже никогда не откажется от тести-рования. Пока никто из наших знакомых не жалеет времени, потраченного на изучение иэксперименты с TDD. Я очень надеюсь, что эта статья поможет кому-то ускорить внедре-ние TDD и избежать тех ошибок, которые мы допускали.

Полезные ссылки:Раздел по TDD на phpclub.ru - http://phpclub.ru/faq/wakka.php?wakka=TDD

27

P

HP

In

side

#16

И

деи

Page 28: #16, Декабрь'2005 :: Ajax и PHP

Основы использования PHP для работы с FTP

Основы использования PHP дляработы с FTP

Авторы: Сообщество developersdigest.org/wiki/Перевод: Андрей Олищук

Руководство затрагивает основы использования PHP для работыс FTP протоколом

По прочтению руководства вы сможете:

• Устанавливать соединения с FTP-сервером.

• Авторизовываться с вашим логином и паролем.

• Проверять статус соединения.

• Загружать на сервер файлы.

• Проверять статус загрузки.

• Закрывать соединения.

• Использовать дополнительные возможности.

Подключение к FTP-серверуУстановка соединения

Установка соединения при помощи PHP – ничего нет проще. Вы сможете подклю-читься к серверу, используя всего одну строку кода. <?php // Установка соединения $ftp_server = "ftp.developersdigest.org"; $conn_id = ftp_connect($ftp_server); ?>

АвторизацияПосле того, как соединение было установлено, вы можете авторизоваться на серве-

ре со своим логином и паролем.<?php // Авторизация $ftp_user_name = "your_username"; $ftp_password = "your_pass"; $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_password); ?>

28

P

HP

In

side

#16

И

деи

Page 29: #16, Декабрь'2005 :: Ajax и PHP

Основы использования PHP для работы с FTP

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

соединения, чтобы убедиться, что все прошло хорошо.<?php // Проверка статуса соединения if ((!$conn_id) || (!$login_result)) { echo "Ошибка подключения!\n"; echo "Попытка подключения к $ftp_server под пользователем $ftp_user_name"; exit; } else { echo "Подключение к $ftp_server под пользователем $ftp_user_name прошлоуспешно"; } ?>

Передача файловЗагрузка файлов на сервер

Пришло время для самого интересного – загрузки файлов. Существует простейшаяфункция, которая добавляет «вкусности» в работу с FTP.<?php // загружаем файл $upload = ftp_put($conn_id, $destination_file, $source_file, FTP_BINARY); ?>

Вот так! Функция ftp_put() получает в качестве параметров следующие данные: idсоединения, путь и имя будущего файла, и путь и имя закачиваемого исходного файла.Последний параметр определяет метод загрузки и может быть бинарным (FTP_BINARY)или ASCII (FTP_ASCII) – это зависит от типа файла, который вы собираетесь закачать.

Проверка статуса загрузки После того как загрузка завершена, будет неплохо проверить – прошла ли она

успешно. К примеру, обрыв соединения в процессе загрузки вызовет ее прерывание ифайл не будет успешно загружен. Это так же просто, потому как переменная $upload бу-дет содержать результат выполнения функции ftp_put() (это будет TRUE в случае успехаи FALSE в случае ошибки).<?php // Проверим статус загрузки if (!$upload) { echo "Загрузка не удалась!"; } else { echo "Загрузка $source_file на $ftp_server под именем $destination_fileзавершена успешно"; } ?>

Закрытие FTP-соединенияЧтобы сэкономить системные ресурсы, всегда необходимо закрывать FTP-соедине-

ния.

29

P

HP

In

side

#16

И

деи

Page 30: #16, Декабрь'2005 :: Ajax и PHP

Основы использования PHP для работы с FTP

<?php // Закрываем FTP поток ftp_close($conn_id); ?>

Получение информации о размере файла Для получения размера файла можно использовать функцию ftp_size(), которая воз-

вращает размер файла в байтах.

Синтаксис:int ftp_size ( resource ftp_stream, string remote_file )

Пример:<?php $file = "your_file.txt"; // Получаем размер $file $size = ftp_size($conn_id, $file); ?>

Удаление файла с сервера Загружая файлы на сервер, вы всегда имеете возможность удалить их в послед-

ствии. Для этого необходима функция ftp_delete().

Синтаксис:bool ftp_delete ( resource ftp_stream, string path )

Пример:<?php $file = "delete_me.txt"; // Пробуем удалить $file if (ftp_delete($conn_id, $file)) { echo "$file успешно удален\n"; } else { echo "Не могу удалить $file\n"; } ?>

Создание директорий (каталогов)Если вам необходимо создать директорию (каталог), то можно использовать функ-

цию PHP – mkdir().

Синтаксис:string ftp_mkdir ( resource ftp_stream, string directory )

Пример:<?php $dir = "path/to/dir"; // Пробуем создать директорию $dir

30

P

HP

In

side

#16

И

деи

Page 31: #16, Декабрь'2005 :: Ajax и PHP

Основы использования PHP для работы с FTP

if (ftp_mkdir($conn_id, $dir)) { echo "Успешно создана $dir\n"; } else { echo "При создании $dir возникли проблемы\n"; } ?>

Смена директорииПодключаясь к FTP-серверу, вы попадаете в определенную директорию. Для того

чтобы перейти в другую, используйте функцию ftp_chdir().

Синтаксис:bool ftp_chdir ( resource ftp_stream, string directory )

Пример:<?php $dir = "dir"; // Пробуем попасть в директорию $dir if (ftp_chdir($conn_id, $dir)) { echo "Успешно перешли в $dir\n"; } else { echo "При переходе в $dir возникли проблемы\n"; } ?>

Удаление директорииЛишние директории можно удалить функцией rmdir().

<?php bool ftp_rmdir ( resource ftp_stream, string directory ) $dir = "path/to/dir"; // Пробуем удалить директорию $dir if (ftp_rmdir($conn_id, $dir)) { echo "Успешно удалили $dir\n"; } else { echo "Проблема при удалении $dir\n"; } ?>

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

Переименование файлов и директорий Если возникла необходимость переименовать файл или директорию на FTP-серве-

ре, то используйте функцию ftp_rename();<?php bool ftp_rename ( resource ftp_stream, string oldname, string newname ) $old_file = "path/to/old_file.txt"; $new_file = "path/to/new_file.txt"; // Пробуем переименовать $old_file в $new_file if (ftp_rename($conn_id, $old_file, $new_file)) { echo "Успешно переименовали $old_file в $new_file\n";

31

P

HP

In

side

#16

И

деи

Page 32: #16, Декабрь'2005 :: Ajax и PHP

Основы использования PHP для работы с FTP

} else { echo "Возникла проблема\n"; } ?>

Получение списка файлов в директории Для получения массива имен файлов в определенной директории, можно использо-

вать функцию ftp_nlist().<?php array ftp_nlist ( resource ftp_stream, string directory ) // Получаем массив с именами файлов $contents = ftp_nlist($conn_id, "."); ?>

Полный список FTP-функций можно найти по ссылке:

http://ru.php.net/manual/en/ref.ftp.php

Оригинал материала: http://developersdigest.org/wiki/index.php/Uploading_with_FTP

32

P

HP

In

side

#16

И

деи

Page 33: #16, Декабрь'2005 :: Ajax и PHP

Сборка PHP 5 с драйверами mysql и mysqli одновременно

Сборка PHP 5 с драйверами mysql иmysqli одновременно

Автор: Джон БернсПеревод: Андрей Олищук

Бывают случаи, когда на одном сервере одновременно должныработать приложения с использованием интерфейсов MySQL иMySQLi. Джон Бернс расскажет как этого добиться на Linux

На протяжении нескольких лет библиотека mysql (иногда ее называют ext/mysqlдля большей понятности) являлась стандартом PHP-разработки и огромнейшее числоPHP-приложений, работающих с MySQL использует именно эту библиотеку. С прихо-дом PHP 5 и MySQL 4.1 появилось новое расширение mysqli, название которого расшиф-ровывается как «MySQL Improved» (улучшенная).

Итак, чего же такого хорошего есть в mysqli и почему нужно переходить на эторасширение? Ответ прост: новый драйвер mysqli, работающий под PHP 5 просто превос-ходен! (в оригинале используется более грубое выражение – kicks ass, - прим. переводчи-ка).

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

• Объектно-ориентированный интерфейс

• Поддержка нового бинарного протокола, представленного в MySQL 4.1. Новый прото-кол гораздо более эффективен чем старый и позволяет использовать некоторые новыеособенности MySQL такие как, например, подготовленные выражения.

• Поддержка всех возможностей клиентской библиотеки MySQL, включая способностьустанавливать расширенные настройки соединения с помощью mysql_init().

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

• Лучшая скорость. На некоторых операциях ext/mysqli превосходит ext/mysql в 40 раз.

• Лучшая безопасность. В старых версиях СУБД MySQL были некоторые уязвимости,которые позволяли атакующему извлекать хеши паролей из сети и воссоздавать поним пароли пользователей. Новая процедура аутентификации более надежна и похожана процедуры аутентификации таких инструментов как SSH.

Но если mysqli такая великолепная штука, то почему все еще не все начали еюпользоваться? Реальность такова, что много кода написано под расширение mysql и он небудет работать с mysqli. Не всегда есть возможность переделывать этот код или серверможет содержать готовые приложения, которые не работают с mysqli (это, к примеру,MediaWiki, WordPress), а стандартным образом собрать PHP с двумя расширениями сра-зу не получится.

33

P

HP

In

side

#16

И

деи

Page 34: #16, Декабрь'2005 :: Ajax и PHP

Сборка PHP 5 с драйверами mysql и mysqli одновременно

Хорошие новости состоят в том, что mysql и mysqli все же могут сосуществовать наодном сервере и вы можете позволить старым приложениям работать с ext/mysql, а новыеразрабатывать на mysqli.

Я приведу способ установки PHP 5 с активированными и mysql и mysqli. Для этого,когда вы запускаете команду ./configure, используйте следующий синтаксис:./configure --with-mysql=/usr –with-mysqli=/usr/bin/mysql_config

Заметьте, что директории для mysql и mysqli различны! Так и должно быть. Разме-щение этих директорий может быть различным, в зависимости от операционной систе-мы, которую вы используете. Итак, наберите в командной строке:slocate mysql_config

На RedHat/Fedora ответ может быть следующим:/usr/bin/mysql_config

Эта директория mysql_config и будет являться директорией для --with-mysqli, в товремя, как директория на два уровня выше mysql_config (в нашем случае это /usr) будетсоответсвовать для --with-mysql.

Но такая команда ./configure создаст неправильный makefile, поэтому созданныйфайл makefile необходимо открыть в текстовом редакторе и найти строку, которая начи-нается с EXTRA_LIBS:EXTRA_LIBS = -lcrypt -lcrypt -lmysqlclient -lpng -lz -lz -lresolv -lm -ldl -lnsl-lxml2 -lz -lm -lxml2 -lz -lm -lmysqlclient -lcrypt -lnsl -lm -lz -lnss_files-lnss_dns -lresolv -lnss_files -lnss_dns -lresolv -lxml2 -lz -lm -lcrypt -lxml2-lz -lm -lcrypt

Вы можете заметить, что параметр “-lmysqlclient” встречается дважды. Удалитеодин из них и сохраните файл. Теперь, если запустить команду make, PHP 5 скомпилиру-ется как надо и будет поддерживать оба расширения – mysql и mysqli!

Это все!

34

P

HP

In

side

#16

И

деи

Page 35: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Учебник по созданию компонентJoomla!

Автор: Джозеф ЛеБланкПеревод: Григорий Федоринов

Joomla! Является одной из наиболее популярных открытых си-стем управления контентом. На примере создания компонента«Ежедневные сообщения» автор демонстрирует принцип разра-ботки компонент для этой CMS

Это пособие должно помочь вам создать компонент с функциональной зонойадминистрирования. После прочтения вы будете понимать как работают некоторыеклассы из ядра Joomlaи сможете использовать наилучшие методы для создания своихсобственных компонентов. Полностью законченная версия компонента «Ежедневныесообщения » доступна в приложении к журналу. Компонент также может устанавли-ваться на Mambo 4.5 и 4.5.1. Дополнительную информацию на русском языке можнонайти здесь: http://myjoomla.ru/content/view/12/28/

Различные люди будут понимать функциональность компонентов joomla по разно-му. Разработчики с опытом разработок на PHP могут начинать с файла dailymessage.php(файл который управляет фронтендом – зоной пользователя) и admin.dailymessage.php(файл который управляет бекендом – зоной администратора). Остальные будут начинатьпонимать с XML файла в котором описаны все содержащиеся файлы в компоненте, атакже SQL – запросы для создания таблиц необходимых для компонента в базе данных.dailymessage.php admin.dailymessage.php admin.dailymessage.html.php dailymessage.class.php toolbar.dailymessage.php toolbar.dailymessage.html.php install.dailymessage.php / uninstall.dailymessage.php XML file

dailymessage.phpЭтот файл отображает то что увидит пользователь когда компонент «Ежедневные

Сообщения» загружен. Хотя этот код прост, это все что необходимо для генерированияHTML для любой версии Joomla. Это только файл, который копируется в папкуcomponents/com_dailymessage.

Расскажем подробнее что в этом файле находится:defined('_VALID_MOS') or die( 'Direct Access to this location is not allowed.');

Эта строка описывает, что только Joomla может вызвать на исполнение этот файл.Именно с нее должны начинаться все php-файлы – это сделано в целях безопасности.

35

P

HP

In

side

#16

Б

онус

Page 36: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

global $database; Объект $database объявляется в ядре Joomla и директива 'global' делает этот объект

доступным в компоненте.// Получаем информацию о конфигурации $database->setQuery("SELECT * FROM mos_joe_dailymessage_conf LIMIT 1"); $rows = $database->loadObjectList(); $row = $rows[0];

Запуск MySQL запросов в Joomla состоит из 2-х этапов. Первый: вы используетеметод setQuery() чтобы сохранить текст SQL запроса в объекте $database. Когда вы ис-пользуете функцию, такую как loadObjectList(), то SQL запрос выполнятеся и возвраща-ется результат запроса. Строка $row = $rows[0] присваивает переменные из первогообъекта в списке в массив $row. При этом мы возвращаем информацию о конфигурациииз базы данных, которая хранится в одной записи.

Также , в MySQL запросах Joomla можно заменять префикс ‘mos_’ на '#_' в этомслучае даже если префикс установленной базы данных joomla отличается от ‘mos_’, тозапрос все равно остается работоспособным. Это позволяет запускать компонент насайтах где установлено несколько CMS в одной базе данных, отличающихся префиксом.$bold = $row->bold; $italic = $row->italic; $underline = $row->underline; $showdate = $row->showdate;

После загрузки результата запроса в массив, мы помещаем отдельные значения измассива в переменные для дальнейшего их использования. $starttags = ""; $endtags = ""; if($bold == 1) { $starttags .= "<b>"; $endtags = "</b>" . $endtags; } if($italic == 1) { $starttags .= "<i>"; $endtags = "</i>" . $endtags; } if($underline == 1) { $starttags .= "<u>"; $endtags = "</u>" . $endtags; }

Этот код выстраивает начало и конец строки настроек, которые были выбраны избазы данных. Эти строки будут использованы ниже для форматирования сообщения. //получение данных $database->setQuery("SELECT * FROM mos_joe_dailymessage WHERE published = '1'");$rows = $database->loadObjectList();

36

P

HP

In

side

#16

Б

онус

Page 37: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Используя объект $database как показано выше мы устанавливаем запрос и выво-дим содержание сообщений из таблицы в список объектов $rows.?><table><?

Теперь мы начинаем вывод HTML кода. Тег ?> разрешает использовать HTML вphp файле пока не начнется тег <?. В противном случае надо использовать оператор echo().foreach($rows as $row) { if($showdate == 1) echo "<tr><td>" . mosFormatDate($row->date) . "</td>"; else echo "<tr>"; echo "<td>" . $starttags . $row->message . $endtags . "</td></tr>"; }

Этот цикл просматривает каждый объект в массиве объектов $rows и загружает со-держание в $row. Теперь мы способны вывести информацию и строки компоновки, кото-рые выведут должным образом отформатированный HTML. ?></table>

Вывод заканчивается закрытием тега table.

admin.dailymessage.phpЭтот файл управляет видом, который видит администратор, когда конфигурирует

компонент. Большая часть вида генерируется через функцию HTML_joeDailyMessage [отскромности я не умру :) ] находящуюся в файле admin.dailymessage.html.php .<?php defined('_VALID_MOS') or die('Direct Access to this location is not allowed.'); // проверим что пользователь имеет доступ к этой функции if (!($acl->acl_check( 'administration', 'edit', 'users', $my->usertype,'components', 'all' ) | $acl->acl_check( 'administration', 'edit', 'users', $my->usertype,'components', 'com_dailymessage' ))) { mosRedirect( 'index2.php', _NOT_AUTH ); }

Так выполняется проверка чтобы убедится что пользователь является администра-тором. require_once($mainframe->getPath( 'admin_html' ) ); require_once($mainframe->getPath( 'class' ) );

37

P

HP

In

side

#16

Б

онус

Page 38: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Эти две строки включают файлы admin.dailymessage.html.php иdailymessage.class.php. Функция getPath() возвращает соответствующие полные пути иимена файлов.$id = mosGetParam( $_REQUEST, 'cid', array(0) ); if (!is_array( $id )) { $id = array(0);

Главный вид имеет форму на которой расположен список состоящий из чекбоксовимеющий name = 'cid.' Функция mosGetParam() возвращает этот массив и сохраняет впеременной $id. Если массив не предстален (например когда загружена первая страница),$id устанавливается в пустой массив чтобы предотвратить ошибки, которые могли бывозникнуть в дальнейшем. switch($act) { case "configure":

switch($task) { case "save": saveConfiguration($option); break;

default: listConfiguration($option); break;

} break; default:

switch ($task) { case "save" : save($option); break; case "edit" : edit( $option, $id ); break;

case "new" : $id = ''; edit( $option, $id);

38

P

HP

In

side

#16

Б

онус

Page 39: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

break; case "delete" : del($option, $id); break; case "publish" : publishMessage($option, '1', $id); break;

case "unpublish" : publishMessage($option, '0', $id); break;

case "listMessages" : default: listMessages($option); break;

} break; }

Теперь наступает подходящий момент поговорить о различиях между $task и $act.Когда администратор делает щелчок на кнопке "publish" или "save," действие должнобыть передано компоненту. Это достигается через переменную $task. Эта кнопка исполь-зуется для различных форм и это необходимо для того чтобы компонент узнал какая фор-ма была отправлена в данный момент. Теперь настает черед переменной $act. В главномменю, при выборе Daily Message, появляется два субменю - опции: Edit Messages иConfigure. Эти опции называются 'all' и 'configure’ соответственно.

Компонент Daily Message использует оператор switch, чтобы выбрать действие, ко-торое будет совершено. Внешний переключатель основан на переменной $act, котораяможет принимать значения такие как 'all' и 'configure'. function saveConfiguration($option) { global $database; $row = new joeDailyMessageConf($database);

Теперь описание функций для обработки различных заданий. Первая будет об-новлять базу данных с новыми переменными, когда кто-нибудь нажмет кнопку 'save' настранице конфигурации. Первое, переменная $option variable применяется в функции ибудет установлена в 'com_dailymessage' окружением Joomla.

39

P

HP

In

side

#16

Б

онус

Page 40: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Это значение будет передано после того как пользователь зайдет в администра-торскую часть данного компонента. Следующее объект $database уже определен внефункции. Когда мы декларируем какой либо объект $row например joeDailyMessageConf[defined in dailymessage.class.php], являющийся расширением класса mosDBTable. Объек-ты основаны на mosDBTable имют много методов, которые позволяют упростить процессзаписи информации в базу.// bind it to the table if (!$row -> bind($_POST)) { echo "<script> alert('" .$row -> getError() ."'); window.history.go(-1); </script>n"; exit();

Этот код использует наследованный метод bind() от класса mosDBTable для полу-чения значения переменных из массива post и копирования их в объект $row. Если по-пытка использовать этот метод не удалась, a Javascript показывает сообщения об ошиб-ке. Ошибка показывается Javascript как всплывающее окно, которое возвращает пользо-вателя на предыдущую страницу. // сохраняет запись в базе if (!$row -> store()) {

echo "<script> alert('" .$row -> getError() ."'); window.history.go(-1); </script>n"; exit();

}

Эта часть кода описывает попытку сохранить информацию из объекта $row в базуданных. Обработка ошибок такая же как и в предыдущей части. mosRedirect("index2.php?option=$option&act=configure","ConfigurationSaved"); }

В заключении, если все прошло успешно, пользователь перемещается назад к стра-нице конфигурирования с сообщением "Configuration Saved", которое будет показановверху экрана. Переменная $option, говорит Joomla страница какого компонента будетиспользоваться т.е. если значение переменной 'com_dailymessage' то выводится страницаадминистрирования компонента Daily Message. Замечание: если URL не содержит пере-менную 'act' со значением 'configure', то он перемещается на страницу по умолчаниюкомпонента Daily Message: редактирование сообщений. function listConfiguration($option) { global $database; $database->setQuery("SELECT * FROM mos_joe_dailymessage_conf" ); $rows = $database -> loadObjectList();

40

P

HP

In

side

#16

Б

онус

Page 41: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Эта функция загружает текущую конфигурацию из базы данных и показывает ее ввиде формы, при этом значения могут быть отредактированы администратором. Вызыва-ется соответствующий запрос и результат загружается в объект $rows как список объек-тов.if ($database -> getErrorNum()) { echo $database -> stderr(); return false; }

Если здесь будет ошибка в запросе, то этот код сообщит эту ошибку и остановитвыполнение функции, при этом будет загружена страница без значений конфигурации.HTML_joeDailyMessage::listConfiguration($option,$rows); }

Это вызывает функцию listConfiguration объекта HTML_joeDailyMessage из файлаdailymessage.class.php file.function publishMessage( $option, $publish=1 ,$cid ) { global $database, $my; if (!is_array( $cid ) || count( $cid ) < 1) { $action = $publish ? 'publish' : 'unpublish'; echo "<script> alert('Select an item to $action'); window.history.go(-1);</script>n"; exit; }

Когда администратор хочет опубликовать письмо эта функция устанавливает флаг'published' сообщения в '1.' Первое мы должны определить действительно ли действие яв-ляется публикацией. Если нет, то выводим ошибку и редиректим пользователя на преды-дущую страницу. Строка, где $action устанавливается посредством краткой версии ди-рективы 'if'. Переменная устанавливается в 'publish' если условие выполняется, т.е.$publish равно 1, аналогично если переменная установлена в 'unpublish.' Javascript пока-зывает сообщение и редиректит пользователя.$cids = implode( ',', $cid );

Если мы имеем статьи которые отмечены на публикацию, мы устанавливаем стро-ковую переменную $сids которая включает в себя весь список идентификаторов статей,находящихся в масссиве $id и разделяет переменные посредством запятых. Этот приемпозволяет нам просто вставить все это в SQL запрос. $database->setQuery( "UPDATE mos_joe_dailymessage SET published='$publish'" . "nWHERE id IN ($cids)" ); if (!$database->query()) { echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1);</script>n";

41

P

HP

In

side

#16

Б

онус

Page 42: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

exit(); }

Запрос отсылается в базу данных и любая ошибка будет показана при помощиJavascript.mosRedirect( "index2.php?option=$option" ); }

В заключении администратор редиректится назад к главной странице компонентаDaily Message в зоне администрирования.function save($option) { global $database; $row = new joeDailyMessage($database); // bind it to the table if (!$row -> bind($_POST)) { echo "<script> alert('" .$row -> getError() ."'); window.history.go(-1); </script>n"; exit(); } // store it in the db if (!$row -> store()) { echo "<script> alert('" .$row -> getError() ."'); window.history.go(-1); </script>n"; exit(); } mosRedirect("index2.php?option=$option", "Saved"); }

Эта функция обычно идентична с saveConfiguration(), только она записывает стро-ку в базу с типом joeDailyMessage и редиректит на страницу по умолчанию (редактиро-вание сообщений) "Saved."function del($option, $cid) { global $database; if (!is_array($cid) || count($cid) < 1) { echo "<script> alert('Select an item to delete'); window.history.go(-1);</script>n";

42

P

HP

In

side

#16

Б

онус

Page 43: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

exit(); }

Список ежедневных сообщений для удаления обрабатывается следующей функци-ей. Если нет идентификаторов статей в массиве $cid [или $cid не является массивом],любая ошибка будет показана и администратор будет возвращен на предыдущую страни-цу. if (count($cid)) { $ids = implode(',', $cid); $database->setQuery("DELETE FROM mos_joe_dailymessage nWHERE id IN ($ids)"); }

Если сообщения, которые нужно удалить были выбраны, вызываем запрос, кото-рый удаляет эти сообщения. if (!$database->query()) { echo "<script> alert('" .$database -> getErrorMsg() ."'); window.history.go(-1); </script>n"; } mosRedirect("index2.php?option=$option"); }

Запрос на удаления выполнен и администратор возвращен на страницу по умолча-нию. function edit($option, $uid) { global $database; $row = new joeDailyMessage($database); if($uid){ $row -> load($uid[0]); }

Когда администратор выбирает сообщения для редактирования, эта функция будетзагружать соответствующее сообщение из базы данных в объект $row. Однако админи-стратор может редактировать только одно сообщение одновременно – первое $uid [0].HTML_joeDailyMessage::edit($option,$row); }

Функция edit() явлется методом класса HTML_joeDailyMessage, который генериру-ет соответсвующий вид – HTML страницу. Строка базы данных и имя компонента(com_dailymessage) передаются для того чтобы был сгенерирован соответствующийHTML-код.function listMessages($option) { global $database; $database->setQuery("SELECT * FROM mos_joe_dailymessage ORDER BY id" );

43

P

HP

In

side

#16

Б

онус

Page 44: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Эта последняя функция для показа страницы по умолчанию. Если не передаетсяконкретное задание, которое должно быть выполнено выполняется эта функция. Приэтом показывается список всех сообщений, которые администратор может редактиро-вать, удалять публиковать/делать неопубликованными. Запрос установлен для выборкисодержания ежедневного сообщения из таблицы. Он отсортирован по полю id т.к. онопредставляет собой автоинкремент, т.е. при добавлении новой записи id увеличивается.Такой способ позволяет легко создать уникальный ключ и позволяет выводить список впорядке создания. $rows = $database -> loadObjectList(); if ($database -> getErrorNum()) { echo $database -> stderr(); return false; } HTML_joeDailyMessage::listMessages($option, $rows); } ?>

Запрос выполняется и если имеет какие либо ошибки, они просто выводятся в стра-нице. Функция listMessages() в классе HTML_joeDailyMessage вызывается для генерациинеобходимой HTML странички.

admin.dailymessage.html.phpdefined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.');

Эта строка кода проверяет действительно ли этот файл вызывается Joomla.class HTML_joeDailyMessage{

Этот класс первоначально вызывается из файла admin.dailymessage.php и обрабаты-вает основной вывод HTML для зоны администрирования.function edit( $option, &$row ) {

Аргументами этой функции являются название компонента (com_dailymessage) истрока записи из базы данных загружанных в admin.dailymessage.php и показывает фор-му, где администратор может редактировать сообщение. ?><form action="index2.php" method="post" name="adminForm" id="adminForm"class="adminForm"><table border="0" cellpadding="3" cellspacing="0"><tr><td>Message: </td><td><input type="text" size="50" maxsize="100" name="message" value="<?php echo$row->message; ?>" /></td></tr><tr><td>Date: </td><td><input size="30" name="date" value="<? echo $row->date; ?>"></td></tr><tr><td>Published: </td>

44

P

HP

In

side

#16

Б

онус

Page 45: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

<td><? echo mosHTML::yesnoSelectList( "published", "", $row->published ); ?></td></tr>

Если строка записи базы данных загружена, то форма заполняется данными . За-метьте что поле 'Published' выводится при помощи метода yesnoSelectList классаmosHTML. Класс mosHTML декларирован в файле classes/mambo.php и доступен в лю-бом месте Joomla. Этот метод генерирует выпадающее меню с двумя значениями 'no' и'yes'. Если значение переменной $row-published равно 0, то будет выставлено значение'no'. Если значение 1, тогда будет выставлено 'yes'. Это более изящный метод созданияадминистративных интерфейсов, нежели чем использовать чекбоксы. </table><input type="hidden" name="id" value="<? echo $row->id; " ?>" /><input type="hidden" name="option" value="<?php echo $option; ?>" /><input type="hidden" name="task" value="" /></form><? }

Скрытые поля содержат идентификатор сообщения id, имя компонента, и задачуtask. Значение 'task' изначально не установлено, однако яваскрипт заполняет это поле взависимости от того какая кнопка нажата. function listConfiguration($option, &$rows) {

Эта функция вызывается для показа панели настроек компонента. ?> <form action="index2.php" method="post" name="adminForm"> <table cellpadding="4" cellspacing="0" border="0" width="100%"class="adminlist"> <? $row = $rows[0]; ?> <tr><td>Bold</td><td><? echo mosHTML::yesnoSelectList( "bold", "", $row->bold );?></td></tr> <tr><td>Italic</td><td><? echo mosHTML::yesnoSelectList( "italic", "", $row->italic ); ?></td></tr> <tr><td>Underline</td><td><? echo mosHTML::yesnoSelectList( "underline", "",$row->underline ); ?></td></tr> <tr><td>Show Date</td><td><? echo mosHTML::yesnoSelectList( "showdate", "",$row->showdate ); ?></td></tr> </table>

Эта форма заполняется данными из первой записи таблицыmos_joe_dailymessage_conf table [здесь только одна запись]. Метод yesnoSelectList() дела-ет простым управление данными на форме.<input type="hidden" name="option" value="<?php echo $option; ?>" /> <input type="hidden" name="task" value="" /> <input type="hidden" name="configid" value=<? echo $row->configid ?> /> <input type="hidden" name="act" value="configure" /> </form> <? }

45

P

HP

In

side

#16

Б

онус

Page 46: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Переменные option, task, configid, и act передаются скрытыми полями из формы.Переменная 'configid' выбирает, какая именно запись редактируется, хотя в данном слу-чае у нас только одна запись. Переменная 'act' передает в admin.dailymessage.php данныео том что события произошли на форме редактирования конфигурации, а не сообщений.Это обрабатывается оператором switch который выполняется в начале файла. function listMessages( $option, &$rows ) {

Функция выводит вид по умолчанию - список сообщений. <form action="index2.php" method="post" name="adminForm"> <table cellpadding="4" cellspacing="0" border="0" width="100%"class="adminlist"> <tr> <th width="20"><input type="checkbox" name="toggle" value=""onclick="checkAll(<?php echo count($rows); ?>);" /></th> <th class="title" width="25%">Message</th> <th>Date</th> <th width="25%">Published</th> </tr>

Это заголовки всех колонок, включая мастер чекбокс, который управляет всей ко-лонкой чекбоксов. <?php $k = 0; for($i=0; $i < count( $rows ); $i++) { $row = $rows[$i]; ?>

Начинаем цикл по массиву $rows, чтобы выбрать данные по каждому элементумассива. <tr class="<?php echo "row$k"; ?>">

Меняем название стиля строки в зависимости от тогд является эта строка четнойили нечетной. Мы начинаем со строки номер 0 и меняем ее на 1, и наоборот, для тогочтобы сделать таблицу удобной для чтения. <td><input type="checkbox" id="cb<?php echo $i;?>" name="cid[]" value="<?phpecho $row->id; ?>" onclick="isChecked(this.checked);" /></td>

Показывает чекбокс и осуществляет наполнение данных об идентификаторе данно-го элемента. Каждый чекбокс id имеет значение cbX, где X это номер позиции элементав списке. Имена определяются как массивы и значение устанавливается в id для того что-бы найти строку в базе данных.<td><a href="#edit" onclick="return listItemTask('cb<?php echo$i;?>','edit')"><?php echo $row->message; ?></a></td>

Создает ссылки содержащие текст сообщения. Когда происходит щелчок мышьюпо тексту сообщения ссылка будет автоматически проверять в начале строки чекбокс ипосле этого Javascript отправляет форму со значением задачи (task) равным 'edit.'<td><? echo mosFormatDate($row->date); ?></td>

46

P

HP

In

side

#16

Б

онус

Page 47: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Выводит дату сообщения, отформатированную в соответствии с форматом временифункцией mosFormatDate() которая декларирована в файле classes/mambo.php.<td align="center"> <?php if ($row->published == "1") { echo "<a href="javascript: void(0);" onClick="return listItemTask('cb$i','unpublish')"><img src="images/publish_g.png" border="0" /></a>"; } else { echo "<a href="javascript: void(0);" onClick="return listItemTask('cb$i','publish')"><img src="images/publish_x.png" border="0" /></a>"; } ?> </td>

Этот код показывает иконки 'published' или 'unpublished', зависящий от статуса со-общения. Если иконка нажата, форма отправляется и статус меняется на противополож-ный. <?php $k = 1 - $k; ?>

Изменения переменных, которые описывают цвет строки. Еденица меняется наноль, ноль на еденицу. </tr> <?php } ?> </table> <input type="hidden" name="option" value="<?php echo $option; ?>" /> <input type="hidden" name="task" value="" /> <input type="hidden" name="boxchecked" value="0" /> </form> <? } }

Скрытые поля option, task, and boxchecked в конце формы. Как 'boxchecked' так и'task' позже меняются Javascript. Boxchecked используется для того чтобы проверить чтоэлементы списка перед тем как запущено задание.

dailymessage.class.phpОпять проверяется что скрипты вызван из Joomla (Mambo).

<? defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.'); class joeDailyMessage extends mosDBTable { var $id = null; var $message = null; var $date = null; var $published = null;

Этот класс является расширением mosDBTable class, который предоставляет мно-гие методы, облегчающие работу с записями в таблице данных. Первое, переменнаяидентична полю в базе данных. По такому пути созданы объекты joeDailyMessage, загру-женные в объект желательные аргументы отсылаются в базу данных. function joeDailyMessage(&$db){

47

P

HP

In

side

#16

Б

онус

Page 48: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

$this->mosDBTable('mos_joe_dailymessage', 'id', $db); } }

Этот конструктор класса наследуется у объекта mosDBTable(), при этом имя табли-цы можно задавать не жестко, а использовать префикс, который будет заменен на нуж-ный [#_ shorthand для 'mos'] также желательно описать имя поля содержащее первичныйключ. class joeDailyMessageConf extends mosDBTable { var $bold = null; var $italic = null; var $underline = null; var $showdate = null; var $configid = null; function joeDailyMessageConf(&$db){ $this->mosDBTable('mos_joe_dailymessage_conf', 'configid', $db); } }

Класс joeDailyMessageConf создается по такому же принципу как и классjoeDailyMessage, основан он на таблце mos_joe_dailymessage_conf и поле 'configid' будетиспользовано в качестве первичного ключа.

toolbar.dailymessage.phpДля всех компонентов, Joomla загружает панель инструментов для Бекенда. Созда-

ние этого кода довольно однообразное, поскольку весь функционал довольно четко опи-сан. Код в этом файле зависит от значений переменных 'task' и 'act'.defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.'); require_once( $mainframe->getPath( 'toolbar_html' ) );

Первым делом проверьте что файл запускается из Joomla (Mambo)toolbar.dailymessage.html.php, и включите файл, который обрабатывает вывод HTML дляэтого меню.switch ( $task ) { case 'edit': menuDailyMessage::EDIT_MENU(); break; case 'new': menuDailyMessage::EDIT_MENU(); break; default: switch($act) {

case "configure": menuDailyMessage::CONFIGURE_MENU(); break; default: menuDailyMessage::DEFAULT_MENU(); break; }

P

HP

In

side

#16

Б

онус

Page 49: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

break; }

Замечание оба значения task - 'new' и 'edit' разделяют это меню. Это не вызываетконфликта потому что меню начинает запускать задачи функционально друг от друга независящие. Текущее значения `task` и 'act' описывают какой вид будет показан. Всеменю вызваются через методы класса menuDailyMessage, который находится в файлеtoolbar.dailymessage.html.php.

P

HP

In

side

#16

Б

онус

Page 50: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

toolbar.dailymessage.html.phpЭтот файл описывает класс menuDailyMessage, который имеет три метода для трех

различных видов. defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.');

Конечно проверяем что вызывается все из Joomla.class menuDailyMessage{ function DEFAULT_MENU() { mosMenuBar::startTable(); mosMenuBar::publish('publish'); mosMenuBar::unpublish('unpublish'); mosMenuBar::divider(); mosMenuBar::addNew('new'); mosMenuBar::editList('edit', 'Edit'); mosMenuBar::deleteList( ' ', 'delete', 'Remove' ); mosMenuBar::endTable();

У большинства приведенных функций первый параметр это значение переменной'task'. Для функции deleteList() первый аргумент необязательный он нужен для того что-бы показывать сообщения типа "вы действительно уверены в том что хотите удалитьэто". Второй аргумент это уже значение переменной 'task', и последний аргумент это над-пись для показа при наведении на пункт меню мышью – установка свойства изображения'alt'. Эта функция доступна для других кнопок.

Функции startTable() и endTable() выводят начало и конец кода таблицы, для тогочтобы Javascript мог нарисовать панель. Функция divider() рисует вертикальный раздели-тель для визуального разделения кнопок.function EDIT_MENU() { mosMenuBar::startTable(); mosMenuBar::back(); mosMenuBar::spacer(); mosMenuBar::save('save'); mosMenuBar::endTable();

Функция back() просто показывает иконку 'cancel' icon с текстом 'back.' Когда на-жимаешь на эту кнопку то возвращаешься к предыдущей странице. Функция spacer() ри-сует некоторое пустое пространство между иконками. } function CONFIGURE_MENU() { mosMenuBar::startTable(); mosMenuBar::save('save'); mosMenuBar::endTable(); } } ?>

P

HP

In

side

#16

Б

онус

Page 51: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

Install и uninstallФайлы install.dailymessage.php и uninstall.dailymessage.php предназначены для вы-

вода дополнительных сообщений когда компонент инсталлируется и деинсталлируется.Компонент Daily Message не имеет каких либо дополнительных сообщений.install.dailymessage.php: <?php function com_install() { } ?>

uninstall.dailymessage.php: <? function com_uninstall() { } ?>

dailymessage.xml<?xml version="1.0" ?>

Этот тег описывает версию XML используемую в этом документе. БольшинствоXML файлов написаны в версии 1.0. Вы можете прочитать больше об XML наwww.w3c.org.<mosinstall type="component">

Тег mosinstall говорит Joomla что за расширение будет установлено. Этот кодинсталлируется как компонент, однако могут еще устанавливаться модули, шаблоны,мамботы.<name>DailyMessage</name><creationDate>06/03/2004</creationDate><author>Joseph LeBlanc</author><copyright>This component in released under the GNU/GPL License</copyright><authorEmail> [email protected]</authorEmail><authorUrl>www.jlleblanc.com</authorUrl><version>1.0</version>

Эти теги рассказывают об имени компонента, даты его создания, авторе, копи-райтах, e-mail автора и его вебсайте, а также версии компонента. Эта информация в даль-нейшем будет отображаться в Бекенде. Имя компонент используется для создания дирек-тории с именем com_[имя компонента]. Оно не должно содержать пробелов и служеб-ных символов.

P

HP

In

side

#16

Б

онус

Page 52: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

<files><filename>dailymessage.php</filename></files>

Тег <files> открывает список файлов, которые будут скопированы во Фронтенд,имя файлов пишется в теге <filename> . В этом компоненте используется только одинфайл.<install><queries> <query>

DROP TABLE IF EXISTS `# __joe_dailymessage`; </query> <query>

CREATE TABLE `# __joe_dailymessage` (`id` INT NOT NULL AUTO_INCREMENT,`message` TEXT NOT NULL,`date` DATETIME NOT NULL,`published` TINYINT(1) NOT NULL,PRIMARY KEY (`id`))

</query> <query>

DROP TABLE IF EXISTS `# __joe_dailymessage_conf`; </query> <query>

CREATE TABLE `# __joe_dailymessage_conf` (`bold` TINYINT(1) NOT NULL,`italic` TINYINT(1) NOT NULL,`underline` TINYINT(1) NOT NULL,`showdate` TINYINT(1) NOT NULL,`configid` TINYINT(4) NOT NULL)

</query> <query>

INSERT INTO `# __joe_dailymessage_conf`(bold, italic, underline, showdate,

P

HP

In

side

#16

Б

онус

Page 53: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

configid) values(0, 0, 0 , 1, 1); </query> </queries> </install>

Инсталляционные запросы, которые устанавливают таблицы баз данных, длякомпонента открываются посредством тега <query>, которые ограничиваются тегами<install>. Префикс '#_' в запросах будет замещен в на префикс текущей базы данныхJoomla [обычно 'jos']. Две таблицы созданы: одна для сообщений, а вторая для храненияинформации о конфигурации. Также, первоначальные значения вставляются в конфигу-рационную таблицу.<uninstall><queries> <query>

DROP TABLE IF EXISTS `# __joe_dailymessage`; </query> <query>

DROP TABLE IF EXISTS `# __joe_dailymessage_conf`; </query> </queries></uninstall>

Подобные инсталляционным теги для анинсталляции - <uninstall>, ограничиваютзапросы, которые необходимы, для удаления таблиц созданных при установке компонен-та. Эти запросы будут исполненты только когда администратор удалит компонент.<installfile><filename>install.dailymessage.php</filename></installfile><uninstallfile><filename>uninstall.dailymessage.php</filename></uninstallfile>

Теги <installfile> и <uninstallfile> содержат имена файлов, которые небоходимыдля произведения дополнительных действий при инсталляции и анинсталляции компо-нента. Они копируются в папку administrator/com_dailymessage.<administration><menu>Daily Message</menu><submenu><menu act="all">Edit Messages</menu>

P

HP

In

side

#16

Б

онус

Page 54: #16, Декабрь'2005 :: Ajax и PHP

Учебник по созданию компонент Joomla!

<menu act="configure">Configure</menu></submenu>

Тег <administration> содержит все что относится к зоне администрирования – Бе-кенду. Тег <menu> содержит заголовок, который будет помещен в качестве элементаменю в главном меню в Бекенде под меню 'Components.' Тег <submenu> содержит именаэлементов меню, которые будут появлятся при выборе в главном меню в зоне админи-стрирования 'Daily Message' под меню 'Components'. Свойство 'act' будет использованодля передачи информации Joomla о выбранном сабменю.

<files><filename>admin.dailymessage.php</filename><filename>admin.dailymessage.html.php</filename><filename>dailymessage.class.php</filename><filename>toolbar.dailymessage.php</filename><filename>toolbar.dailymessage.html.php</filename></files>

Теги <files> внутри тега <administration> описывают какие файлы будут скопиро-ваны в Бекенд - папку administration/com_dailymessage. </administration></mosinstall>

P

HP

In

side

#16

Б

онус