http://www.developer.com/

Back to article

WML Scripting Tips and Integration with PHP


August 19, 2002

This series of articles describes how to provide Web content to mobile devices through WML (Wireless Markup Language). This article covers some additional uses for WMLScript and how to integrate PHP with WML. Future articles will cover more advanced PHP and WML techniques.

Note: These articles cover WML and WMLScript version 1.1, which are supported by the majority of mobile devices in use today. The articles assume a working knowledge of HTML and general Web technologies, and further assume that you have read the previous article(s) in this series.

WMLScripting

In the last article we discussed how to use WMLScript to perform basic scripting tasks within your WML pages. As mentioned in that article, WMLScript can be used to validate input and perform basic operations on WML variables. WMLScript can also be used to control the display of various cards and the information contained on them. For example, the following code will display an animation by changing an image's source and refreshing a card every two seconds:

animation.wml

<wml>
  <card id="card1">
    <onevent type="onenterforward">
      <refresh>
      <setvar name="num" value="1" />
      <setvar name="image" value="image1.wbmp" />
      </refresh>
    </onevent>
    <onevent type="ontimer">
      <go href="junk.wmls#main()" />
    </onevent>
    <timer value="20" />
    <p><img alt="$(image)" src="$(image)" /></p>
  </card>

  <card id="card2">
  <p>Animation Done!</p>
  </card>
</wml>

animation.wmls

extern function main() {
var Num = WMLBrowser.getVar("num");
var Image = "";

if (Num < 9) {
  Num++;
  Image = "image" + Num + ".wbmp";
  WMLBrowser.setVar("num", Num);
  WMLBrowser.setVar("image", Image);
  WMLBrowser.refresh();
} else {
  WMLBrowser.go("animation.wml#card2");
  }
}

The deck (animation.wml) sets two variables and forces a refresh. These are the variables:

num:The number to append to the image source
image:  The starting image source (image1.wbmp)

Every two seconds, the main() function in animation.wmls is called. This function adds one to "num," creates a new image source (image<num>.wbmp), and refreshes the card, which causes the new image to be displayed. After the ninth image (image9.wbmp) is displayed, the script goes to the second card in the deck, ending the animation.

Note: The above example assumes that your animation consists of nine images that, when displayed sequentially, create the animation.

WMLScripting is flexible and brings basic scripting to WML. However, it's possible to lend more programming power to WML by infusing it with PHP, as covered in the next section.

Integrating PHP into WML

Although WML is well suited to most mundane content delivery tasks, it falls short of being useful for database integration or extremely dynamic content.

Another Web technology, PHP, fills this gap quite nicely-integrating into most databases and other Web structures and languages. It's possible to "cross-breed" mime types in Apache and IIS to enable PHP to deliver WML content. The following sections show you how to configure your server and how to integrate the two technologies.

Note: This section assumes that you have a basic understanding of PHP. To learn more about PHP, visit the PHP Web site (www.php.net) and browse through the language documentation. You can also find a series of articles here on Developer.com for learning PHP. The first is Learning PHP: The What's and the Why's

What Is PHP?

According to the PHP documentation, "PHP (recursive acronym for 'PHP: Hypertext Preprocessor') is a widely-used Open Source general-purpose scripting language that is especially suited for Web development and can be embedded into HTML."

Essentially, this scripting language is a server-side language that's processed before being sent to the requesting client. This is in contrast to scripting languages like JavaScript that are client-side and processed by the client's browser after being sent to the client.

The benefit of being a preprocessed language is that PHP pages can be highly dynamic. Decisions can be made from user input, databases, server conditions, and so on about how the requested content is delivered to the client. It's exactly what we need to increase the power of our WML.

Installing PHP

PHP is available for most major Web server platforms, including Apache and Microsoft's Internet Information Server (IIS). Visit www.php.net, download the appropriate version for your server, and install it by following the included instructions.

Note: If you're running Debian, Red Hat, or another version of Linux with a robust packaging system, PHP is probably available in a preconfigured package. Check your distribution's Web site and documentation for more info on PHP package(s).

Cross-breeding with WML: Apache

To enable WML pages to be parsed by PHP, you simply have to add the WML suffix to the PHP application definition in your Apache configuration file:

    AddType application/x-httpd-Php .php .wml

Note the addition of ".wml" to the definition. This will cause the server to parse all .wml files with PHP. Don't forget to restart Apache so it will read the new configuration. Make sure that your WML definitions appear before the PHP definition to ensure that Apache recognizes ".wml" as a valid type.

Tip: As mentioned above, this causes all .wml files to be parsed by PHP. Although this is usually desirable, you could create another mime type ("pwml") and include it in both the WML and PHP definitions. Then you could continue to use .wml for pure WML files and the new type for PHP-parsed WML.

Cross-breeding with WML: IIS

To enable WML pages to be parsed by PHP, you need to add PHP as an application to handle your .wml files.

To do this, follow the steps below:

  1. Open the Internet Information Services Management Console.

  2. Right-click on the site where you want to add this functionality (or use Default Web Site) and choose Properties.

  3. Access the Home Directory tab and click the Configuration button near the bottom of the dialog.

  4. Click the Add button to add an application.

  5. Add the path and filename of the PHP executable (usually "C:\PHP\php.exe") in the Executable field and ".wml" in the Extension field.

  6. Ensure that "Script Engine" and "Check that file exists" are both checked.

  7. Select OK back to the IIS MC.

  8. Although not usually required, you may need to restart your Web server.

In step 6, above, setting the "Check that file exists" option is not entirely necessary, but can be helpful in debugging server issues. Without that option being set, IIS will pass all requests for .wml pages to PHP, even if the requested page doesn't exist. Instead of generating a "404 - Not Found" error, the Web server will report a problem with PHP (which failed because there was no file to parse).

These steps will result in all .wml files being parsed by PHP. Although this is usually desirable, you could create another mime type ("pwml") and include it in the WML definition and define PHP as an application for the new type. Then you could continue to use .wml for pure WML files and the new type for PHP-parsed WML.

Getting the Client to Recognize PHP-parsed WML

Now that the server has been configured to deliver PHP-parsed WML, you need to ensure that the client will receive it as WML. This is accomplished by having each PHP-parsed page send the appropriate header to the client.

You should begin each PHP file with the following line:

    header("Content-type: text/vnd.wap.wml");

This line needs to come before anything else is sent to the client-it pays to make a habit of including it right after the "<?php" start tag.

The following example shows how to display a one-card deck with the text "Hello world" using PHP:

<?php

header("Content-type: text/vnd.wap.wml");  

print "<?xml version=\"1.0\"?>\n";  
print "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\""  
   . " \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n"; 
   
print "<wml>\n";
print "<card>\n";
print "<p>Hello world</p>\n";
print "</card>\n";
print "</wml>\n";

?>

Note that there are several ways to accomplish sending the WML to the client. I've chosen to use individual print statements, each ending with a newline code. This keeps the resulting WML fairly readable and PHP mimics the line breaks. In some cases, namely long stretches of code, a print "here document" structure would work better. The above example would resemble the following in "here document" structure:

print <<<END
<?xml version=\"1.0\"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"  
    "http://www.wapforum.org/DTD/wml_1.1.xml"> 
   
<wml>
<card>
<p>Hello world</p>
</card>
</wml>
END;

In any case, remember that your target platform is WML-stick to WML-compatible tags and structure and avoid using reserved characters (such as "$") in places where they might be misinterpreted. Also, debugging the code is twice as hard as straight WML because you have to debug the PHP code as well as the resulting WML. The next article in this series will provide more debugging tips.

Utilizing the Power of PHP

As previously mentioned, PHP's interoperability with other technologies makes it a powerful ally for WML. One such technology, databases, is especially useful.

As an introduction, we'll cover a basic example here. The next article in the series will showcase more examples of using PHP to extend WML.

For this example we'll use MySQL, a popular open-source database solution, although any database with PHP connectivity would work as well.

Suppose that we have a team of salespeople in the field who need regular access to customer data. In this example we'll only be concerned with the customer's phone number, but it illustrates the underlying power of using PHP while creating a useful "online" phonebook.

Our database for this example is very simple:

    First Name         Last Name         Phone Number    
John Smith 555-723-0900
Kathy Lamarr 555-876-2222
Sam Kinkaid 555-243-8766
Holly Haute 555-327-0987

In MySQL, the database and table would be created using the following code:

CREATE DATABASE Customer;

USE Customer;

CREATE TABLE Phone (
  FirstName varchar(30) default NULL,
  LastName varchar(30) default NULL,
  Phone varchar(12) default NULL
);

INSERT INTO Phone VALUES ('John','Smith','555-723-0900');
INSERT INTO Phone VALUES ('Kathy','Lamarr','555-876-2222');
INSERT INTO Phone VALUES ('Sam','Kinkaid','555-243-8766');
INSERT INTO Phone VALUES ('Holly','Haute','555-327-0987');

Now we'll create a relatively simple PHP program to display the customers in a select list. When the user selects an entry, the phone will dial the selected number.

1.  <?php

2.  header("Content-type: text/vnd.wap.wml");  

3.  print "<?xml version=\"1.0\"?>\n";  
4.  print "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\""  
5.  . " \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n"; 

6.  print "<wml>\n";
7.  print "<card id=\"Phonebook\">\n";
8.  print "<p><select>\n";

9.  $link = mysql_connect("localhost", "user", "password")
10.  or die("Could not connect to database!");
11.  mysql_select_db("customers")
12.  or die("Could not select database!");

13.  $query = "select * from Phone order by LastName";
14.  $result = mysql_query($query,$link)
15.  or die("Query failed:$query");

16.  while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
17.  print "<option title=\"Call\"";
18.  print " onpick=\"wtai://wp/mc;$line[Phone]\" >";
19.  print "$line[FirstName] $line[LastName] ($line[Phone])\n";
20.  print "</option>\n";
21.  }

22.  print "</select></p>\n";
23.  print "</card>\n";
24.  print "</wml>\n";

25.  ?>

The code is fairly straightforward:

  • Lines 1-5 are our standard WML preamble.
  • Lines 6-8 open the required tags.
  • Lines 9-12 create the link to the database. Be sure to substitute an actual username and password for the placeholders.
  • Lines 13-15 query the database for all fields in all rows of the Customers database.
  • Lines 16-21 step through the results row by row and build an <option> for each one.
  • Lines 22-24 close all open tags.

Each <option> includes an "onpick" attribute that will dial the selected number on most devices, via the "wtai://wp/mc;<phone number>" URL scheme. This is a useful trick for all users to dial numbers from within your WML.

The generated output resembles the following figure:

Image courtesy Openwave Systems Inc. (Openwave, the Openwave logo, Openwave SDK, Openwave SDK Universal Edition, Openwave SDK WAP Edition are trademarks of Openwave Systems Inc. All rights reserved.)

Quite a few changes can be made to the code above:

  • The "order by" clause of the query can be changed to sort by a different field or by multiple fields.
  • Although the current layout allows each record to be displayed in its entirety, using the "wrap" option in the <p> tags would allow more records to be displayed per screen (but each would have to be highlighted for the full record to be seen).
  • This example is convenient because there are only four rows in our database. To make our user interface more "friendly," we should create paging code to step through the data nine rows at a time (ensuring that each row has a quick access key [1-9] associated with it).

Next Time

The next article in this series will expand the phone book PHP example, highlighting techniques such as paging record display, searching for records, etc.

About the Author

Steve Schafer is president and CEO of Progeny Linux Systems, a Linux-based consulting company in Indianapolis, Indiana. He has written several technical books and articles and can be reached at sschafer@synergy-tech.com.

# # #

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date