picture of Andres Baravalle
Cellular phones supporting WAP are slowly, but constantly spreading. Therefore, it could be time for you to start building your WML pages to access internet databases. As such, we will show you how to build PHP/WML pages to access a MySQL database which contains professors' receiving hours and exams timetables for a University. I'm testing a beta service of this kind, prepared with Vitaveska Lanfranchi, at www.scidecom.it.
There are some things you need to know before starting. First, we are assuming that:
  1. You have correctly installed PHP and MySQL, and you have some experience in programminng with both languages. Your database needs to be properly installed as well.
  2. You have some knowledge of SQL; I suggest reading Database Normalization and Design Techniques.
  3. You are running Apache and you can write .htaccess files; or you are running IIS and you can add mappings (or you can ask the system administrator to do it for you).
  4. You have some experience with WML; I suggest reading Introduction to WML, Apache, and PHP.
The first step is telling your server to process WML pages with PHP. Let's see how to do it.

Setting up the server

If you are using Apache, you have to look for a .htaccess file in your home directory. Then, you need to write the following lines in it:
<limit get post>
AddType application/x-httpd-php3 .wml
</limit>
If you don't have a file .htaccess, simply write these lines in a text editor and save the result as .htaccess in your home directory.
If you are using IIS instead, you have to do the same you did when you installed PHP in your server: look at the mappings of .php and .php3 extensions and do the same for .wml extension.
Commonly you will find PHP mapped onto:
C:\php\php4isapi.dll
or
C:\php\php.exe

Preparing to work

If you use Microsoft OS, you can install the NOKIA Development Kit. It checks for your syntax and lets you preview your WML pages with a phone-like user interface. Moreover, the kit comes equipped with useful documentation about WML and WMLScript. This helps if you don't have a mobile phone with WAP support, or if you can't use a WAP gateway.
To download it, you have first to register as a wap developer. Remember that you need the Java2 Runtime Enviroment. However, any text editor is fine for writing your pages.
Before writing any PHP/WML code, you need to set up your MySQL tables.
The database is structured in 4 tables.
  1. table professors contains data about professors
  2. table subjects contains data about subjects
  3. table exams contains data about exams
  4. table teach contains the relations between the professors and their subjects
Write the code below after establishing a MySQL connection.
CREATE TABLE professors (
	Id int(11) DEFAULT '0' NOT NULL auto_increment,
	Surname varchar(24) NOT NULL,
	Name varchar(24) NOT NULL,
	Email varchar(48) DEFAULT 'Not avaliable',
	Cod_course varchar(16) DEFAULT 'Not avaliable',
	Consulting_hour varchar(128) DEFAULT 'Not avaliable', 
	Consulting_place varchar(128) DEFAULT 'Not avaliable',
	PRIMARY KEY (Id)
);
These lines specifiy the structure of table professors. Id is the field for associating an unique identifier with each professor and is the key of the table. The other fields, Surname, Name, Email specifies the surname, the name and the e-mail address for each professor. Cod_course assumes unique values identifying the subjects. Finally, Consulting_hour and Consulting_place specify the receiving time and the place for receiving.
CREATE TABLE subjects (
	Subject varchar(96) NOT NULL,
	Cod_Subject varchar(24) NOT NULL,
	Cod_number varchar(12) NOT NULL,
	PRIMARY KEY (Cod_subject )
); 
Subject is the name of the subject, Cod_subject is the field containing the unique name adopted by the University for the subject and is the key of the table. Cod_number is a numeric field containing a number grouping different courses on the same subject.
CREATE TABLE exams (
	Cod_Subject varchar(24) NOT NULL,
    Id int(11) NOT NULL,
    Date date DEFAULT '0000-00-00',
    Time time DEFAULT '00:00:00',
    Room varchar(64),
    Test varchar(16) DEFAULT 'Oral'
); 
Cod_subject again contains the unique name adopted by the University for the subject,Id is the unique identifier for the professors, Date, Time, and Room, record the date, the time and the place where exams will take place; Test is for the type of the exam (written, oral, or anything else).
CREATE TABLE teach (
	Cod_Subject varchar(16) NOT NULL,
	Id int(11) DEFAULT '0' NOT NULL,
	PRIMARY KEY (Id, Cod_subject )
); 
In table teach the two fields form the key and are necessary to know who is teaching what.
The next step is filling the database with some data, which you can do by yourself.

Writing PHP/WML code

Now we write our first PHP/WML page which we call index.wml

<?php

Header
("Content-type: text/vnd.wap.wml");
Header("Cache-Control: no-cache, must-revalidate");
Header("Pragma: no-cache");
echo (
"<?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="card1" title="UNITO/Database"> 
<p> You can search for professors' consulting hours
  or for examinations timetables.
  <select name="choice" value="1" title="Research"> 
    <option value="exams_data">Examinations timetables</option> 
    <option value="consulting_data">Consulting hours</option> 
  </select> 
  <do type="text" label="Go"> 
  <go method="get" href="index2.wml#card2"> <postfield name="choice" value="$(choice)" /> </go> 
  </do> 
</p> 
</card> 
</wml> 
The first line tells the browser accessing the page what kind of MIME type are sent. Without the header command, the browser could not understand what kind of content is coming. Moreover, with this line you are not forced to set a particular extension for your files. This is very useful if you plan to write multimodal pages, with a script that checks the device or its capabilities and returns WML or HTML according to the type of browser.
Check whether PHP is installed with short tags enabled. If yes, every time you write a declaration like <?xml version='1.0'?>, embed it into PHP code to avoid confusion.
The rest of the code of this page simply lets you search for examinations timetables or consulting hours. The choice is recorded into variable $choice.
The next page is called index2.wml and allows you to decide whether you want to query the database by subject or by surname.

<?php

Header
("Content-type: text/vnd.wap.wml");
Header("Cache-Control: no-cache, must-revalidate");
Header("Pragma: no-cache");
echo (
"<?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="card2" title="Kind of research"> 
<p> 
  <?php
echo ("You are checking ");

if (
$choice == "exams_data") {
    echo (
" examinations timetables.<br />\n");
} else if (
$choice == "consulting_data") {
    echo (
" consulting hours.<br />\n");
} else {
    echo (
"I don't know what and there is some problem.<br />\n");
}
?> 
</p> 
<p> You can search by surname (either exact or partial)
  or by subject (either exact or partial).<br /> 
  Select the kind of research.</p> 
<p> 
<select name="<?php echo ("$choice");?>" value="surname" title="research"> 
<option value="surname"> professor's name</option> 
<option value="subject"> subject</option> 
<do type="text" label="Go"> 
<go method="get" href="index3.wml#card3"> 
<?php
echo ("<postfield name=\"$choice\" value=\"$"."$choice"."\"/>");
echo (
"<postfield name=\"choice\" value=\"$choice\"/>");
?> 
</go> 
</do> 
</p> 
</card> 
</wml> 
 

Again the decision is stored into variable $choice.


Now the user must input the data as specified in the next file, index3.wml. We ask the user to insert the name of a subject or the surname of a professor. Look how variables are sent, in this page and in the previous. The syntax is pretty complex, but it lets you handle all the whole process, with only a few files.

<?php

Header
("Content-type: text/vnd.wap.wml");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo 
"<?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="card3" title="Name"> 
<?php

echo ("<p>Insert ");

if (${
$choice} == "surname") {
    echo (
"professor's surname (or part of it).<br />\n");
} else if (${
$choice} == "subject") {
    echo (
"the subject (or part of it).<br />\n");
} else {
    echo (
"Maybe there is some problem.<br />\n");
}

echo (
"<input type=\"text\" name=\"${$choice}\" />");

?> 
<do type="text" label="Go"> 
<go method="get" href="query.wml"> 
<?php

echo ("<postfield name=\"$choice\" value=\"$"."$choice"."\"/>");

echo (
"<postfield name=\"${$choice}\" value=\"$"."${$choice}"."\"/>");

?> 
</go> 
</do> 
<p> 
</p> 
</card> 
</wml> 
 

Writing the query

This file is the one responsible for handling the query. It's name is query.wml and we will analyze it more in depth.

<?php

Header
("Content-type: text/vnd.wap.wml");
printf("<?xml version=\"1.0\"?>\n");
printf("<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" "
        
."\"http://www.wapforum.org/DTD/wml_1.1.xml\" >\n");
printf("<wml>\n");


//    The next lines are used to build
//    the sql query for receiving hours:

$consulting_tables =
    
"(professors left join teach on (professors.Id = teach.Id), subjects)";
$consulting_columns =
    
"professors.Surname, professors.Name, subjects.Subject , ";
$consulting_columns .=
    
"subjects.Cod_number, professors.Consulting_hour, professors.Consulting_place";
$consulting_query=
    
"subjects.Cod_Subject = teach.Cod_subject ";


//    The next lines are used to build the
//    sql query for examination timetables:

$exams_tables"(exams left join professors ON (exams.Id = professors.Id), subjects)";
$exams_columns"subjects.Subject , subjects.Cod_number, professors.Surname, ";
$exams_columns.= "professors.Name, exams.Date, exams.Time, exams.Room, exams.Test";
$exams_query"exams.Cod_Subject = subjects.Cod_Subject ";

//  The next lines are used to add options to the sql query for examination timetables:


if ($exams_data) {

    switch(
$exams_data) {
        case 
"subject":
            
$exams_query.= " and subjects.Subject like '%$subject%'";
            break;
        case 
"surname":
            
$exams_query.= " and professors.Surname like '%$surname%'";
            break;
    }
}


// The next lines are used to to add options to the sql query for receiving times:

if ($consulting_data) {
    switch(
$consulting_data) {
        case 
"subject":
            
$consulting_query
                
.= " and subjects.Subject like '%$subject%'";
            break;
        case 
"surname":
            
$consulting_query.= " and professors.Surname like '%$surname%'";
            break;
    }
}


// handles the connection with database


function connect($tables$data$condition_passed) {
    
//
    //    put your password and username in next line
    //

    
$db mysql_pconnect("localhost","***","***");

    
// put your database name in next line

    
mysql_select_db("lanfranchi_co_uk",$db);

    
$sql "SELECT $data FROM $tables WHERE $condition_passed order by professors.Surname";
    
$result mysql_query($sql,$db);
    return 
$result;
}


// this function writes the wml code for receiving hours


function consulting_print($consulting_result) {
    global 
$file;
    
printf("<card id=\"card1\" title=\"hours\">\n");
    
printf("<p>Receiving hours</p>\n");
    
    while (
$myrow mysql_fetch_row($consulting_result)) {
        
printf("<p>$myrow[0], $myrow[1]</p>\n");
        
printf("<p>$myrow[2]</p>\n");
        
printf("<p>$myrow[3]</p>\n");
        
printf("<p>$myrow[4]</p>\n");
        
printf("<p>$myrow[5]</p>\n");
    }
    
printf("</card>\n");
}


// this function writes the wml code for examination timetables

function print_exams($exams_result) {
    global 
$file;
    
printf("<card id=\"card1\" title=\"hours\">\n");
    
printf("<p>Examinations hours</p>\n");
    while (
$myrow mysql_fetch_row($exams_result)) {
        
printf("<p>$myrow[2], $myrow[3]</p>\n");
        
printf("<p>$myrow[0]</p>\n");
        
printf("<p>$myrow[1]]</p>\n");
        
printf("<p>$myrow[4], $myrow[5]</p>\n");
        
printf("<p>$myrow[7]</p>\n");
        
printf("<p>$myrow[6]</p>\n");
    }
    
printf("</card>\n");
}


// checks if you selected reciving hours or examination
//timetables, connects to the database and calls the
//function to the write wml code

if ($consulting_data) {
    
$connection_result =
        
connect($consulting_tables$consulting_columns$consulting_query);
    
consulting_print($connection_result);
}
if (
$exams_data) {
    
$connection_result =
        
connect($exams_tables, $ exams_columns, $ exams_query);
    
print_exams($connection_result);
}
printf("</wml>\n");

?>

The End

We have finished. Your first PHP/WML pages are ready to get the data from your MySQL database.
-- Andres