Because dates are ubiquitous in web interfaces, and because working with dates is often comparatively complicated, let's look at creating a class library to automate some of the work that dates can present. Along the way, we will revisit some of the techniques we have already covered.
The simple date_pulldown library created in this instance will consist of three separate select elements: one for day of the month, one for month, and one for year. When a user submits a page, the script will verify the form input. If there is a problem with the input, we will refresh the page with the user's input still in place. This is easy to accomplish with text boxes but is more of a chore with pull-down menus.
Pages that display information pulled from a database present a similar problem. Data can be entered straight into the value attributes of text type input elements. Dates will need to be split into month, day, and year values, and then the correct option elements selected.
The date_pulldown class aims to make date pull-downs sticky (so that they will remember settings from page to page) and easy to set. To create our class, we first need to declare it and create a constructor.
By the Way
A constructor is a function that exists within a class and that is automatically called when a new instance of the class is created.
We can also declare some class properties. We will step through Listing 24.6; this first snippet shows the beginning of the class.
Listing 24.6. Creating a Calendar Library
We first declare the $name property, on line 2. This will be used to name the HTML select elements. The $timestamp property, defined on line 3, will hold a UNIX time stamp. The $months array property, defined on lines 45, contains the strings we will display in our month pull-down. The $yearstart and $yearend properties (lines 6 and 7) are both set to 1, pending initialization. They will eventually hold the first and last years of the range that will be presented in the year pull-down.
The constructor is simple. It accepts a string, which we assign to the $name property. Now that we have the basis of our class, we need a set of methods by which the client code can set the date. Listing 24.6 continues as follows.
Of the methods shown here, setDate_timestamp() is the simplest (lines 1922). It requires a UNIX time stamp, which it assigns to the $timestamp property. But let's not forget the others.
The setDate_array() method (lines 2435) expects an associative array with at least three keys: mon, mday, and year. These keys will have data values in the same format as in the array returned by getdate(). This means that setDate_array() will accept a hand-built array such as
array("mday"=> 20, "mon"=>9, "year"=> 2003);
or the result of a call to geTDate():
It is no accident that the pull-downs we will build later will be constructed to produce an array containing mon, mday, and year keys. The method uses the mktime() function to construct a time stamp, which is then assigned to the $timestamp variable.
The setDate_global() method (lines 1217) is called by default. It attempts to find a global variable with the same name as the object's $name property. This is passed to setDate_array(). If this method discovers a global variable of the right structure, it uses that variable to create the $timestamp variable. Otherwise, the current date is used.
The ranges for days and months are fixed, but years are a different matter. As Listing 24.6 continues, we create a few methods to allow the client coder to set her own range of years (although we also provide default behavior) .
The setYearStart() and setYearEnd() methods are straightforward (lines 3643), in that a year is directly assigned to the appropriate property. The getYearStart() method tests whether the $yearstart property has been set, and if it has not been set, getYearStart() assigns a $yearstart value five years before the current year. The getYearEnd() method performs a similar operation.
We're now ready to create the business end of the class as Listing 24.6 continues.
The output() method orchestrates most of this code (lines 6069). It first checks the $timestamp property, and, unless one of the setDate methods has been called, the value of $timestamp will be set to 1, and setDate_global() will be called by default. The time stamp is then passed to the getdate() function to construct a date array, and a method is called to produce each pull-down.
The day_select() method (lines 7179) simply constructs an HTML select element with an option element for each of the 31 possible days in a month. The object's current date is stored in the $datearray argument variable, which is used during the construction of the element to set the selected attribute of the relevant option element. The sprintf() function formats the day number, adding a leading zero to days 19. The month_select() and year_select() methods (lines 81101) use similar logic to construct the month and year pull-downs.
Why did we break down the output code into four methods, rather than simply creating one block of code? When we build a class, we have two kinds of programmer in mind: one who will want to instantiate a date_pulldown object, and the one who will want to subclass the date_pulldown class to refine its functionality.
For the former, we want to provide a simple and clear interface to the class's functionality. The programmer can then instantiate an object, set its date, and call the output() method. For the latter, we want to make it easy to change discrete elements of the class's functionality. By putting all the output code into one method, we would force a child class that needed to tweak output to reproduce a lot of code that is perfectly usable. By breaking this code into discrete methods, we allow for subclasses that can change limited aspects of functionality without disturbing the whole. If a child class needs to represent the year pull-down as two radio buttons, for example, the coder can simply override the year_select() method.
Listing 24.7 contains some code that calls the library class. Before you try to execute this code, take the code from Listing 24.6, surround it with PHP opening and closing tags, and save into a file called date_pulldown.class.php. Place this file in the document root of your web server because Listing 24.7 uses it and it had better be there!
Listing 24.7. Using the date_pulldown Class
On line 6, we include the date_pulldown.class.php; after we have included the class file, we can use all of its methods. We use the class's default behavior for all the pull-downs, apart from "foundingdate". For this particular object, we override the default year start, setting it to 1972 on line 10. On line 12, we assign this pull-down an arbitrary date that will be displayed until the form is submitted (see Figure 24.6).
Figure 24.6. The pull-downs generated by the date_pulldown class.
By the Way
This is only the front end of a form, with no action or method; you need to supply your own action or method for this to actually do something!