Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Database

PHP & Hosted Applications


Jan01: PHP & Hosted Applications

Ahmad is an independent consultant and writer. He can be contacted at ahmad@ apicalconsulting.com.


So Why PHP?


PHP is a server-side scripting language, most often used to spice up static web pages served from UNIX-based Apache servers. However, PHP 4 (the current version, available at http://www.php.net/) runs on almost any operating system used for web hosting. PHP also supports numerous web servers, including Microsoft's Internet Information Server (IIS), Apache, and AOL Server, and it has native support for multiple database engines such as Microsoft SQL Server, Oracle, MySQL, and mSQL, to name a few.

PHP is embedded in HTML code (or vice versa) using special tags. The web server invokes the PHP engine to process the PHP code before it sends the output to the browser with whatever HTML is already on the page. The browser sees only an HTML page.

PHP is well suited for performing system-level functions, such as file and folder manipulation. It can access databases to retrieve, insert, modify, and delete data from a database server. PHP can interpret form data and perform actions based on form requests. It can also encrypt data, handle cookies, generate images on the fly, perform session management, and perform identification, authentication, and authorization functions — all on the fly.

The Making of a Hosted Application

Additionally, PHP 4 can be used as part of a hosted application on remote servers. Many such hosted applications can be developed using back-end databases, a business layer written in PHP, and a front-end developed in DHTML and JavaScript.

To illustrate how you can use PHP to create hosted applications, I'll present in this article an electronic survey application that can be hosted on your servers and used by remote clients to survey end users. A global enterprise with scattered departments might use an application like this to survey employees for benefits information or customers for product feedback and market research. Such an application does not have to be limited to this particular usage, however. It can be used in voting, opinion polling, product registration, or similar pursuits.

Although the hosted app I present here uses the MySQL database, you can also use Microsoft SQL Server and Oracle with PHP. If you use a lot of stored procedures, complex subqueries, or data integrity via foreign-key constraints, you should probably opt for something other than MySQL. Since this application does not use any of the aforementioned functions, MySQL is a good choice.

The PHP code consists of three main pieces:

  • A tool that lets users create a survey from scratch and store it on the remote server.
  • The survey client application, allowing users to complete the survey.

  • An administrative tool that lets survey administrators check the results of completed surveys. (Once the application is developed, however, it can run itself.)

When you first access the system to create a new survey, you are prompted to enter a name, description, and the total number of questions in the survey. This information is collected in a form and submitted to a PHP page called "step2.php." Rather than being a slow new process invocation, PHP is invoked as a Server API (SAPI) application. PHP is good at processing information sent by users (the values of complex form selects, radio buttons, and other form elements). Listing One, which shows the relevant code of the first page in the application, produces a simple form to collect user input with a JavaScript validation function to ensure users entered all required data in the appropriate format. The real action occurs in step2.php, at which time all of the form input elements are readily available as variables in the script. Thus, the code in step2.php (see Listing Two) can access the variables $survey_name, $survey_description, and $survey_questions without extra logic to handle the form's data. In contrast, if you are using ASP/VBScript, you will need to access the form variables using the built-in Request() object and QueryString collection.

The next step is to create a list of questions for users to answer, each with a question type. This application lets users create free text questions or multiple-choice questions. The multiple-choice questions can accept either one answer (radio buttons) or multiple answers (check boxes). You should track the number of questions needed, the text for every question, the type of question (before dynamically generating other HTML forms to input the text questions), and the multiple choices where applicable. The available approaches for holding the information include:

  • Store information in the database.
  • Store information in the session.

  • Store information as hidden form variables and carry it across requests.

With PHP, all of these are valid options. With its simple database interface, connection pooling, and persistent connections, you can efficiently store the information in the database and carry over a survey ID from one request to another. Whenever the information is needed, it can be picked up from the database.

With PHP 4's Session Management interface, the process is even more straightforward. You have to register your form variables (which PHP created on the fly to start with) as session variables, and all the information is accessible in all PHP scripts invoked in that same session. You can then carry the information over in the form's request collection from one page to another. Step2.php takes that approach in Listing One.

If you have never used server-side scripts, a brief explanation is in order. The tags <? and ?> are used to delimit PHP code. Lines outside those tags are normal HTML. PHP code can be intermixed with HTML. Regardless of its place in the file, all PHP code gets executed on the server before the HTML page is generated. The printf() function is used to generate output that will become part of the final HTML sent to the browser. The semicolons (;) and the braces ({}) are part of the syntax familiar to C/C++ programmers. You may be confused initially by the dollar ($) signs. They are just the way variables are named in PHP. Just remember to prefix all variable names with $.

All form variables from the previous form appear immediately in the new script. Also, the three hidden input elements in the new form ensure that the $survey_questions, $survey_name, and $survey_description variables are carried across without any special code or logic to handle them. The loop generates one select statement and one text input for every question in the survey. Users specify the type of the question and the number of choices available per question.

The next step, step3.php (Listing Three), follows the same concept. PHP takes care of passing all the form input values to your script. Two nested loops generate the form input elements needed to collect all the information. The outer loop iterates through the questions, generating form input elements for the text of each question. The inner loop iterates through the multiple choices per question, if applicable, thus generating form input elements for the text of each choice. A puzzle that you may encounter is what to name the form elements holding the text for the multiple choices. PHP 4 has a useful feature that lets you name those variables using 2D array notation, for example:

printf ("<input type=checkbox name= check_box[$i][$j]>");

This resultant HTML form has a line that looks something like the following:

<input type=checkbox name=check_box [0][1]>

HTML has no problem with this notation, even though PHP 3 (and other scripting languages) would not know how to handle the variable in the target form. With PHP 4, however, you have a variable called $check_box[0][1] that holds the input value. Since that variable is an actual array element, you can use a nested loop to iterate through all its elements.

After all the data are collected, it is time to insert the values into the database. PHP has built-in support for a large number of databases as well as connectivity to any ODBC-enabled database. (Perhaps a future PHP version will introduce a common set of database functions to isolate the code from the actual DBMS being used. Until then, you have to make calls that are specific to your DBMS.)

For example, Listing Four creates an entry in a table called "Survey" within a MySQL database called "Surveys." Examples 1, 2, and 3 show three MySQL tables created for this application. The ID is an automatically generated ID for the survey. Under Microsoft SQL Server, this type of field is called Identity; under Oracle, you will need to create another object called Sequence, but the idea is the same. Name and Description are both strings of variable size. MySQL limits the size to 255 characters: Other databases have a more liberal limit.

There are two mistakes to avoid here. Commonly, users choose a small limit for the size of a varchar field. Because this is a variable-length field, you only use space equivalent to the length of the actual string used (plus some overhead), and not the upper limit. Thus in most cases, it does not make sense to use anything smaller than 255. If you are in doubt, keep it at 255 and enforce a length limit in your code that is easier to change in the future. The other problem you have to be aware of is the internationalization of dates. Recently, an application of mine started failing in England when the date generated by my ActiveX components failed to insert into a SQL database after the user changed the date format on the server. Make sure you use either the built-in database date functions to insert the current date, or use functions based on the locale if you are generating the date values in your code.

The other two tables holding the survey data are Questions and Choices, as shown in Examples 2 and 3. You join the Survey with the Questions in the code based on the SurveyID field in the Questions table. Similarly, you join the Choices with Questions using the QuestionID field.

All the data can be inserted using code similar to the mysql_query() code in Listing Four. By making the ID an auto_increment primary key, you get MySQL to provide you with the last inserted ID using the PHP function mysql_insert_id().

The flip side of the application lets users take and complete the survey. Users key in the ID of the survey, and the application performs a select statement against the database. A loop on the result set generates an HTML form with elements for every question. The form gets submitted to a final PHP script that takes the answers and inserts them into an Answers table that may look something like Example 4.

The listings and examples presented here form the basis of a complete survey application. I left some of the code for your imagination, but it is easy to see how you can develop a full-blown online application using PHP and a back-end database. PHP 4 compiles all the code in a page before executing it, making it fast, efficient, and perfect for such applications. Another advantage is that you will not encounter "syntax error" surprises because all of those are detected at compile time and not at run time.

Conclusion

For developing more complex applications, PHP 4 can invoke Java objects, and in Win32 environments, it can create and invoke COM objects. This functionality is similar to what ASP provides through the Server.CreateObject method. For example, under ASP, if you decide to create a separate COM component to perform database queries and hold large result sets, you can then create the object and call functions in it in a fashion similar to the code in Listing Five. In short, PHP 4 provides the same functionality for COM and Java objects. For example, Listing Six shows how code from Listing Five looks in PHP. This lets you reuse existing components, as well as move complex code to components if you so wish.

DDJ

Listing One

<form method="post" name="create_survey" action="step2.php" 
onsubmit="return validate();">
    <table border=0 cellspacing=2 cellpadding=2>
        <tr>
            <th> Please enter the survey's name </th>
            <td> <input type="text" name="survey_name"> </td>
        </tr>
        <tr>
            <th> Please enter a short description </th>
            <td> <input type="text" name="survey_description"> </td>
        </tr>
        <tr>
            <th> Please enter the number of questions in the survey </th>
            <td> <input type="text" name="survey_questions"> </td>
        </tr>
        <tr> 
            <td> <input type="Submit" Value="Create Survey">
        </tr><
/table>    <
/form>

Back to Article

Listing Two

<html><
head><
/head><
body><
form id="create_questions" name="create_questions" 
                                          action="step3.php" method=post><
?
    printf ("<input type='hidden' name=survey_questions 
                                          value=$survey_questions>");
    for ($i=0;$i<$survey_questions;$i++) {
        $j = $i+1;
        printf ("Select Question Type for Question $j <p>");
        printf ("<select name='questions_type[$i]'>");
        printf ("<option value=0> Free Text Answer");
        printf ("<option value=1 selected> Radio Button Answer");
        printf ("<option value=2> Check Box Answer");
        printf ("</select>");
        printf ("<br>If Radio Button or Check Box:<br> <dl> ");
        printf ("<dd> Number of Choices ");
        printf ("<input type=text length=5 name=choices[$i] value=3><br>");
        printf ("<dd><input type=checkbox name=isCheck[$i] value=selected>");
        printf ("Provide an Other option</dl>");
        printf ("<hr color=blue>");
    }
?><
input type="submit" value="Goto Step 3"><
/form><
/body><
/html>

Back to Article

Listing Three

<html><
body>
    <form method=post name=create id=create action="createit.php">
    <?
        printf ("<input type='hidden' name=survey_questions 
                                               value=$survey_questions>");
        $choice_counter=0;
        for ($i=0;$i<$survey_questions;$i++) {
            echo "<br>";
            $j=$i+1;
            echo "<big>Question #$j is: </big> ";
            echo "<input type=text id=question_text[$i] 
                                               name=question_text[$i]>\n";
            echo "<input type='hidden' name=choices[$i] 
                                               value=$choices[$i]>\n";
            printf ("<input type=hidden id=questions_type[$i] 
                      name=questions_type[$i] value=$questions_type[$i]>\n");
            switch ($questions_type[$i]) {
                case 0:
                    echo "<p>";
                    break;
                case 1:
                    printf("<br>  ");
                    for ($counter=0;$counter<$choices[$i];$counter++) {
                        printf ("Choice #$counter: <input type=text 
                            id=choice_text[$choice_counter] 
                            name=choice_text[$choice_counter]>\n");
                        if ($counter && ($counter % 2 == 0)) echo "<br>\n";
                        $choice_counter++;
                    }
                    break;
                case 2:
                    printf("<br>  ");
                    for ($counter=0;$counter<$choices[$i];$counter++) {
                        printf ("Choice #$counter: <input type=text 
                            id=choice_text[$choice_counter] 
                            name=choice_text[$choice_counter]>\n");
                        if ($counter && ($counter % 2 == 0)) echo "<br>\n";
                        $choice_counter++;
                    }
                    break;
                default:
                    echo $questions_type[$i];
                    break;
            }
            echo "<hr color=red>";
        }
    ?>
    <input type="submit" Value="Create Survery" >
    </form><
/body><
/html>

Back to Article

Listing Four

$stmt = "insert into surveys.survey (name,lastupdate,DateCreated,OwnerID, ";
    $stmt = $stmt . "Description,isClosed) values 
                                            ('$survey_name',now(),now(),0";
    $stmt = $stmt . ",'$survey_description',0)";
    if (!(mysql_query($stmt)) {
{
        printf ("Failed in Creating the Survey Entry...");
        exit();
    }

Back to Article

Listing Five

<%
            Dim myObject
            Set myObject = Server.CreateObject("MyProject.MyClass")
            Dim myString
            myString = myObject.GetDataBaseName
            Response.Write "The Database name is " & myString
        %>

Back to Article

Listing Six

        <?
            $myObject = new COM("MyProject.MyClass");
            $myString = $myObject->GetDataBaseName();
            echo "The Database name is $myString";
        ?>


Back to Article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.