1 Разработка Web-сервиса на основе PHP и MySQL Web-сервис — это объект на стороне сервера, который предоставляет клиенту свои функции через Internet-протоколы. На платформе Microsoft .NET или J2EE Web-сервис представляет собой развитый сервер на основе WSDL (Web Service Definition Language), который после его инициирования на основе HTTP-Get или SOAP (Simple Object Access Protocol) возвращает данные в XML формате. SOAP — это реализация вызовов удаленных процедур (Remote Procedure Call — RPC) через HTTP. Другими словами, SOAP использует XML для кодирования обращения к процедуре (и расшифровки ответа процедуры) в пакет для передачи в сети по HTTP протоколу1. Вот усеченный пример запроса процедуры getState() по SOAP протоколу: <?xml version="1.0"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <m:getStateName xmlns:m="http://www.soapware.org/"> <statenum xsi:type="xsd:int">19</statenum> </m:getState> </SOAP-ENV:Body> </SOAP-ENV:Envelope> </SOAP-ENV:Envelope> Как видим, это документ в формате XML. Корневой тег SOAP-ENV:Envelop содержит внутри себя тег SOAP-ENV:Body, который содержит описание вызываемой процедуры. В нашем примере сообщение описывает запрос на вызов процедуры getState с параметром statenum равным 19. Ответ сервера при успешном вызове выглядит так: <?xml version="1.0"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsd=http://www.w3.org/2001/XMLSchema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> DCOM-объекты используют бинарный формат передачи протокольных сообщений. 1 2 <SOAP-ENV:Body> <m:getStateNameResponse xmlns:m="http://www.soapware.org/"> <Result xsi:type="xsd:string">Сумы</Result> </m:getStateNameResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> В этой части серии статей "Web-сервисы" мы покажем, как, используя open source технологии PHP и MySQL можно создать Web-сервис — приложение на стороне Web-сервера, которое предоставляет услугу: извлекает данные из базы и возвращает их в XML формате. Этот сервис могут использовать Web-сайты новостных газет и других СМИ компаний, которые представляют текущие результаты и статистику футбольной лиги в стиле привычном для их аудитории. Инсталляция MySQL и ввод данных Сейчас мы опишем процесс инсталляции MySQL и MySQL Control Center (MySQLCC). Затем покажем, как, используя MySQLCC создать базу данных Сontent и таблицу Standings, где мы будем хранить данные о результатах футбольной лиги. Если у вас есть сборник статей "intro e-Shoping(1)", то можете пропустить этот материал вплоть до создания базы данных Сontent и таблицы Standings. Загрузите zip-архив сервера MySQL (http://www.mysql.com/downloads/) и разархивируйте его в новую папку. Запустите файл setup.exe для инсталляции сервера, после чего перезагрузите компьютер. Если сервер не запущен (mysqld-nt.exe отсутствует в списке диспетчера задач Windows), запустите его самостоятельно. Загрузите MySQL Control Center (http://www.mysql.com/downloads/mysqlcc.html). Разархивируйте файлы и запустите setup.exe. В процессе инсталляции MySQL Control Center (MySQLCC) его ярлык будет помещен на рабочий стол. Щелкните дважды на этом значке. Левая часть окна MySQLCC предназначена для отображения списка MySQL серверов. Если список пустой, то щелкните правой кнопкой мыши на свободном месте и выберите пункт New контекстного меню. В появившемся диалоговом окне назначьте значение поля Name равным ContentManager и Host Name — Localhost. Щелкните на кнопке Add чтобы вернуться к основному окну. Вы увидите в списке ContentManager с красной точкой, которая указывает, что сервер остановлен. Щелкните правой кнопкой на ContentManager и выберите Connect. Откройте узел Databases, чтобы увидеть базы данных, доступные этому серверу. Это будут, вероятно, mysql и test. 3 Щелкните правой клавишей на узле Databases и выберите New Database. Введите имя базы данных Content и щелкните на кнопке OK. Щелкните правой кнопкой на новой базе данных Content и выберите Connect. Откройте узел, и выберите Tables. Щелкните правой клавишей на Tables и выберите New Table. Опишите в появившемся окне поля таблицы Standings (табл. 1). Таблица 1. Описание полей таблицы Standings FieldName DataType Описание Lenght TeamID Int 11 Порядковый номер команды TeamName Varchar 100 Название команды TeamPlayed Int 11 Игры TeamGHome Int 11 Сыграно дома TeamGOut Int 11 Сыграно на выезде TeamScore Int 11 Забито мячей TeamLost Int 11 Пропущено TeamPts Int 11 Очки Выберите поле TeamID и щелкните в панели инструментов на значке Add Primary Key, чтобы TeamID cтало первичным ключом таблицы. Если вы сделали все правильно, то TeamID появится на вкладке Indexes. Убедитесь также, что флажок AUTO_INCREMENT установлен. Сохраните таблицу под именем Standings. Теперь можно ввести данные в таблицу. Если вам нравится вводить данные вручную, то щелкните дважды на таблице. Можно исполнить SQL команды, которые записанные в файле Ins_data.sql. В этом случае достаточно щелкнуть на кнопке SQL панели инструментов основного окна MySQLCC, а затем выбрать меню File/Open. Структура XML документа Теперь, когда все настроено, пришло время разработки PHP-приложения. Но сначала мы опишем формат данных, в котором это приложение должно их вернуть клиенту. Она важна с точки зрения оптимизации размера возвращаемых данных. Основа любого набора записей — это одна или несколько таблиц и множество индексов, которые используются, чтобы уникально идентифицировать данные. Для описания набора записей в XML рационально использовать следующую структуру: 4 <record index1=something index2=something index3=something> </record> Таким образом, индексы не копируются в поля записи и отделены от них для упрощения чтения. Поля записи могут быть дочерними по отношению к тегу <record>: <record index1=something index2=something index3=something> <column1>column1_value</column1> <column2>column2_value</column2> ... <column>columnN_value</column> </record> Единственная проблема состоит в том, что при большом числе записей или количестве столбцов XML документ становится очень большим, что "тормозит" сервер, клиент и повышает трафик сети. Поэтому мы используем формат <record index1='something' index2='something'> <item column1='column1_value' column2='column2_value' /> который не будет предъявлять повышенные требования ко всем трем выше перечисленным составляющим. Эта измененная XML-структура позволяет уменьшить размер набора записей по сравнению с тем, который будет при традиционном способе записи. Генерация XML Вызывая службу мы будем задавать требуемый тип отчета: все или часть данных о состоянии футбольной лиги. Для этого в форме на странице get_service.htm, мы будем задавать значение переменной service равной fullStandings (возвратить все данные о состоянии футбольной лиги) или Standings (часть данных). Передача параметров PHP-программе (скрипту) в адресной строке браузера в первом случае будет выглядеть так: http://localhost/return_xml.php?service=fullStandings а во втором случае — http://localhost/return_xml.php?service=Standings Чтобы считать значения параметра service из переданного в URL формой get_service.htm в PHP-скрипте return_xml.php использован GET метод: $condition = $_GET['service']; Затем, для предоставления требуемого сервиса генерируется запрос: if($condition == "fullStandings") // Возвратить все данные о состоянии футбольной лиги $query = "SELECT * FROM Standings"; else 5 if($condition == "Standings") // Возвратить места команд футбольной лиги $query = "SELECT TeamName, TeamPlayed, TeamPts FROM Standings ORDER BY TeamPts DESC"; Язык PHP располагает набором встроенных функций для управления MySQL. В таблице 2 приведено описание некоторых из них. Таблица 2. Описание PHP-функций для управления MySQL Функция Описание mysql_connect(host, user, password) Создание связи с определенным сервером с правами специфицированными именем (user) и паролем (password) пользователя. Возвращает переменную экземпляра связи. mysql_select(dbname, instance) Для заданного экземпляра связи instance выбирает базу данных dbname mysql_query(query) Возвращает выборку из текущей базы данных. mysql_fetch_array(results) Помещает результат в массив. mysql_field_name(results, index) Возвращает имя поля в позиции index. В листинге 1 показано использование этих функций. Листинг 1. Формирование XML документа // Соединение с сервером и выбор базы $db = mysql_connect("localhost", "root", ""); @mysql_select_db("Content", $db) or die("База недоступна"); // Исполнение запроса для получения требуемых данных $result = mysql_query($query) or die("Ошибка в запросе"); // Формирование возвращаемого XML документа while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) { $i=0; foreach ($line as $col_value) { $fieldname=mysql_field_name($result,$i); if($i==0){ echo"<record id='$col_value'>"; echo ("<rowitem"); } else echo ("$fieldname='$col_value' "); $i++; 6 } echo ("/></record>"); } echo (" </xml>"); Разберемся, как формируется XML документ. Сначала формируется начало записи и открывается тег для вывода имен и значений полей ($i равна нулю). Затем $i отлична от нуля и выводятся имена и значения полей ($fieldname = '$col_value'). Наконец, когда данные в $result исчерпаны формируется значение /></record> и заканчивается формирование XML документа. На рис. 1 приведен пример XML документа, который отображает места команд в футбольной лиге. Рис. 1. Пример XML документа Итак, мы разработали простую PHP-службу, которая возвращает XML используя сервер MySQL. Поскольку она не поддерживает SOAP или WSDL ее нельзя считать полноценной Web-службой, но это малозатратный способ оперирования языком Web-служб — XML для разработки управлямых XML Webсайтов в рамках open source технологий. P.S. В моей книге "Базы данных: от проектирования до разработки приложений" эта глава реализована на Delphi и "немного" не так.