Introduction

One of the most time-consuming tasks of any web application developer is dealing with forms. Not only must you decide what information to place onto the form and design the HTML for it, but you also must validate the submitted form data and process it. Fortunately, server-side scripting languages such as Perl and PHP have made our lives much easier, as we can use them to handle repetitive tasks rather than placing the work on ourselves. In this article, we'll take a look at a common task for applications such as calendars and appointment books: handling dates and times.

Selecting Dates and Times

The easiest way for a developer to deal with dates and times is to have the user enter them in a text field as a specific format such as "yyyy-mm-dd," and use PHP's strtotime() function on them. As all user interface developers should know though, users have a habit of not doing what you tell them to do. They might enter in an invalid date without realizing it, or they might mix up the syntax and type "mm-dd-yy" as U.S. users are prone to doing. In order to alleviate the possibility of errors, the <select> element can be used to limit input to specific ranges and ensure proper formats.

By replacing a text field such as

Enter Date (ex: 2002-06-07):

with the select fields

Date (Year-Month-Day): -

-

You can ensure that the input will be in the correct format and within the range that you specified.

Of course, it can become a real hassle to write out the various <select> and <option> tags every time you want to use a date field in a form, so why not have PHP do it for you? The following function will write out a select date field for you given a prefix for the fields, the method of the form, the beginning year of the range, and the ending year of the range.

function WriteDateSelect($BeginYear = 0, 

$EndYear = 0,

$IsPosted = true,

$Prefix = '')

{

if (! $BeginYear)

{

$BeginYear = date('Y');

}

if (! $EndYear)

{

$EndYear = $BeginYear;

}

$Year = $IsPosted

? (int) $_POST[$Prefix . 'Year']

: (int) $_GET[$Prefix . 'Year'];

$Month = $IsPosted

? (int) $_POST[$Prefix . 'Month']

: (int) $_GET[$Prefix . 'Month'];

$Day = $IsPosted

? (int) $_POST[$Prefix . 'Day']

: (int) $_GET[$Prefix . 'Day'];

echo '-

-

';

return;

}

As it stands, you can call the function in the middle of your form like

<?php WriteDateSelect(2000, 2002); ?>

and it will generate the field -

-

, which will make date development in forms substantially easier. A similar function can easily be written to obtain the time of day from the user, but as for right now, let's take a look through this function and see how it operates.

Using The WriteDateSelect() Function

There are four arguments to be passed into the function: $BeginYear, $EndYear, $IsPosted, and $Prefix. There are default parameters for all of them, so you could literally call the function without any arguments at all like WriteDateSelect(), and it would produce the default field allowing the user to choose the current year only. Otherwise, you'll need to actually specify values in the function call. If you leave out the

Retrieving the Submitted Date

So now you can easily place date select fields into forms and guarantee that the user will have to choose from a predetermined range of values. However, that's only half of the work that we need to do, since we also need to process the information after the form is submitted. In order to do so, we'll introduce another utility function: GetDateSelectString().

function GetDateSelectString($IsPosted = true,

$Prefix = '')

{

if ($IsPosted)

{

return (int) $_POST[$Prefix . 'Year']

. '-' . (int) $_POST[$Prefix . 'Month']

. '-' . (int) $_POST[$Prefix . 'Day'];

}

return (int) $_GET[$Prefix . 'Year']

. '-' . (int) $_GET[$Prefix . 'Month']

. '-' . (int) $_GET[$Prefix . 'Day'];

}

As you can see, all this function does is to take the values in the POST or GET array, cast them to int to prevent any SQL injections, and then concatenate them together with dashes in between. Thus, if the user selected 2002 for the year, 5 for the month, and 12 for the day, this function will return the string "2002-5-12". This string can be used directly in a MySQL query statement such as

$PostedDate = GetDateSelectString();

mysql_query("SELECT * FROM Table WHERE LastDate = '$PostedDate'");

since MySQL natively understands the "yyyy-mm-dd" syntax, or the string could be converted to a PHP timestamp via the strtotime() function if you require further processing.

Retaining Previous Values

If you glance through the code for the WriteDateSelect() function above, you might notice the lines which say

$Year = $IsPosted

      ? (int) $_POST[$Prefix . 'Year']

      : (int) $_GET[$Prefix . 'Year'];

and

if ($i == $Year)

     echo 'selected="yes"';

The reason why these lines of code exist is that it's fairly common for a user to take more than one try to fill out a form correctly. Although you could use JavaScript to pre-validate the form client-side, that is not an guarantee that the data will be correct, as the user agent could not support JavaScript or have JavaScript disabled. Therefore, server-side validation is always needed for absolute assurance. The most common design is to have both the code which writes out the form and the code which validates and processes the form in the same script. In that way, if the user fails to complete a portion of the form, then the script writes out the form again for the user to make corrections.

Of course, the problem with this approach is that the form won't retain the previous data unless you explicitly write out the values which the user entered beforehand. That is exactly what these lines of code do: get the values of the elements from the $_POST or $_GET arrays, and then write out a selected attribute if the present option value matches that of the previous value. Thus, your users won't have to reselect the dates again, they will be happier, and you will be happier.

Downloading the Code

The code which I use in production is a bit different than the code posted here, as it has been organized into classes and some of the options have been moved into class variables. If you think that you would find it useful though, you can download it by going to my website and going to the section Downloads -> Jackson's Programs. I'm not posting a direct link because I may restructure the site in the future, but it will always be located in that section.