Validation basics

Log in

If you're a student, please log in, so you can get the most from this page.

Multiple choice

What will this output? The URL is something.php?pet=cat

  1. <?php
  2. $petType = $_GET['pet'];
  3. if ($petType == 'dog' || $petType == 'cat' || $petType == 'goat') {
  4.     $message = 'Favored pet';
  5. }
  6. else {
  7.     $message = 'Not a favored pet';
  8. }
  9. print $message;
Saving
A

Favored pet

B

Not a favored pet

C

Can't tell from the information given.

Not graded. So why do it?

Multiple choice

What would this code output? The URL is ...something.php?weight=0.

  1. <?php
  2. if ($weight <= 0) {
  3.     $output = "<p>Sorry, weight must be positive.</p>";
  4. }
  5. else {
  6.     $shipping = $weight * 0.5;
  7.     $output = "<p>Shipping: $shipping</p>";
  8. }
  9. print $output;
Saving
A

The shipping cost.

B

An error message.

C

Can't tell from the information given.

Not graded. So why do it?

Multiple choice

What would this code output?

  1. <?php
  2. $color = 'black ';
  3. $color = strtolower(trim($color));
  4. if ($color != 'black') {
  5.     $message = "$color is the new black";
  6. }
  7. else {
  8.     $message = "$color is itself again";
  9. }
  10. print $message;
Saving
A

black is the new black

B

black is itself again

Not graded. So why do it?

Matt's Ella
Matt's Ella. A dog, not a horse.

Log in

If you're a student, please log in, so you can get the most from this page.

Goal

Let's make a PHP page that tells you the sales tax rate of a state. It will only work for Michigan and Illinois, though we could extend it easily. You can download it.

Try it with Michigan:

http://webappexamples.skilling.us/validation/basics/state-sales-tax-rate/state-sales-tax-rate.php?state=mi

With Illinois:

http://webappexamples.skilling.us/validation/basics/state-sales-tax-rate/state-sales-tax-rate.php?state=il

So this is on the end of the URL: ?state=something.

What if the state is invalid? Let's see:

http://webappexamples.skilling.us/validation/basics/state-sales-tax-rate/state-sales-tax-rate.php?state=qld

As we write the code, let's work out a programming pattern for validation, that we can reuse in other situations.

Principle

Reuse

Reuse your code across programs, using functions and page components.

Top and bottom chunks

Here's a typical PHP page.

  • <?php
  • // Some code that runs before any HTML has been produced.
  • ...
  • ?><!DOCTYPE html>
  • <html lang="en">
  •   ...
  •   <body>
  •     ...
  •     <?php
  •     // Code that runs while HTML is being processed.
  •     ...
  •   <body>
  • </html>

It's common to make a page as two chunks.

Two chunks

We made a pattern out of this.

Pattern

Computation at the top, simple output at the bottom

Put code for complex calculations in the top part of your program. That code puts values in variables. The bottom bit makes HTML using those variables.

Let's map our validation code into the two chunks.

  • <?php
  • // Code that runs before any HTML has been produced
  • // Get the user's input
  • // Check for errors
  • // If there are no errors
  • // Process the data
  • ?><!DOCTYPE html>
  • <html lang="en">
  •   ...
  •   <body>
  •     ...
  •     <?php
  •     // If there were errors
  •     // Show error messages
  •     // Else
  •     // Show processing results
  •     ...
  •   <body>
  • </html>

So the top chunk does input and processing. The bottom chunk does output, either of errors, or the results.

The top chunk has to tell the bottom chunk at least two things:

  • Validation errors, if any.
  • Processing results.

Passing data

Sales tax rate

OK, let's write a program that outputs a state's name and sales tax rate, when you give it a state name. For example, with the url something.php?state=mi, you would get:

Output

The top chunk

The top chunk does two things:

  1. Data validation
  2. Processing

We want to do the processing, only if data validation says the data is OK.

  • If input data is OK:
  •   Process the input data

For the sales tax program:

  • If input for state is MI or IL:
  •   Work out the sales tax

Let's bring in the the bottom chunk for a moment. It will need to know what errors there were, and the results of processing.

We'll use variables to tie the two pieces together.

All the variables

Like this:

  • Top:
  • If input for state is MI or IL:
  •   Work out the sales tax
  •  
  • Bottom:
  • If there were errors:
  •   Output error messages
  • Else
  •   Output state and tax rate
Adela
Adela

Wait, where did the error messages come from?

Oh, right. The top bit would work them out:

  • Top:
  • If not (input for state is MI or IL):
  •   Put something in an error message variable, like "State is bad"
  • Else:
  •   Work out the sales tax
  •  
  • Bottom:
  • If there were errors:
  •   Output error messages
  • Else
  •   Output state and tax rate

So an error message variable, and some other variables, tie the top and bottom of the program together. The top bit fills the variables, and the bottom bit uses them.

Several error types

Now, users can make different kinds of mistakes. The state could be missing from the input, if the URL was like this:

http://webappexamples.skilling.us/validation/basics/state-sales-tax-rate/state-sales-tax-rate.php?state=

Or this:

http://webappexamples.skilling.us/validation/basics/state-sales-tax-rate/state-sales-tax-rate.php

So that's one error to check for: the state is missing.

Another possible error is that the data is there, but is an unknown value.

http://webappexamples.skilling.us/validation/basics/state-sales-tax-rate/state-sales-tax-rate.php?state=qld

QLD isn't MI or IL, so there's an error.

Some programs can have many types of errors. Supposed we wanted users to input the number of doggos they have, like this: something.php?doggos=2

Some different types of errors:

  • The doggos value is missing: something.php, or something.php?doggos=
  • The doggos value is not a number: something.php?doggos=some
  • The doggos value is negative: something.php?doggos=-1
  • The doggos value is too large: something.php?doggos=8192

We want to write validation code that can handle all these types of errors.

Notice the dependencies between the error messages. For example, if there is no doggos value, there is no point in checking whether the doggos value is not a number. There's nothing to check!

Another: if the doggos value is not a number, there is no point checking whether it is negative. The concept of "negative" doesn't even apply to a value that is not numeric.

Let's start with this code for the top part of a program like this:

  1. Get input value
  2. Do error check 1
  3. If data passed error check 1:
  4.   Do error check 2
  5. If data passed error check 1 and 2:
  6.   Do error check 3
  7. If data passed error check 1, 2, and 3:
  8.   Do error check 4
  9. If data passed error check 1, 2, 3, and 4:
  10.   Do processing

So the processing (line 10) only happens if all of the check pass. Makes sense. No point in processing data that's faulty.

So, how do we write the code?

Ethan
Ethan

We'll need variables for all of the error checks, right?

Adela
Adela

Maybe... but maybe it could be simpler. Like, take this line...

  • If data passed error check 1, 2, 3, and 4:

It doesn't matter which error happened, right? If anything went wrong, we don't want to process.

So maybe:

  1. Get input value
  2. Do error check 1
  3. If no problems so far:
  4.   Do error check 2
  5. If no problems so far:
  6.   Do error check 3
  7. If no problems so far:
  8.   Do error check 4
  9. If no problems so far:
  10.   Do processing

Hey, good idea! We could use a flag variable. Like, maybe:

  1. // No errors yet.
  2. $isDataOK = true;
  3. Get input.
  4. If error 1 found:
  5.   // Something is wrong.
  6.   $isDataOK = false;
  7. If $isDataOK then:
  8.   // All OK so far, next error check.
  9.   If error 2 found:
  10.     $isDataOK = false;
  11. If $isDataOK then:
  12.   // All OK so far, next error check.
  13.   If error 3 found:
  14.     $isDataOK = false;
  15. If $isDataOK then:
  16.   // All OK so far, next error check.
  17.   If error 4 found:
  18.     $isDataOK = false;
  19. If $isDataOK then:
  20.   // No errors!
  21.   Process input.
Pattern

Flag

Use a variable as a flag. Set the flag if any of a number of things happens. After, check the flag to see if any of those things happened.

Adela
Adela

We still need a variable for the error message, though.

Oh, OK. I forgot.

  1. $isDataOK = true;
  2. $errorMessage = '';
  3. Get input.
  4. If error 1 found:
  5.   $isDataOK = false;
  6.   $errorMessage = 'Sorry, ...';
  7. If $isDataOK then:
  8.   If error 2 found:
  9.     $isDataOK = false;
  10.     $errorMessage = 'Sorry, ...';
  11. If $isDataOK then:
  12.   If error 3 found:
  13.     $isDataOK = false;
  14.     $errorMessage = 'Sorry, ...';
  15. If $isDataOK then:
  16.   If error 4 found:
  17.     $isDataOK = false;
  18.     $errorMessage = 'Sorry, ...';
  19. If $isDataOK then:
  20.   Process input.
  21.  
  22. Later...
  23. if (!$isDataOK) {
  24.   print $errorMessage;
  25. else {
  26.   print output from processing;
  27. }
Georgina
Georgina

Wait! Idea! If there are no errors, $errorMessage will be MT (empty), right?

We could use $errorMessage as a flag, as well as holding an error message!

Oh, I get it!

  1. $errorMessage = '';
  2. Get input.
  3. If error 1 found:
  4.   // Something is wrong, set error message.
  5.   $errorMessage = 'Sorry, ...';
  6. If $errorMessage == '' then:
  7.   // No errors so far. Next check.
  8.   If error 2 found:
  9.     $errorMessage = 'Sorry, ...';
  10. If $errorMessage == '' then:
  11.   // No errors so far. Next check.
  12.   If error 3 found:
  13.     $errorMessage = 'Sorry, ...';
  14. If $errorMessage == '' then:
  15.   // No errors so far. Next check.
  16.   If error 4 found:
  17.     $errorMessage = 'Sorry, ...';
  18. If $errorMessage == '' then:
  19.   // No errors! Processing.
  20.   Process input.
  21.  
  22. Later...
  23. if ($errorMessage != '') {
  24.   print $errorMessage;
  25. else {
  26.   print output from processing;
  27. }

Nice!

How would that work for the sales tax thing? Remember, the user gives a state, like something.php?state=mi. If the state is OK, you get:

Output

Here's some code for it.

  1. <?php
  2. // Set up vars to track results.
  3. // Error message is a flag, too.
  4. $errorMessage = '';
  5. $taxRate = 0;
  6. $stateShortName = '';
  7. $stateLongName = '';
  8. // Is there input?
  9. if (!isset($_GET['state'])) {
  10.     $errorMessage = 'Sorry, you must give a state.';
  11. }
  12. if ($errorMessage == '') {
  13.     // OK so far.
  14.     $stateShortName = strtoupper(trim($_GET['state']));
  15.     // Is the state known?
  16.     if ($stateShortName != 'MI' && $stateShortName != 'IL') {
  17.         $errorMessage = "Sorry, '$stateShortName' is not a recognized state.";
  18.     }
  19. }
  20. if ($errorMessage == '') {
  21.     // Input checks out.
  22.     // Lookup.
  23.     if ($stateShortName == 'MI') {
  24.         $stateLongName = 'Michigan';
  25.         $taxRate = 0.06;
  26.     }
  27.     else {
  28.         $stateLongName = 'Illinois';
  29.         $taxRate = 0.0625;
  30.     }
  31. }
  32. ?><!doctype html>
  33. <html lang="en">
  34. ...

Let's break it down.

The first few lines set up variables:

  • $errorMessage = '';
  • $taxRate = 0;
  • $stateShortName = '';
  • $stateLongName = '';

You don't have to Dim variables in PHP, but I like to set them all up anyway, to help remind myself what the code is going to do.

OK, there are two types of errors:

  • The state is missing from the URL.
  • The state is there, but is unknown (only MI and IL are valid).

Let's deal with the first one.

  • if (!isset($_GET['state'])) {
  •     $errorMessage = 'Sorry, you must give a state.';
  • }

isset() is a PHP function. It's true if its parameter exists. So !isset($_GET['state']) will be true if something called state is not at the end of the URL (remember, ! means "not"). If there's no state, set $errorMessage.

That's the first validation rule. The second is the state has to be known. Let's add a rule for it, but we only want to check the rule, if there are no errors so far.

  1. if (!isset($_GET['state'])) {
  2.     $errorMessage = 'Sorry, you must give a state.';
  3. }
  4. if ($errorMessage == '') {
  5.     // OK so far.
  6.     $stateShortName = strtoupper(trim($_GET['state']));
  7.     // Is the state known?
  8.     if ($stateShortName != 'MI' && $stateShortName != 'IL') {
  9.         $errorMessage = "Sorry, '$stateShortName' is not a recognized state.";
  10.     }
  11. }

OK, the fourth line is:

  • if ($errorMessage == '') {

We only check the second validation rule (a known state) if the first one (is there a state?) passed. This is important. Check out this line, that's part of the state check.

  • $stateShortName = strtoupper(trim($_GET['state']));

$_GET['state'] will crash the program, if there is no state param at the end of the URL. So, don't run $_GET['state'], unless we know that the state param is there. That's what the first validation rule is about. If it passes, $errorMessage will be MT, so it's safe to $_GET['state'].

This code pattern is:

  • First validation test on variable $v.
  • Is everything OK?
  •   Do the next test on $v.
  • Is everything still OK?
  •   Do the next test on $v.
  • How about now?
  •   Do the next test on $v.
  • Still OK?
  •   Do the next test on $v.
Adela
Adela

Instead of...

  • if (!isset($_GET['state'])) {
  •     $errorMessage = 'Sorry, you must give a state.';
  • }
  • if ($errorMessage == '') {
  •     // OK so far.

... could it be...

  • if (!isset($_GET['state'])) {
  •     $errorMessage = 'Sorry, you must give a state.';
  • }
  • else {
  •     // OK so far.

Aye, it could be. Good thinking. There's no difference in this case. However, when validation gets more complex, with more rules and more fields, it's easier to keep track of things by testing whether $errorMessage is MT (empty).

Check out this again:

  • $stateShortName = strtoupper(trim($_GET['state']));

What's the deal with the strtoupper(trim(?

Ethan
Ethan

Same thing we did in VBA. trim() gets rid of spaces at the start and end of the variable, strtoupper() makes it uppercase, so we know what to test in the if:

  • if ($stateShortName == 'MI') {

Right! Nice work.

Adela
Adela

We could use lowercase, right?

  • $stateShortName = strtolower(trim($_GET['state']));
  • if ($stateShortName == 'mi') {

Aye, no problem.

After validation, there's processing.

  • if ($errorMessage == '') {
  •     // Input checks out.
  •     // Lookup.
  •     if ($stateShortName == 'MI') {
  •         $stateLongName = 'Michigan';
  •         $taxRate = 0.06;
  •     }
  •     else {
  •         $stateLongName = 'Illinois';
  •         $taxRate = 0.0625;
  •     }
  • }

We check the state only if there are no validation errors, that is, if $errorMessage is MT. That's why we don't need an explicit test for IL. If the state isn't MI, it has to be IL, since the validation code already established that the state is either MI or IL.

The next chunk

Here's the big picture:

All the variables

The top chunk fill some variables, so that bottom chunk knows what happened. Here's the code for the top chunk:

  1. <?php
  2. // Set up vars to track results.
  3. // Error message is a flag, too.
  4. $errorMessage = '';
  5. $taxRate = 0;
  6. $stateShortName = '';
  7. $stateLongName = '';
  8. // Is there input?
  9. if (!isset($_GET['state'])) {
  10.     $errorMessage = 'Sorry, you must give a state.';
  11. }
  12. if ($errorMessage == '') {
  13.     // OK so far.
  14.     $stateShortName = strtoupper(trim($_GET['state']));
  15.     // Is the state known?
  16.     if ($stateShortName != 'MI' && $stateShortName != 'IL') {
  17.         $errorMessage = "Sorry, '$stateShortName' is not a recognized state.";
  18.     }
  19. }
  20. if ($errorMessage == '') {
  21.     // Input checks out.
  22.     // Lookup.
  23.     if ($stateShortName == 'MI') {
  24.         $stateLongName = 'Michigan';
  25.         $taxRate = 0.06;
  26.     }
  27.     else {
  28.         $stateLongName = 'Illinois';
  29.         $taxRate = 0.0625;
  30.     }
  31. }
  32. ?><!doctype html>
  33. <html lang="en">
  34. ...

At the end of this, if all is OK, $errorMessage will be MT, and $stateLongName and $taxRate will have data, ready to output.

If there's a problem, $errorMessage will have an error message, and the other variables will be meaningless.

The bottom chunk will use the variables filled by the top chunk.

  • <h1>Sales tax rate</h1>
  • <?php
  • if ($errorMessage != '') {
  •     print "<p class='error-message'>$errorMessage</p>";
  • }
  • else {
  •     print "<p>The sales tax rate for $stateLongName is $taxRate.</p>";
  • }
  • ?>

The bottom chunk handles the output. Either an error message, or the results.

The top chunk prepared the output variables, the bottom chunk showed the output variables, along with the HTML around them.

Another example

The last program took string input, interpreting it as a state code, and did some validation. Let's write a program that takes a number, and does the same sort of thing.

This program simulates a microwave. You tell it how many seconds to run, and it will tell you how hot the food is. OK, I know it's silly, but it's easy to follow.

Try these links, with different values for heating time.

http://webappexamples.skilling.us/validation/basics/microwave-time/microwave-time.php

http://webappexamples.skilling.us/validation/basics/microwave-time/microwave-time.php?seconds=some

http://webappexamples.skilling.us/validation/basics/microwave-time/microwave-time.php?seconds=-33

http://webappexamples.skilling.us/validation/basics/microwave-time/microwave-time.php?seconds=10000

http://webappexamples.skilling.us/validation/basics/microwave-time/microwave-time.php?seconds=33

http://webappexamples.skilling.us/validation/basics/microwave-time/microwave-time.php?seconds=700

Let's use the same validation approach as before.

  • First validation test on variable $v.
  • Is everything OK?
  •   Do the next test on $v.
  • Is everything still OK?
  •   Do the next test on $v.
  • How about now?
  •   Do the next test on $v.
  • Still OK?
  •   Do the next test on $v.

We'll use the variable $errorMessage as a flag. So the code will be more like:

  • $errorMessage = '';
  • Get input.
  • If error 1 found:
  •   // Something is wrong, set error message.
  •   $errorMessage = 'Sorry, ...';
  • If $errorMessage == '' then:
  •   // No errors so far. Next check.
  •   If error 2 found:
  •     $errorMessage = 'Sorry, ...';
  • If $errorMessage == '' then:
  •   // No errors so far. Next check.
  •   If error 3 found:
  •     $errorMessage = 'Sorry, ...';
  • If $errorMessage == '' then:
  •   // No errors so far. Next check.
  •   If error 4 found:
  •     $errorMessage = 'Sorry, ...';
  • If $errorMessage == '' then:
  •   // No errors! Processing.
  •   Process input.
  •  
  • Later...
  • if ($errorMessage != '') {
  •   print $errorMessage;
  • else {
  •   print output from processing;
  • }

Last time, the tests were about a state code, like MI. This time, there'll be a number.

Here's the code:

  1. <?php
  2. // Set up vars to track results.
  3. // Error message is a flag, and a message container.
  4. $errorMessage = '';
  5. // User's input.
  6. $seconds = 0;
  7. // Output message. Only worked out if input is OK.
  8. $output = '';
  9. // Is there input?
  10. if (!isset($_GET['seconds'])) {
  11.     $errorMessage = 'Sorry, you must give the number of seconds.';
  12. }
  13. if ($errorMessage == '') {
  14.     // OK so far.
  15.     // Get the user's input.
  16.     $seconds = $_GET['seconds'];
  17.     // Is input a number?
  18.     if (! is_numeric($seconds)) {
  19.         $errorMessage = "Sorry, '$seconds' is not a number.";
  20.     }
  21. }
  22. if ($errorMessage == '') {
  23.     // Input checks out so far. Time for another test.
  24.     // Is the input negative?
  25.     if ($seconds < 0) {
  26.         $errorMessage = "Sorry, time cannot be a negative number.";
  27.     }
  28. }
  29. if ($errorMessage == '') {
  30.     // OK so far. Time for another test.
  31.     // Is the input too big?
  32.     if ($seconds > 1000) {
  33.         $errorMessage = "Sorry, time cannot be that large.";
  34.     }
  35. }
  36. // All input checks done.
  37. if ($errorMessage == '') {
  38.     // Input OK.
  39.     // Work out the output message.
  40.     if ($seconds < 60) {
  41.         $output = 'Warmed it up.';
  42.     }
  43.     else if ($seconds < 300) {
  44.         $output = 'Some like it hot.';
  45.     }
  46.     else if ($seconds < 600) {
  47.         $output = 'Warning! Hot lava!';
  48.     }
  49.     else {
  50.         $output = 'ARGH! Hull breach!';
  51.     }
  52. }
  53. ?><!doctype html>
  54. <html lang="en">
  55.     <head>
  56.         <title>Microwaving</title>
  57.         <meta charset="utf-8">
  58.         <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  59.         <link rel="stylesheet" href="styles.css">
  60.     </head>
  61.     <body>
  62.         <h1>Microwaving</h1>
  63.         <?php
  64.         if ($errorMessage != '') {
  65.             print "<p class='error-message'>$errorMessage</p>";
  66.         }
  67.         else {
  68.             print "<p>Starting microwave...</p>\n";
  69.             print "<p>PING</p>\n";
  70.             print "<p>$output</p>\n";
  71.         }
  72.         ?>
  73.     </body>
  74. </html>

Let's compare the code between the sales tax and microwave programs. They started like this:

  • <?php
  • // Set up vars to track results.
  • // Error message is a flag, too.
  • $errorMessage = '';
  • $taxRate = 0;
  • $stateShortName = '';
  • $stateLongName = '';
  •  
  •  
  • <?php
  • // Set up vars to track results.
  • // Error message is a flag, and a message container.
  • $errorMessage = '';
  • // User's input.
  • $seconds = 0;
  • // Output message. Only worked out if input is OK.
  • $output = '';

They both set up some variables at the start. Both had $errorMessage, then different variables, depending on the purpose.

Next, they both checked for input:

  • // Is there input?
  • if (!isset($_GET['state'])) {
  •     $errorMessage = 'Sorry, you must give a state.';
  • }
  •  
  •  
  • // Is there input?
  • if (!isset($_GET['seconds'])) {
  •     $errorMessage = 'Sorry, you must give the number of seconds.';
  • }

Then, they both grabbed the input into a variable, and ran another check - but only if there were no errors so far.

  • if ($errorMessage == '') {
  •     // OK so far.
  •     $stateShortName = strtoupper(trim($_GET['state']));
  •     // Is the state known?
  •     if ($stateShortName != 'MI' && $stateShortName != 'IL') {
  •         $errorMessage = "Sorry, '$stateShortName' is not a recognized state.";
  •     }
  • }
  •  
  •  
  • if ($errorMessage == '') {
  •     // OK so far.
  •     // Get the user's input.
  •     $seconds = $_GET['seconds'];
  •     // Is input a number?
  •     if (! is_numeric($seconds)) {
  •         $errorMessage = "Sorry, '$seconds' is not a number.";
  •     }
  • }

The two programs ran different checks, depending on what they needed to test.

The programs kept running checks, until they had checked everything they needed to.

Then, they did the processing, but only if there were no errors.

  • if ($errorMessage == '') {
  •     // Input checks out.
  •     // Lookup.
  •     if ($stateShortName == 'MI') {
  •         $stateLongName = 'Michigan';
  •         $taxRate = 0.06;
  •     }
  •     else {
  •         $stateLongName = 'Illinois';
  •         $taxRate = 0.0625;
  •     }
  • }
  •  
  • // All input checks done.
  • if ($errorMessage == '') {
  •     // Input OK.
  •     // Work out the output message.
  •     if ($seconds < 60) {
  •         $output = 'Warmed it up.';
  •     }
  •     else if ($seconds < 300) {
  •         $output = 'Some like it hot.';
  •     }
  •     else if ($seconds < 600) {
  •         $output = 'Warning! Hot lava!';
  •     }
  •     else {
  •         $output = 'ARGH! Hull breach!';
  •     }
  • }

Both programs filled variables for use in the output part of the program.

Here's what the output code looked like:

  • <h1>Sales tax rate</h1>
  • <?php
  • if ($errorMessage != '') {
  •     print "<p class='error-message'>$errorMessage</p>";
  • }
  • else {
  •     print "<p>The sales tax rate for $stateLongName is $taxRate.</p>";
  • }
  • ?>
  •  
  •  
  • <h1>Microwaving</h1>
  • <?php
  • if ($errorMessage != '') {
  •     print "<p class='error-message'>$errorMessage</p>";
  • }
  • else {
  •     print "<p>Starting microwave...</p>\n";
  •     print "<p>PING</p>\n";
  •     print "<p>$output</p>\n";
  • }
  • ?>

The programs output the results they worked out earlier, in the processing section.

Reflect

What similarites and differences are there between the two programs?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Ray
Ray

Well, they're not the same. The validation tests are different, the variables are different.

But... in a way, they are the same. They do things in the same way. When you know what to look for, you can see they're the same.

Right! We'd say they have the same structure. If you want to do validation, which comes up a lot in business programming, you could copy the structure, and change the variables.

I do this all the time in my own programming. Every experienced programmer does.

Note that I also screw up now and then. I'll copy code, and forget to change some of the variable names. Still, the structure works, so I'm ahead.

Adela
Adela

Something else I noticed. The output code is, like, really, really simple.

Good eye, Adela! Here's the output code again:

  • <h1>Sales tax rate</h1>
  • <?php
  • if ($errorMessage != '') {
  •     print "<p class='error-message'>$errorMessage</p>";
  • }
  • else {
  •     print "<p>The sales tax rate for $stateLongName is $taxRate.</p>";
  • }
  • ?>
  •  
  •  
  • <h1>Microwaving</h1>
  • <?php
  • if ($errorMessage != '') {
  •     print "<p class='error-message'>$errorMessage</p>";
  • }
  • else {
  •     print "<p>Starting microwave...</p>\n";
  •     print "<p>PING</p>\n";
  •     print "<p>$output</p>\n";
  • }
  • ?>

The logic is simple:

  • If there's an error message:
  •   Show it
  • Else:
  •   Show the output variables

The complexity is in the first part of the program, working out $errorMessage and the output variables.

Taking different pieces of logic, and working on them separately, is common. It makes your life easier.

  • When you're writing the validation and processing code, you don't need to think about the output code. Easier on your brain.
  • When you're writing the output code, you don't need to think about the validation and processing code. Easier on your brain.
Georgina
Georgina

Oo! Wouldn't that make it easier for two people to work on the program at the same time? You know, Adela could write the top bit, and Ethan the bottom.

They'd have to decide what variables link the two chunks of code. But then they could work at the same time, and the program would get written faster.

Wow! Good brain work! Aye, that's true. That's how teams work on software. They break the job into chunks, and decide how the chunks are going to talk to each other (with variables, and other things). Then they can work in parallel, that is, at the same time.

Let's make this validation approach into a pattern. We need a name for it. What should we call this pattern?

  • First validation test on variable $v.
  • Is everything OK?
  •   Do the next test on $v.
  • Is everything still OK?
  •   Do the next test on $v.
  • How about now?
  •   Do the next test on $v.
  • Still OK?
  •   Do the next test on $v.
Ethan
Ethan

How about a validation chain? You know, the different tests are all chained together.

OK, that'll work.

Pattern

Validation chain

Test some input, making an error message if needed. If that's OK, run another test. If it's still OK, do another.

Up next

Let's validate several fields at once.