Storing other dates in MySQL

Một phần của tài liệu The Essential Guide to Dreamweaver CS4 with CSS, Ajax, and PHP phần 9 ppsx (Trang 42 - 48)

A very simple way to handle dates in user input is to use the YUI Calendar widget (see Chapter 8) or the Spry validation text field widget (see Chapter 9) to enforce a particular format. So if you’re in an enclosed environment, such as an intranet, where you can guar- antee compliance—and that JavaScript won’t be disabled—this might be your solution.

However, getting Internet users to adhere to rules is rather like herding cats. It’s far safer to ensure accurate date input by providing separate fields for month, day of the month, and year, and then to use PHP to verify and format the input.

In the examples/ch17 folder of the download files, you will find a page called fixed_date_start.php. When you load it into a browser, it displays a drop-down menu preset to the current month, together with two text fields for the date and year, as shown in Figure 17-17. The Max Charssettings for the text fields have been set to 2 and 4, respec- tively, to limit the range of mistakes that can be made.

Figure 17-17.Providing separate fields for the date parts is the most reliable way of inserting dates accurately.

The drop-down menu for the month is created in two parts. The first section of code goes in a PHP block above the DOCTYPEdeclaration and consists of an array of the names of the months, plus the PHP getdate()function. This is how it looks:

$months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', ➥ 'Sep', 'Oct', 'Nov', 'Dec');

$now = getdate();

The getdate()function produces an associative array that contains a number of useful date parts, such as the year, weekday name, and so on. When used without an argu- ment like this, getdate()returns information about the current date, so you can find the number of the current month in $now['mon']and use it to preset the drop-down menu. You can find a full list of the array elements returned by getdate()at http://

docs.php.net/manual/en/function.getdate.php.

The code for the drop-down menu looks like this:

<label for="select">Month:</label>

<select name="month" id="month">

<?php for ($i=1;$i<=12;$i++) { ?>

<option value="<?php echo $i < 10 ? '0'.$i : $i; ?>"

<?php if ($i == $now['mon']) {

echo ' selected="selected"'; } ?>><?php echo $months[$i-1]; ?>

</option>

<?php } ?>

17

This uses a for loop to populate the menu’s <option>tags. Although counters normally begin at 0, I have set the initial value of $ito 1, because I want to use it for the value of the month.

The second line highlighted in bold uses the conditional operator (see Chapter 10) to test whether $iis less than 10. If it is, a leading zero is added to the number; otherwise, it is left alone. Another way of writing it would be to use this:

if ($i < 10) { echo '0'.$i;

} else { echo $i;

}

The third line of PHP checks whether the value of $iis the same as $now['mon']. If it is, the following line inserts selected="selected"into the opening <option>tag. The final part of the script displays the name of the month by drawing it from the $monthsarray.

Because indexed arrays begin at 0, you need to subtract 1 from the value of $ito get the right month.

To validate the input from the month, date, and year input fields and format them ready for MySQL, I have created the following function:

function formatMySQLDate($month, $day, $year, &$error) {

$mysqlFormat = null;

$m = $month;

$d = trim($day);

$y = trim($year);

if (empty($d) || empty($y)) {

$error = 'Please fill in all fields';

} elseif (!is_numeric($d) || !is_numeric($y)) {

$error = 'Please use numbers only';

} elseif (($d <1 || $d > 31) || ($y < 1000 || $y > 9999)) {

$error = 'Please use numbers within the correct range';

} elseif (!checkdate($m,$d,$y)) {

$error = 'You have used an invalid date';

} else {

$d = $d < 10 ? '0'.$d : $d;

$mysqlFormat = "'$y-$m-$d'";

}

return $mysqlFormat;

}

I have not created similar drop-down menus for the day and year because PHP is a server-side language. Although you could create a script to display the correct number of days for the month, you would have to reload the page every time the month was changed. You could create an intelligent date input system with JavaScript, but that makes the dangerous assumption that all users will have JavaScript enabled.

The formatMySQLDate()function is one of the snippets you installed in the PHP-DWCS4 folder of the Snippetspanel in Chapter 11. It takes four arguments: the month, date, and year values submitted by the form, and a variable to hold any error messages. The fourth argument should be an empty string ready to capture any error message.

In the function definition, the fourth argument is preceded by an ampersand (&). This is the same technique I used in the isSuspect()function in Chapter 11. Normally, passing a variable to a function simply uses a copy of its value; anything that happens in the function has no effect on the variable’s original value. However, preceding the argument by &in the function definition passes the actual value to the function, so any changes inside the func- tion are reflected in the main script. This is a technique known as passing by reference because it passes a reference to the actual value, rather than a copy.

Let’s take a quick look at what happens inside the formatMySQLDate()function. It begins by setting a variable called $mysqlFormatto null. This will be used as the value the func- tion returns, so it will remain nullif any errors are found. You don’t need to perform any checks on the value of the month, because the drop-down menu has generated it. So, after trimming any whitespace from around the date and year, they are subjected to the first three checks: to see whether they are empty, not numeric, or out of range. You have met the empty()function before. The second check uses is_numeric(), which is basically self-explanatory. It takes advantage of PHP’s loose typing. In strict terms of datatypes, the content of a text field is always a string, but is_numeric()also returns trueif a string con- tains a number, such as '5'. (No, it’s not clever enough to recognize 'five'as a number.) The third test looks for numbers within acceptable ranges. It looks like this:

elseif (($d <1 || $d > 31) || ($y < 1000 || $y > 9999)) {

The values set for the day (1–31) are immediately understandable, even though they don’t apply to every month. The range for years (1000–9999) is dictated by the legal range for MySQL. I suggest that you use a narrower range, more in line with the requirements of the application you’re building. In the unlikely event that you need a year out of that range, you must choose a different column type to store the data. MySQL was not designed to handle stardates from Star Trek: The Next Generation!

By using a series of elseifclauses, this code stops testing as soon as it meets the first mis- take. If the input has survived the first three tests, it’s then subjected to the PHP function checkdate(), which really puts a date through the mill. It’s smart enough to know the dif- ference between February 29 in a leap year and an ordinary year.

Finally, if the input has passed all these tests, it’s rebuilt in the correct format for insertion into MySQL. The first line of the final elseclause uses the ternary operator, as described earlier, to add a leading zero to the day of the month if necessary. The function returns the date wrapped in single quotes, so it can be inserted directly into a SQL query. If an error is found, the function returns null, and the error message can be retrieved from the vari- able passed as the fourth argument to formatMySQLDate().

Now that you have seen what the formatMySQLDate()function does, let’s incorporate it into a page to insert a user-defined date into MySQL.

17

The following exercise uses the formatMySQLDate()function to validate and format a date ready for insertion into MySQL. It uses the date_testtable that was created for the pre- ceding exercise.

1.Copy fixed_date_start.phpfrom examples/ch17, and save it in workfiles/ch17 as fixed_date.php. The file is based on current_date.phpfrom the previous exer- cise, so it contains a hidden field called created to set the current date for the second TIMESTAMPcolumn.

2.Apply an Insert Record server behavior. The names of the fields for the date parts no longer match the fixed_datecolumn in the date_testtable, so you need to select fixed_date in the Insert Record dialog box, and select one of the date part fields from the Valuedrop-down menu, as shown in Figure 17-18.

Figure 17-18.You need to select one of the date part fields to match the database column.

3.The other settings should be fine, so click OKto apply the Insert Record server behavior.

4.Locate the Insert Record server behavior code in Code view, and insert the follow- ing code at the point indicated in Figure 17-19:

// initialize string for error message

$error = '';

if (array_key_exists('insert', $_POST)) { // formatMySQLDate definition goes here // format the date parts

$mysqlDate = formatMySQLDate($_POST['month'], $_POST['date'], ➥

$_POST['year'], $error);

}

Inserting a user-defined date into MySQL

Figure 17-19.The code to format the date needs to go before the INSERT query.

17

The new code begins by initializing an empty string to hold any error message gen- erated by the formatMySQLDate()function. A conditional statement then checks whether the insert form has been submitted. If it has, you need to define the formatMySQLDate()function and then pass the date parts and the $errorvariable to it.

If the date parts constitute a valid date, $errorwill remain an empty string, so the second conditional statement will equate to false, letting the Insert Record server behavior go ahead.

5.Tidy up the code you have just inserted by inserting the formatMySQLDate()func- tion definition from the PHP-DWCS4folder of the Snippetspanel (it’s called Format date for MySQL). Also add a closing curly brace for the second conditional state- ment just after the Insert Record server behavior code (line 48 in Figure 17-19, although the line number will have increased to about 74).

6.The next task is to edit the code that inserts the values into the SQL query. The code shown on line 41 of Figure 17-19 should look like this:

GetSQLValueString($_POST['created'], "defined", 'NOW()'),

This is the same edit as in the previous exercise, so it needs no explanation.

7.The line that inserts the user-defined date is on line 42 of Figure 17-19. It needs to be edited like this:

GetSQLValueString($_POST['month'], "defined", $mysqlDate),

The insert code won’t run if an error has been detected by formatMySQLDate(), so you know that $mysqlDatemust contain a valid date in MySQL format. The date is already formatted with quotes, so it can be inserted directly into the SQL query.

8.The final change you need to make is to add a warning if the INSERTquery didn’t run. Add the following code between the page heading and insert form:

<?php

if (isset($error)) { echo "<p>$error</p>";

}

?>

9.Save fixed_date.php, and load it into a browser. Test it by adding a message and selecting a date. Then check that it has been inserted correctly into the date_test table. Also try an invalid date, such as Feb 29, 2007. You should see an error mes- sage, and nothing will be inserted into the database.

You can check your code, if necessary, against fixed_date.phpin examples/ch17.

These exercises have dealt only with the Insert Record server behavior, but you use the same techniques to handle dates in the Update Record server behavior.

Now that you have stored dates correctly in MySQL, how do you make them look accept- able to visitors to your site? Many developers who have already dabbled with PHP attempt to use the PHP date()function (covered later in the chapter) to format the date. However, the date() function expects a timestamp based on the number of seconds since the beginning of 1970; a MySQL timestamp is incompatible. Although it’s perfectly possible to use PHP to format the date, it’s much more efficient to get MySQL to do all the work for you, as explained in the next section.

Một phần của tài liệu The Essential Guide to Dreamweaver CS4 with CSS, Ajax, and PHP phần 9 ppsx (Trang 42 - 48)

Tải bản đầy đủ (PDF)

(94 trang)