RU beehive logo ITEC dept promo banner
ITEC 325
2015spring
ibarland

homelectsexamshws
D2Lbreeze (snow day)

lect12-form-handle
processing input; array functions

We've been talking about input forms (html elements), and then php scripts to process a submitted form:

testing a form-handler

Our functions have test cases, and this helps gives us confidence before we ever deploy to the web. But what about form-handlers? The result from form-handler is a long page that includes various bits from the form. It's too tedious to make this a check/expect sort of test, since the details of the html part of the output aren't relevant (and might change). Moreover, generating the page requires the POST data, that were entered by hand back in the form. But we would like to be able to check that the form-handler without going through the web, and also eyeball-check the result on certain inputs w/o having to continually re-type the inputs and call up the form.

Solution: Make a php program which simply initializes $_POST, and then require's the form-handler. Recall the sample form from last lecture (and recall what happens when it submits). Then, inspect:

I'll call these "demos", because they're not full tests: they're not automated. Note that we can run these locally, or over the web. (The former is useful if the latter isn't showing up as expected.)

Sanitizing input

When creating a page which includes something typed in by the user (from a previous text-input), we must be careful! What could the user have typed, that would goof up our web page?

Quick q: suppose a user types:

  hi
<3
in a textarea whose name is msg. What is


We have seen arrays, and mentioned that if they have all-numeric indices (keys) then we can process them with a for loop or a while loop, using the same syntax that Java and Javascript happen to use.

Then we saw that if an array has keys which aren't all numeric, we can use a foreach loop to process them:

  $myData = array( 'hi' => 'hallo', 'good day' => 'guten Tag', 'see you later' => 'auf wiedersehen' );

  foreach ($mydata as $german) {
    echo $german, "\n";
    }

  foreach ($mydata as $english => $german) {
    echo "You say '$english', I say '$german'.\n";
    }
The foreach loop is of course one way to process each element of the $_POST array (if you didn't want code specific/different for each input form).


directory-processing

Look at the documentation for scandir.
Since it returns an array of filenames, it's a natural match to use with other functions that want an array of strings: For example, echo htmlLines( scandir( '/ibarland/Tmp' ) );


array_map

Suppose we wanted an English list of hyperlinks, separated by commas, with the word "and" before the last item. This decomposes into two orthogonal parts:

And you just wrote a function for making an English list, and you called that. The array you pass in must be an array of URLs.

To create the array, hopefully you also used your function hyperlink, written from hw02. (If you wrote the same long HTML a tag over and over, that's a sign that a function would be better.) So you might have a loop:

  $URLsAsText = array( "http://d20srd.org", "http://www.radford.edu", "http://google.com" );

  $URLsAsHTML = array();
  foreach ($URLsAsText AS $url) {
     $URLsAsHTML[] = hyperlink($url);
     }

  echo "It should appeal to users of ", commaSeparatedList( $URLsAsHTML ), "."
  

Any other repeated stuff? Hmm, the “http:” prefix was kinda annoying, but writing a loop for that seems definite overkill.
(Design Question: Should hyperlink be prepending a http:? How does this limit what it can do? Does it violate the principle of least surprise?)

It's kinda annoying to keep writing loops that make a new array of updated values. Most of the loop is very rote — the only part that differs is the particular rule to transform the individual element to the new element. (In the example above, the answer is “the function hyperlink”.)

There is a handy function, array_map: You pass it an array of data, and you pass it the rule (function) on how to transform each individual datum, and it gives you back the entire transformed array. So our loop above gets turned in to:

  $URLsAsText = array( "http://d20srd.org", "http://www.radford.edu", "http://google.com" );
  $URLsAsHTML = array_map( $URLsAsText, "hyperlink" );
  echo "It should appeal to users of ", commaSeparatedList( $URLsAsHTML ), ".";
or we could even get rid of the intermediate variable, if we don't want to save the result1:
  $URLsAsText = array( "http://d20srd.org", "http://www.radford.edu", "http://google.com" );
  echo "It should appeal to users of ", 
       commaSeparatedList( array_map( $URLsAsText, "hyperlink" ) ),
       ".";

Finally, note that we can also handle the “prepend “http://” to each item” issue. We could make a separate function and pass that to array_map, or we could use an anonymous function:

  $URLsAsText = array_map( array( "d20srd.org", "www.radford.edu", "google.com" ),
                           function ($domain) { return "http://" . $domain; }2 );
  


1 Heck, if you don't even want to name the original array, you could inline that. This is arguably in-lining too much, but that can be an issue of taste (and requires taking care with indentation):

  echo "It should appeal to users of ", 
       commaSeparatedList( array_map( array( "http://d20srd.org",
                                             "http://www.radford.edu",
                                             "http://google.com" ),
                                      "hyperlink" ) ),
       ".";
     

2 This is a function that we declare in the middle of the line; note it doesn't even have a name. We don't call this function ourselves: we are giving the function to array_map, and they'll use the function as they see fit — in this case, calling the function on every element of the array we're also handing them. In truth, the implementation of array_map is potentially very simple:

function arraymap( $arr, $func ) {
  $result = array();
  foreach ($arr AS $k => $v) {
    $result[$k] = $func($v);    // call the function we were handed, and store the answer in our array $result.
    }
  return $result;
  }
.      

homelectsexamshws
D2Lbreeze (snow day)


©2015, Ian Barland, Radford University
Last modified 2015.Feb.21 (Sat)
Please mail any suggestions
(incl. typos, broken links)
to ibarlandradford.edu
Rendered by Racket.