Create an adaptable phone book and contact list for your phones with XML and PHP

Use XML to feed a consistent contact list to your phones

On-the-go professionals need access to a consistent and reliable list of contacts on whatever phone they have in hand. Using the example of a MySQL database providing data for a desktop SIP phone and a smart phone, learn to use PHP to output customized XML from the same root database to suit a desktop phone or a smart phone, or both devices simultaneously.

Colin Beckingham, Writer and Researcher, Freelance

Colin Beckingham is a freelance researcher, writer, and programmer who lives in eastern Ontario, Canada. Holding degrees from Queen's University, Kingston, and the University of Windsor, he has worked in a rich variety of fields including banking, horticulture, horse racing, teaching, civil service, retail, and travel and tourism. The author of database applications and numerous newspaper, magazine, and online articles, his research interests include open source programming, VoIP, and voice-control applications on Linux. You can reach Colin at colbec@start.ca.



29 March 2011

Also available in Chinese Russian Japanese

You need to keep in touch with contacts, even when you're on the road. When desk-bound, you call with your desktop VoIP phone; when travelling, you use your smart phone. But each device requires that its phone list be in a particular format, each with its own distinctly formatted contact list or phone book. You could, if required, enter all your contacts twice—once for each contact list—and then, each time you have a change, make the change in both lists. Of course, you might prefer to have both phones get their data from the same back-end source, where you can edit names and numbers in only one place. This is not a problem: You are Internet or intranet connected with access to technology. In this article, learn how data from a single MySQL database can provide contact information to two quite different devices: a VoIP phone represented by the snom 300 family of devices and a smart phone in the shape of the Nokia E71 device (see Resources for links).

Desktop device: the snom 300 family

Frequently used acronyms

  • HTML: Hypertext Markup Language
  • HTTP: Hypertext Transfer Protocol
  • LAN: Local area network
  • LDAP: Lightweight Directory Access Protocol
  • SQL: Structured Query Language
  • VoIP: Voice over IP
  • XML: Extensible Markup Language

The snom 300 family offers good, solid VoIP phones with a wide range of functions relevant in an office context, such as hold, transfer, and conference. Although the phone does have native support for data fed from an LDAP server, it also has a minibrowser (see Resources) that can read HTML. It can even display text on the phone's screen in a format that can trigger a phone call.

Listing 1 provides an example of the XML format that the snom minibrowser requires, specifically in a phone book context.

Listing 1. Example of the snom XML minibrowser
<?xml version="1.0" encoding="UTF-8"?>
<SnomIPPhoneDirectory>
  <Title>PhoneList - Snom</Title>
  <DirectoryEntry>
    <Name>Friend, First</Name>
    <Telephone>555-456-7890</Telephone>
  </DirectoryEntry>
  <DirectoryEntry>
    <Name>Person, Second</Name>
    <Telephone>555-654-0987</Telephone>
  </DirectoryEntry>
  <SoftKeyItem>
    <Name>F1</Name>
    <Label>Dial</Label>
    <SoftKey>F_ENTER</SoftKey>
  </SoftKeyItem>
</SnomIPPhoneDirectory>

In this code, the root element SnomIPPhoneDirectory has three different children: Title, DirectoryEntry, and SoftKeyItem. The title appears at the top of the phone display and remains in place during scrolling. The directory entries follow—one per line—and can scroll. The soft key items relate to four buttons just below the display. These buttons can perform such functions as initiating a call to the currently highlighted directory entry. The data in this example consist of two phone number entries: a display name and the number used for dialing. It activates only one button: Press the F1 button and the phone begins to dial.


Traveling device: The Nokia E71 smart phone

The Nokia E71 device is a good example of a modern smart phone. It can connect with wireless LAN or cell service, has a Session Initiation Protocol (SIP) client, can browse the Internet with its own native browser, and manages voice communications on the go.

The E71 device is capable of Wireless Application Protocol (WAP) version 2.0 (WAP2—see Resources)—not to be confused with the Wi-Fi Protected Access II (WPA2) functions. This means that it can read XML-formatted files that communicate internally in the phone with its various specialist abilities, such as opening a window to initiate a call.

Listing 2 provides an example of what the smart phone requires in WAP2/XML format. This example uses the same two fictional entries as in Listing 1.

Listing 2. Example of WAP2 XML
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
   "http://www.wapforum.org/DTD/wml_1.1.xml" >
<wml>
  <card id="main" title="PhoneList - Nokia">
    Tel (WTAI): <a href="wtai://wp/mc;%2B555-456-7890">Friend, First</a><br />
    Tel (WTAI): <a href="wtai://wp/mc;%2B555-654-0987">Person, Second</a>
  </card>
</wml>

WAP2 requires that you present the data in the form of decks of cards. The root element <wml> has one child <card> (or page), with two lines separated by a break. The title of the page is listed in an attribute of the root element. The telephone numbers are indicated in anchor, or <a>, elements, with an <href> attribute that uses Wireless Telephony Applications Interface (WTAI—see Resources). When you open the page in the phone's browser and click a phone link, a window pops up and asks if you want to call the number, at which point the phone finds a route to place the call—whether over a wireless LAN or using another phone subscription.

Because the smart phone has no native ability to deal with LDAP and the desktop phone does not handle WAP2, there seems to be little common ground. Scripting, however, provides a solution using the adaptability of XML. You might find a way to synchronize your contacts with the LDAP server through the smart phone, but it might not be as clean as direct dynamic access to information. Fortunately, although the format of the XML might change in the two schemas, the data remains fundamentally the same.


The approach

With ubiquitous access to the Internet from both devices, one solution to a common phone book is to keep all the data in a database, then use a scripting engine to generate an XML file for delivery to a browser on whichever device you find most convenient. As long as you know which device is using the script, the correct output can be delivered. In addition, the script can control access and filter information for delivery, as required.

The database

The data can be stored in a wide variety of formats and extracted as required. Alternatives include PostgreSQL, XML, plain text, IBM® DB2®, and many others. Listing 3 shows a sample schema for MySQL.

Listing 3. Example database schema
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 ;

The table contains just four fields—an ID for convenience, the first name and last name, and the phone number—and one index. This schema presents the bare essentials of information required. Further fields and indices can be added, as required. You can edit the data content with LibreOffice Base or phpMyEdit (see Resources) the editor of your choice.

The PHP generator

Listing 4 shows a bare-bones script that gets the data from the back end and presents the output in plain-text format. At this point, you are just testing the script to make sure that it returns sensible data.

Listing 4. Basic database generator
<?php
    $dev = "";
    $db_host = "your.database.server";
    $db_user = "your_user";
    $db_pass = "your_password";
    $db_name = "your_database";
    $mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);
    if (mysqli_connect_errno()) show_err($dev,"Could not connect to database");
    $query = "SELECT * FROM mycontacts order by lastName asc";
    $result = $mysqli->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);
}
?>

This code begins by defining the variables used to access the database, opens a connection, and returns a result set or a message if it cannot connect to the database. A while loop then iterates through the dataset, storing the information in a convenient array for later display. Because the device variable $dev is initialized to a zero-length string, when the switch executes, it goes to the default and calls the mytest() function. This function displays a simple header, writes out the content of the array, and then prints a footer—all in plain text.

This script deals with only one possible error: a failure to connect to the database. Plan to deal other conditions, such as successfully connecting to the database but finding an empty table. You can trap and deal with these conditions using similar calls to the show_err() function.

Most of the pieces are in place to generalize this script to deal with other types of devices. The switch has cases for the two phones, but their functions do not yet exist. The challenge now is to make the output relevant for the other destination devices, adding detail as required in XML format.

Desktop minibrowser

Referring to the example in Listing 1, you can see that the functions in Listing 5 add necessary pieces to deal with the desktop VoIP phone.

Listing 5. Function to handle desktop minibrowser
function mysnom($myarr) {
    $cont = "<?xml version=\"1.0\"?>
<SnomIPPhoneDirectory>
  <Title>MySQL Directory</Title>";
  foreach ($myarr as $a) {
    $cont .= "
  <DirectoryEntry>
    <Name>".$a['first']." ".$a['last']."</Name>
    <Telephone>".$a['phone']."</Telephone>
  </DirectoryEntry>\n";
  }
  $cont .= "</SnomIPPhoneDirectory>\n";
  return $cont;
}
function show_err($dev,$msg) {
  switch ($dev) {
    case 'snom':
      echo "<?xml version=\"1.0\"?>
<SnomIPPhoneText>
  <Text>
$msg
  </Text>
</SnomIPPhoneText>
";
    break;
    default:
      echo $msg;
    break;
  }
  die();
}

Comparing Listing 5 with Listing 4, instead of echoing the plain text, these new functions echo data wrapped in the elements that the minibrowser is expecting. The mysnom() function is an addition to the script, and the show_err() function is a replacement. The minibrowser is not capable of presenting plain text: It just does nothing. So XML output is required for both normal and exceptional output. Because you are using the phone, that is where the error messages must appear. In the case of failure to connect to the database, the script reports the error to the phone. In the case of success, before the while loop begins, the script announces the root element. As the loop progresses, each record is wrapped in its own directory entry tags; after the loop is complete, the setup for the buttons begins. With only four buttons, it is questionable whether this needs to be encoded in the database, as well. Finally, the code closes the root element.

The above functions behave correctly if the variable $dev is set correctly at the beginning of the code, as follows:

$dev = "snom";

Smart phone WAP2

In the case of the Nokia phone, you add the output details that provide the XML for the smart phone in WAP2 format with WTAI references. Listing 6 shows the code.

Listing 6. Function to handle smart phone WAP2
function mynoki($myarr) {
  $cont = "<?xml version=\"1.0\"?>
<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"
   \"http://www.wapforum.org/DTD/wml_1.1.xml\" >
<wml>\n
  <card id=\"main\" title=\"PhoneList - Nokia\">\n";
  foreach ($myarr as $a) {
    $cont .= "\nTel (WTAI): <a href=\"wtai://wp/mc;%2B".$a['phone']."\">
      ".$a['last']." ".$a['first']."</a><br />";
  }
  $cont .= "</card></wml>\n";
  return $cont;
}

Again, this code provides the required XML for the Nokia phone. The text output in the case of an error making the connection to the database is not wrapped in any kind of markup because simple output displays correctly on the phone without the markup. When phone book entries are displayed, before the loop begins, the script sends the XML and DOCTYPE information, followed by the opening of the root <wml> element and <card> element. Then, the loop begins, presenting each row enclosed in WTAI information. Finally, the code closes the card and the root <wml> elements.

The above functions behave correctly if the variable $dev is set correctly at the beginning of the code, as follows:

$dev = "noki";

Note that this suggestion for an approach to contacts on the Nokia E71 phone is not intended as a complete replacement for the native contacts application, which clearly has some advantages as part of the phone system and therefore enjoys close internal hooks with other applications. The native contacts list, however, can be generated from the same MySQL database using the same process but generating intermediate output in vCard (VCF) file format (see Resources) for import into the phone.


Detecting the device

The final piece in the puzzle is to let the script know at run time which device output is required. You can do this in a number of ways, one of which is to send GET information in the HTTP request query string. Imagine that you send the following request, which explicitly states a device and a user:

http://www.myserver.tld/phonebook/myscript.php?device=snom&user=jim

Then, the complete script in Listing 7 parses the query string and inserts the information into the script at run time.

Listing 7. Detecting the device
<?php
    if ($_GET['user'] != 'jim') show_err($dev,'Unauthorised access');
    $dev = $_GET['device'];
    $db_host = "your.database.server";
    $db_user = "your_user";
    $db_pass = "your_password";
    $db_name = "your_database";
    $mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);
    if (mysqli_connect_errno()) show_err($dev,"Could not connect to database");
    $query = "SELECT * FROM mycontacts order by lastName asc";
    $result = $mysqli->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 = "<?xml version=\"1.0\"?>
<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"
   \"http://www.wapforum.org/DTD/wml_1.1.xml\" >
<wml>\n
  <card id=\"main\" title=\"PhoneList - Nokia\">\n";
  foreach ($myarr as $a) {
    $cont .= "\nTel (WTAI): <a href=\"wtai://wp/mc;%2B".$a['phone']."\">
      ".$a['last']." ".$a['first']."</a><br />";
  }
    $cont .= "</card></wml>\n";
  return $cont;
}
function mysnom($myarr) {
    $cont = "<?xml version=\"1.0\"?>
<SnomIPPhoneDirectory>
  <Title>MySQL Directory</Title>";
  foreach ($myarr as $a) {
    $cont .= "
  <DirectoryEntry>
    <Name>".$a['first']." ".$a['last']."</Name>
    <Telephone>".$a['phone']."</Telephone>
  </DirectoryEntry>\n";
  }
  $cont .= "</SnomIPPhoneDirectory>\n";
  return $cont;
}
function show_err($dev,$msg) {
  switch ($dev) {
    case 'snom':
      echo "<?xml version=\"1.0\"?>
<SnomIPPhoneText>
  <Text>
$msg
  </Text>
</SnomIPPhoneText>
";
    break;
    default:
      echo $msg;
    break;
  }
  die();
}
?>

This code, which is basically a repeat of Listing 4 with the functions from Listing 5 and Listing 6 added, begins with a trivial check to see who the user is and stops under controlled conditions if the wrong user attempts to access the information. It then gets the device from the query string and completes the output according to the instructions.

With each phone presenting its own request and query string to the database, output is quickly and easily received in a format that the device can display.


Conclusion

You can use the contact list from a common source on other platforms by modifying the XML output. The function for the Nokia should work on any phone that conforms to WAP 2.0. Adapting the snom function to other phones might be more difficult, but if XML is respected, then all you need is the right schema. You can easily maintain and expand the script as required, using whichever scripting language is most convenient.

Resources

Learn

Get products and technologies

  • LibreOffice: Learn more about this Open Source personal productivity suite for Windows, Macintosh and Linux. Try the six apps for document production and data processing needs: Writer, Calc, Impress, Draw, Math and Base.
  • phpMyEdit: With this utility, write a simple calling program that generates PHP code to display or edit MySQL tables in HTML.
  • IBM product evaluation versions: Download or explore the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into XML on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Open source
ArticleID=643262
ArticleTitle=Create an adaptable phone book and contact list for your phones with XML and PHP
publish-date=03292011