Navigation


Lesson: Making decisions

Goals

Write more programs that make decisions, including server-side validation. We'll see how you can use functions to make code easier to write and understand. We'll look at page redirection, and create a simple log in system.

Notes

Let's create a simple log in system. In this topic, we'll do the input form an some basic checking. Later, we'll see how you can use session variables to let the log in system protect pages.

Let's start with the simplest thing we can do. You can try it here.

Here is the architecture of the system:

Architecture

You can check out the HTML for the log in form yourself. Let's focus on the server-side.

Here is the PHP code for check_login.php:

<?php
//Get user input.
$userName = $_POST['userName'];
$userPassword = $_POST['userPassword'];

//Log in OK?
if ( $userName == 'Willow' && $userPassword == 'Tara') {
   header('Location: login_success.php');
   exit();
}

//Jump to bad login.
header('Location: login_fail.php');
exit();
?>

The only new thing is the header. This inserts an HTTP header into the output. Headers must be output before anything else. Even a lowly space above the opening PHP tag will cause this to fail! Note the exit() right after the header. This causes the PHP script to stop at once. So only the header is output.

There are lots of different HTTP headers. The one we want here causes the browser to redirect to a different page. Which page it goes to depends on whether the log in data supplied by the user was correct or not.

A testing time

On an earlier page, I talked about some of the ways to use tests to handle strings and numbers. Business data often involves dates and times. Date/time processing can actually get quite complicated, what with leap years, time zones, daylight saving, different calendars (Jewish, Chinese, Western), etc. We won't talk about it in detail, but let's look at a few wrinkles.

In your business work, you'll see dates/times in three main formats:

  • Human time
  • ISO 8601
  • Unix timestamp

There are many formats designed for people to use, like May 18, 2013, and 12/8/2018. They are used differently in different countries. For example, 12/8/2018 is August 12, 2018 in Australia, but it's December 8, 2018, in the US. Why? Just because.

ISO 8601 is often used in databases. A common format is YYYY-MM-DD hh:mm:ss. Software translates that into whatever form users want.

A Unix timestamp (often called just a timestamp) is a different dog entirely. It's a count of the number of seconds that has elapsed since 1/1/1970 (or 1902, if you allow negatives). Timestamps make date arithmetic possible. For example, suppose your company rents out evil robot clowns (ERCs) by the hour. When someone returns one, you want to figure out how many hours s/he had the ERC, so you can compute the bill. Your program takes the time the customer took the clown, and converts it into a timestamp (making it a count of seconds since 1970, tick tick). Then take the time the ERC was returned, and convert it into a timestamp (also number of seconds since 1970, but more of them). Subtract one from the other, and you know how many seconds the customer had the ERC. Divide that by 3,600 (the number of seconds in an hour), and you know how many hours the ERC was rented.

Here's some code that will find the difference between two times, given in hh:mm:ss format. The result will be in hh:mm:ss format as well.

$time1TS = strtotime($time1); //Convert from hh:mm:ss to timestamp.
$time2TS = strtotime($time2);
$diff = abs($time1TS - $time2TS); //Compute difference.
$fullHours = floor($diff/3600);
$fullMinutes = floor( ($diff - $fullHours*3600) / 60 );
$seconds = $diff - $fullHours*3600 - $fullMinutes*60;
//Format as hh:mm:ss.
$timeDiff = date('H:i:s',strtotime($fullHours.':'.$fullMinutes.':'.$seconds));

strtotime() has another useful feature. If the value you give it is invalid, it returns false. You can use it like this:

$timeString = $_POST['timeFromUser'];
$timeTS = strtotime(trim($timeString));
if ( ! $timeTS ) {
    print "<p>Dude(tte)! The time you gave me ({$timeString}) isn't valid!</p>";
}
else {
    //Time is OK.
    ...

There's lots more we could say about time, but let's not.

Exercises

Exercise 1. Character case.

Change the PHP code so that the user name and password are not case sensitive.

Note: This is not necessarily good practice, but it's a useful exercise.

Try it.    Solution (try it yourself first).

Exercise 2. One server-side error message.

Change the PHP code so that if there is an error, the user is told what the error is on login_fail.php. Error messages: "User name incorrect," "Password incorrect," "User name empty," and "Password empty." If there are multiple errors, your code need only display the first error.

Try it.    Solution (try it yourself first).

Exercise 3. Multiple server-side error messages.

Change the PHP code so that if there is an error, the user is told what the error is on login_fail.php. Error messages: "User name incorrect," "Password incorrect," "User name empty," and "Password empty." If there are multiple errors, your code should display all of them.

Question: how many error messages does your code show if the user name is empty? One, or two? How many should it show?

Try it.    Solution (try it yourself first).

Exercise 4. More server-side validation.

Change the PHP code to add error messages if the user name and/or password are too short (less than 4 characters) or too long (more than 20 characters).

Try it.    Solution (try it yourself first).

Exercise 5. Hiding the right stuff.

Change the PHP code so that the PHP code does not include the user name and password in clear text. One way to do this is to use MD5. This site might be useful.

Note: this is harder to make case insensitive. Make it case sensitive (easier to code).

Try it.    Solution (try it yourself first).

Exercise 6. Average of three

Write a program to find the average of three numbers entered by the user. Show error messages if any of the values the user inputs are not valid numbers.

Try it.   Solution (try it yourself first).

Exercise 7. Mortgage calculator

Write a program to find the mortgage payment given loan amount, interest rate, and term. Show error messages if any of the values the user inputs are not valid numbers. Check for fields that have just white space in them. Check for out of range numbers, like negative loan amounts. Output the payment amount in dollars.

Here is the code I used for computing payment amount.

$payment = ($month_ir+($month_ir/(pow(1+$month_ir,$term*12)-1)))*$loan_amount;

Try it.   Solution (try it yourself first)

Change the program so that no matter whether the user enters 4.5 or .045 in the interest rate field, the program will still use an annual interest rate of 4.5%.

Change the program so that it shows a dancing (or spinning or whatever) dollar sign (or $100 bill or whatever) for loans over $250,000.

Change the program so that it will output the total paid over the life of the loan, and how much of that is principal and how much is interest.

Exercise 8. Compatibility

Write a program that checks whether two people are compatible, based on their names. It shows a first name and last name field for each person. All fields are required. Your program should check for missing data, and show all error messages at once.

Compatibility depends on the first letters of the first and last names. Specifically, where in the alphabet the letters occur, the first part (A-L) or the last part (M-Z). Two people are compatible if the first letters of their first names are in the same part of the alphabet, and the first letters of their last names are in different parts of the alphabet.

Output the names, and whether the two people are compatible.

Try it.   Solution (try it yourself first)

Extra: In your output, make sure that the first letter of every first and last name is capitalized, no matter what the user typed.