Людям, постоянно находящимся в разъездах, необходимо иметь согласованные и достоверные списки контактов во всех телефонах, которыми они пользуются. В этой статье рассмотрен пример, в котором данные для стационарного SIP-телефона и мобильного смартфона извлекаются из базы данных MySQL. Из статьи вы узнаете, как с помощью PHP получить настраиваемый XML-код из одной и той же базы данных, подходящий для использования как в стационарных, так и в мобильных телефонах.
Даже если вы находитесь в командировке или где-то еще, вам необходимо иметь связь со всеми людьми из вашего списка контактов. Когда вы находитесь в офисе, вы совершаете звонки с помощью стационарного VoIP-телефона, а в пути пользуетесь смартфоном. Однако каждое устройство предъявляет свои требования к формату списка контактов, и форматы телефонных книг в каждом устройстве разные. При необходимости модно было бы работать с двумя списками контактов – сначала добавлять новую запись в обе телефонные книги, а затем редактировать обе книги при изменении информации о контактах. Конечно, более предпочтительным является вариант, когда оба телефона получают данные из одного и того же источника, позволяющего вносить изменения только в одном месте. Что ж, если вы подключены к Интернету или интрасети, это не проблема. В этой статье я покажу, как одна база данных MySQL может предоставлять информацию о контактах двум различным устройствам: стационарному VoIP-телефону семейства snom 300 и мобильному смартфону (в нашем примере используется Nokia E71)
Семейство snom 300 представляет собой линейку надежных VoIP-телефонов с широким набором важных офисных функций, таких как удержание, переадресация вызова и конференц-связь. Хотя в этих телефонах не реализована поддержка получения данных с LDAP-сервера, в них есть мини-браузер, позволяющий читать HTML-код. Кроме того, он умеет выводить текст на дисплей телефона в формате, позволяющем инициировать телефонный вызов.
В листинге 1 приведен пример XML-формата телефонной книги, используемого мини-браузером snom.
Листинг 1. Пример XML-кода для мини-браузера snom
|
В этом листинге корневой элемент
SnomIPPhoneDirectory
имеет три дочерних элемента: Title
, DirectoryEntry
иSoftKeyItem
. Заголовок (Title
) отображается в верхней части дисплея телефона и остается на месте при прокрутке. За ним следуют записи каталога (DirectoryEntry
); каждая запись занимает одну строку, и эти строки можно прокручивать. Программируемые клавиши (SoftKeyItem
) относятся к четырем кнопкам, расположенным под дисплеем. Эти кнопки могут выполнять различные функции, например, инициализировать вызов абонента, чье имя подсвечено на дисплее. В этом примере имеются две записи каталога, состоящие из отображаемого имени абонента и его телефонного номера, используемого для набора, и активируется только одна кнопка – F1, нажатие на которую инициирует набор телефонного номера.Nokia E71 - хороший пример современного смартфона. Он умеет соединяться с сотовыми и беспроводными локальными сетями, имеет встроенные SIP-клиент и Интернет-браузер и поддерживает голосовое управление.
Смартфон E71 поддерживает протокол WAP (Wireless Application Protocol – протокол беспроводной связи) версии 2.0 (не путайте WAP2 с протоколом защиты беспроводных сетей WPA2). Это означает, что E71 может считывать XML-файлы, осуществляющие внутренние взаимодействия с его специальными функциями, например, открытие окна для начала телефонного вызова.
В листинге 2 приведен пример требуемого смартфону содержимого в формате WAP2/XML. В этом примере используются те же самые записи каталога (два вымышленных контакта), что и в листинге 1.
Листинг 2. Пример WAP2 XML
|
Протокол WAP2 требует, чтобы данные предоставлялись в виде "колоды карт". Корневой элемент
включает в себя один дочерний элемент (или страницу)
, содержащий две строки, разделенных тегом перевода строки. Заголовок страницы указан в атрибуте корневого элемента. Телефонные номера указаны в виде ссылок (
) внутри атрибута
, использующего протокол WTAI (Wireless Telephony Applications Interface – протокол приложений беспроводной телефонии, . При открытии страницы в браузере телефона и нажатии на ссылку с телефонным номером появляется всплывающее окно с запросом подтверждения вызова; на этом этапе телефон выбирает маршрут вызова – беспроводная локальная сеть или другая доступная услуга связи.Поскольку в смартфоне не предусмотрена поддержка протокола LDAP, а стационарный телефон не умеет работать с WAP2, то может показаться, что между ними мало общего. Тем не менее можно найти общее решение, используя гибкость XML и командные сценарии. Можно было бы попытаться найти способ синхронизировать адресную книгу смартфона с LDAP-сервером, но сделать это было бы не так просто, как при использовании прямого динамического доступа к информации. К счастью, несмотря на то, что формат XML может различаться в двух разных схемах, сами данные остаются неизменными.
Поскольку оба устройства могут подключаться доступ к Интернету, одно из возможных решений, позволяющих использовать общую адресную книгу, такое: вся информация хранится в базе данных, а для генерации XML-файла и передачи его в браузер подходящего устройства используется механизм сценариев. Если вы знаете, какое устройство обращается к сценарию, то можно сгенерировать и отправить соответствующий ответ для этого устройства. Кроме того, сценарий может управлять доступом и отфильтровывать отправляемую информацию по мере необходимости.
Данные могут храниться в самых различных форматах и извлекаться по мере необходимости. Для хранения данных можно использовать PostgreSQL, XML, простой текст, IBM® DB2® и т. д. В листинге 3 приведен пример схемы базы данных MySQL.
Листинг 3. Схема базы данных для нашего примера
CREATE TABLE IF NOT EXISTS 'mycontacts' ( 'id' int(11) NOT NULL auto_increment, 'firstName' varchar(30) default NULL, 'lastName' varchar(30) default NULL, 'number' varchar(20) default NULL, PRIMARY KEY ('id') ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; |
Всего таблица содержит четыре поля – идентификатор (для удобства), имя, фамилия, телефонный номер – и один индекс. В этой схеме используется только самая необходимая информация. При желании в эту схему можно добавить дополнительные поля и индексы. Для редактирования содержимого MySQL-таблиц вы можете воспользоваться инструментами LibreOffice Base или phpMyEdit на ваш выбор
В листинге 4 представлен базовый код сценария, извлекающего информацию из базы данных и генерирующего вывод в обычном текстовом формате. На этом этапе нам необходимо лишь убедиться в том, что генератор возвращает правильные данные.
Листинг 4. Базовый код генератора вывода
query($query); $num = $result->num_rows; $i = 0; while ($row = $result->fetch_array()) { $myarr[$i]['first']=$row["firstName"]; $myarr[$i]['last']=$row["lastName"]; $myarr[$i]['phone']=$row["number"]; $i++; } $mysqli->close(); switch ($dev) { case 'snom': echo mysnom($myarr); break; case 'noki': echo mynoki($myarr); break; default: echo mytest($myarr); break; } function mytest($myarr) { $cont = "Header\n"; foreach ($myarr as $a) { $cont .= " ".$a['first']." ".$a['last']." ".$a['phone']."\n"; } $cont .= "Footer\n"; return $cont; } function show_err($dev,$msg) { die($msg); } ?> |
Код сценария начинается с определения переменных, используемых для доступа к базе данных, установки подключения и возврата результирующего набора данных или сообщения о невозможности подключения к БД. Далее в цикле
while
последовательно считываются все записи результирующего набора и информация сохраняется в массив для последующего использования. Поскольку начальным значением переменной устройства $dev
является строка нулевой длины, то при выполнении оператора switch
происходит переход в секцию default и выполняется вызов функцииmytest()
. Эта функция выводит заголовок, содержимое массива и нижний колонтитул в виде обычного текста.В этом сценарии обрабатывается лишь одна ошибка – неудачное подключение к базе данных. Вы можете написать дополнительный код для обработки других ошибок – например, успешного подключения к пустой базе данных. Для отслеживания и обработки этих событий можно использовать подобные вызовы функции
show_err()
.Теперь у нас имеется все необходимое для того, чтобы научить наш сценарий работать с разными типами устройств. В операторе
switch
имеются условия для двух телефонов, но функции еще не определены. Наша задача состоит в том, чтобы сгенерировать вывод для других устройств в требуемом XML-формате.Если вы проанализируете листинг 1, то поймете, что функции из листинга 5 добавляют функциональность, необходимую для работы со стационарным VoIP-телефоном.
Листинг 5. Функции для работы с мини-браузером стационарного телефона
function mysnom($myarr) { $cont = " |
В отличие от листинга 4, в котором вывод генерируется в виде обычного текста, функции, добавленные в листинге 5, упаковывают данные в формат, используемый мини-браузером телефона. В сценарий была добавлена новая функция
mysnom()
, а функция show_err()
была заменена. Мини-браузер не умеет отображать простой текст (в этом случае он просто ничего не делает), поэтому как обычные данные, так и сообщения об ошибках необходимо выводить в формате XML. Поскольку вы пользуетесь телефоном, то именно на нем должны отображаться сообщения об ошибках. В случае невозможности подключения к базе данных сценарий отправляет сообщение об ошибке на телефон. В случае успешного подключения на телефон отправляется корневой элемент, а затем начинает выполняться цикл while
. В этом цикле каждая запись упаковывается в свои собственные теги элемента каталога, после чего начинается настройка кнопок телефона. Поскольку телефон имеет всего четыре функциональные кнопки, вряд ли стоит хранить их значения в базе данных. И, наконец, последняя часть кода закрывает корневой элемент.Функции из листинга 5 срабатывают в том случае, если переменная
$dev
определена в начале кода следующим образом:$dev = "snom"; |
В случае использования смартфона Nokia необходимо получить вывод в XML-формате WAP2 с учетом WTAI. Этот код представлен в листинге 6.
Листинг 6. Функция для работы с протоколом WAP2 мобильного смартфона
function mynoki($myarr) { $cont = " |
Этот код также преобразует данные в требуемый XML-формат, используемый в телефонах Nokia. В этом случае текст сообщения о неудачном подключении к БД не упаковывается в какие-либо XML-теги, поскольку телефон может отображать простой текст без каких-либо дополнительных требований. Когда все записи телефонной книги окажутся отображены на экране телефона, сценарий отправляет информацию XML и DOCTYPE, а также открывающие теги элементов
и
, после чего начинается цикл foreach
, в котором к каждой строке результирующего набора добавляется необходимая информация протокола WTAI. Наконец, последняя часть кода закрывает элементы
и
.Функция из листинга 6 срабатывает в том случае, если переменная
$dev
определена в начале кода следующим образом:$dev = "noki"; |
Заметим, что предлагаемый вариант списка контактов для смартфона Nokia E71 не является полной заменой встроенной телефонной книги, которая, являясь частью системы, несомненно имеет ряд преимуществ, обеспечивающих ее тесное взаимодействие с остальными приложениями смартфона. Тем не менее список контактов для встроенной телефонной книги также можно сгенерировать на основе базы данных MySQL, используя тот же самый подход; отличие будет заключаться в том, что промежуточный вывод, который затем будет импортирован в телефон, необходимо генерировать в формате vCard (VCF).
Последняя наша задача состоит в том, чтобы сообщить сценарию, в каком формате требуется получить данные. Для этого можно воспользоваться разными способами, одним из которых является отправка информации
GET
в строке HTTP-запроса. Представьте, что вы отправляете следующий запрос, в котором явно указаны устройство и пользователь:http://www.myserver.tld/phonebook/myscript.php?device=snom&user=jim |
Итак, в листинге 7 представлен полностью готовый сценарий, который анализирует строку запроса и инициализирует переменные в соответствии с полученной информацией во время выполнения.
Листинг 7. Определение устройства
query($query); $num = $result->num_rows; $i = 0; while ($row = $result->fetch_array()) { $myarr[$i]['first']=$row["firstName"]; $myarr[$i]['last']=$row["lastName"]; $myarr[$i]['phone']=$row["number"]; $i++; } $mysqli->close(); switch ($dev) { case 'snom': echo mysnom($myarr); break; case 'noki': echo mynoki($myarr); break; default: echo mytest($myarr); break; } function mytest($myarr) { $cont = "Header\n"; foreach ($myarr as $a) { $cont .= " ".$a['first']." ".$a['last']." ".$a['phone']."\n"; } $cont .= "Footer\n"; return $cont; } function mynoki($myarr) { $cont = " |
Этот код объединяет код из листингов 4, 5 и 6 и содержит дополнительную проверку пользователя; если пользователю не разрешен доступ к информации, то выполнение сценария останавливается. В противном случае на основании строки запроса определяется устройство, для которого в соответствии с правилами генерируются выходные данные.
Каждое устройство отправляет свои собственные запрос и строку запроса к базе данных и получает быстрый ответ в том формате, с которым оно работает.
Общий список контактов можно использовать и на других платформах, по-разному генерируя вывод XML. Функция для телефонов Nokia должна работать с любым устройством с поддержкой WAP 2.0. Более сложной может оказаться адаптация функции snom для использования на других телефонах, но если они работают с XML, то все, что вам нужно – это подобрать правильную схему. Вы можете изменять и расширять функциональность сценария так, как вам это нужно, используя для этого наиболее удобный для вас язык сценариев.