Web design seattle - 146Part IPHP: The Basics$original = More than
146Part IPHP: The Basics$original = More than meets the eye ; $chopped = chop($original); $ltrimmed = ltrim($original); $trimmed = trim($original); print( The original is $original
); print( Its length is . strlen($original) .
); print( The chopped version is $chopped
); print( Its length is . strlen($chopped) .
); print( The ltrimmed version is $ltrimmed
); print( Its length is . strlen($ltrimmed) .
); print( The trimmed version is $ltrimmed
); print( Its length is . strlen($trimmed) .
); The result as viewed by a browser is: The original is More than meets the eye Its length is 28The chopped version is More than meets the eye Its length is 25The ltrimmed version is More than meets the eye Its length is 26The trimmed version is More than meets the eye Its length is 23The original string had three spaces at the end (subject to removal by chop()or trim()) and two at the beginning (removed by ltrim()and trim()). We were careful to describe ourresult as viewed by a browser because the multiple spaces have apparently been collapsed toone in the output, as browsers will do. If we viewed the HTML source produced by PHP origi- nally, we would still see sequences of two and three spaces. In addition to spaces, these functions remove whitespace like that denoted by the escapesequences n, r, t, and (end-of-line characters, tabs, and the null character used to terminate strings in C programs). You will hear the name chop()more frequently, but the identical function can also be calledwith the more logical name of rtrim(). Finally, notice that although chop()sounds extremelydestructive, it does not harm the $originalargument, which retains the same value. String replacementThe substring functions we ve seen so far are all about choosing a portion of the argumentrather than building a genuinely new string. Enter the functions str_replace()and substr_replace(). The str_replace()function enables you to replace all instances of a particular substringwith an alternate string. It takes three arguments: the string to be searched for, the string toreplace it with when it is found, and the string to perform the replacement on. For example: $first_edition = Burma is similar to Rhodesia in at least one way. ; $second_edition = str_replace( Rhodesia , Zimbabwe , $first_edition); $third_edition = str_replace( Burma , Myanmar , $second_edition); print($third_edition); #BREAK# 147Chapter 8Stringsgives us: Myanmar is similar to Zimbabwe in at least one way. This replacement will happen for all instances found of the search string. If our outdatedencyclopedia could be snarfed into a single PHP string, we could update it in one pass. One subtlety to be aware of: What happens when multiple instances of the search string over- lap? For example, with code like: $tricky_string = ABA is part of ABABA ; $maybe_tricked = str_replace( ABA , DEF , $tricky_string); print( Substitution result is $maybe_tricked
); the behavior we see is: Substitution result is DEF is part of DEFBA which is probably as reasonable as any other alternative. As we ve seen, str_replace()picks out portions to replace by matching to a target string; by contrast, substr_replace()chooses a portion to replace by its absolute position. Thefunction takes up to four arguments: the string to perform the replacement on, the string toreplace with, the starting position for the replacement, and (optionally) the length of the section to be replaced. For example: print(substr_replace( ABCDEFG , - , 2, 3)); gives us: AB-FGThe CDEportion of the string has been replaced with the single -. Notice that we are allowedto replace a substring with a string of a different length. If the length argument is omitted, it isassumed that you want to replace the entire portion of the string after the start position. The substr_replace()function also takes negative arguments for starting position andlength, which are treated exactly the same way as in the substr()function (described in theearlier section Substring selection ). It is important to remember with both str_replaceand substr_replacethat the original string remains unchanged by these operations. Finally, we have a couple more whimsical functions that produce new strings from old. Thestrrev()function simply returns a new string with the characters of its input in reverseorder. The str_repeat()function takes a string argument and an integer argument andreturns a string that is the appropriate number of copies of the string argument tackedtogether. For example: print(str_repeat( cheers , 3)); gives us: cheers cheers cheersfor the end of this section at long last. The substring search and replacement functions are summarized in Table 8-2.10 #BREAK# 148Part IPHP: The BasicsTable 8-2: Substring and String Replacement FunctionsFunctionBehaviorsubstr()Returns a subsequence of its initial string argument, as specified bythe second (position) argument and optional third (length) argument. The substring starts at the indicated position and continues for asmany characters as specified by the length argument or until the endof the string, if there is no length argument. A negative position argument means that the start character is locatedby counting backward from the end, whereas a negative lengthargument means that the end of the substring is found by countingback from the end, rather than forward from the start position. chop(), or rtrim()Returns its string argument with trailing (right-hand side) whitespaceremoved. Whitespace is , n, r, t, and . ltrim()Returns its string argument with leading (left-hand side) whitespaceremoved. Trim()Returns its string argument with both leading and trailing whitespaceremoved. Str_replace()Used to replace target substrings with another string. Takes three stringarguments: a substring to search for, a string to replace it with, and thecontaining string. Returns a copy of the containing string with allinstances of the first argument replaced by the second argument. Substr_replace()Puts a string argument in place of a position-specified substring. Takesup to four arguments: the string to operate on, the string to replacewith, the start position of the substring to replace, and the length ofthe string segment to be replaced. Returns a copy of the first argumentwith the replacement string put in place of the specified substring. If the length argument is omitted, the entire tail of the first stringargument is replaced. Negative position and length arguments aretreated as in substr(). Case functionsThese functions change lowercase to uppercase and vice versa. The first two (de)capitalizeentire strings, whereas the second two operate only on first letters of words. strtolower() The strtolower()function returns an all-lowercase string. It doesn t matter if the original isall uppercase or mixed. This fragment: returns the string they don t know they re shouting . #BREAK# 149Chapter 8StringsIf you have been faced with extensive form-validation needs before, you might already havenoticed that strtolower()is extremely handy for use with those that still think theire-mail addresses contain capital letters. Subsequent functions in this category will prove sim- ilarly useful. strtoupper() The strtoupper()function returns an all-uppercase string, regardless of whether the originalwas all lowercase or mixed: strtoupper($original) ); ?> ucfirst() The ucfirst()function capitalizes only the first letter of a string: ucwords() The ucwords()function capitalizes the first letter of each word in a string: Neither ucwords()nor ucfirst()converts anything into lowercase. Each makes only theappropriate leading letters into uppercase. If there are inappropriate capital letters in themiddle of words, they will not be corrected. Escaping functionsOne of the virtues of PHP is that it is willing to talk to almost anybody. In its role as a glue lan- guage, PHP talks to database servers, to LDAP servers, over sockets, and over the HTTP con- nection itself. Frequently, it accomplishes this communication by first constructing a messagestring (like a database query) and then shipping it off to the receiving program. Often, how- ever, the program attaches special meanings to certain characters, which therefore have tobe escaped,meaning that the receiving program is told to take them as a literal part of thestring rather than treating them specially. Many users deal with this issue by enabling magic-quotes, which ensures that quotes areescaped before strings are inserted into databases. If that s not feasible or desirable, thereare good old-fashioned strip-slashing and add-slashing by hand. The addslashes()functionescapes quotes, double quotes, backslashes, and NULLs with backslashes, because these arethe characters that typically need to be escaped for database queries. NoteTip10 #BREAK# 150Part IPHP: The Basics This will prevent the SQL statement from thinking it s finished right before the letter I. Whenyou pull the data back out, you ll need to use stripslashes()to get rid of the slashes. ; $qm_string = quotemeta($literal_string); echo $qm_string; will print: These characters ($, *) are very special to me\nFor escaping functions specific to HTML, see the Advanced String Functions section inChapter 22. Printing and outputThe workhorse constructs for printing and output are printand echo, which we cover indetail in Chapter 5. The standard way to print the value of variables to output is to includethem in a doubly quoted string (which will interpolate their values) and then give that stringto printor echo. If you need even more tightly formatted output, PHP also offers printf()and sprintf(), which are modeled on C functions of the same name. The two functions take identical argu- ments: a special format string (described later in this section) and then any number of otherarguments, which will be spliced into the right places in the format string to make the result. The only difference between printf()and sprintf()is that printf()sends the resultingstring directly to output, whereas sprintf()returns the result string as its value. To C programmers:This sprintf()function is slightly different from C s version in that youneed not supply an allocated string for sprintf()to write into PHP allocates the resultstring for you. The complicated bit about these functions is the format string. Every character that you putin the string will show up literally in the result, except the %character and characters thatimmediately follow it. The %character signals the beginning of a conversion specification, which indicates how to print one of the arguments that follow the format string. NoteCross- Reference10 #BREAK# 151Chapter 8StringsAfter the %, there are five elements that make up the conversion specification, some of whichare optional: padding, alignment, minimum width, precision, and type. .The single (optional) paddingcharacter is either a 0or a space (). This character isused to fill any space that would otherwise be unused but that you have insisted (withthe minimum width argument) be filled with something. If this padding character is notgiven, the default is to pad with spaces. .The optional alignmentcharacter (-) indicates whether the printed value should beleft- or right-justified. If present, the value will be left-justified; if absent, it will be right-justified. .An optional minimum widthnumber that indicates how many spaces this value shouldtake up, at a minimum. (If more spaces are needed to print the value, it will overflowbeyond its bounds.) .An optional precision specifier is written as a dot (.) followed by a number. It indicateshow many decimal points of precisiona double should print with. (This has no effect onprinting things other than doubles.) .A single character indicating how the typeof the value should be interpreted. The fcharacter indicates printing as a double, the scharacter indicates printing as a string, and then the rest of the possible characters (b, c, d, o, x, X) mean that the value shouldbe interpreted as an integer and printed in various formats. Those formats are bforbinary, cfor printing the character with the corresponding ASCII values, ofor octal, xfor hexadecimal (with lowercase letters) and X for hexadecimal with uppercase letters. Here s an example of printing the same double in several different ways:
gives us: 3.141590, 3.141590,3.141590000000000, 3.14The
construct is HTML that tells the browser to format the enclosed block liter- ally, without collapsing many spaces into one, and so on. Extended Example: An Exercise CalculatorIn this section, we continue the exercise calculator example from Chapter 5 by using a variety of string functions to process strings posted from a user form. In the previous exam- ple, we had just managed to pass off a string variable from an HTML form to the PHP pagedesigned to receive it. In this version, we actually do some analysis of the string we receive. (See the end of this section for reasons why this example will still need to be improved inlater chapters.) Listing 8-1 shows the HTML form used to prompt the user for an exercise to analyze. This is largely the same as the corresponding form in Chapter 7, with a different form-handling target. #BREAK# 152Part IPHP: The BasicsListing 8-1:The entry form
Workout calculator (passing a string)Enter an exercise, and we ll tell you how long you d have todo it |
Workout calculator handler, part 2The workout calculator says, $message |
); } } city_by_number(0, $major_city_info); city_by_number(1, $major_city_info); city_by_number(2, $major_city_info); If we have set $major_city, as in the previous block of code, the browser output we shouldexpect is: Caracas is in VenezuelaParis is in FranceTokyo is in JapanNow, this method of retrieval is fine when we know how the array is structured and we knowwhat all the keys are. But what if you would simply like to print everything that an array contains? Our favorite iteration method: foreachOur favorite construct for looping through an array is foreach. Although it is probably inher- ited from Perl s foreach, it has a somewhat odd syntax (which is not the same as Perl s oddsyntax). It comes in two flavors which one you decide to use will depend on whether youcare about the array s keys or just the values. #BREAK# 168Part IPHP: The Basicsforeach ($array_variable as $value_variable) { // .. do something with the value in $value_variable} // Note that this is an example template, not real PHP codeforeach ($array_variable as $key_var => $value_var) { // .. do something with $key_var and/or $value_var} Although in the preceding pseudocode we assume that the array of interest is in the variable$array_variable, you can have any expression that evaluates to an array in that position, for example: foreach (function_returning_array() as $value_variable) { // .. do something with the value in $value_variable} Like array()and list(), but unlike the genuine iteration functions in the rest of this sec- tion, foreachis a language construct, not a function. (See the earlier note about list() for an explanation of the difference.) As an example, let s write a function to print all the names from our sample array: function print_all_foreach ($city_array) { foreach ($city_array as $name_value) { print( $name_value
); } } print_all_foreach($major_city_info); print_all_foreach($major_city_info);// again, as an experimentAs output, we get all the names, in the order we stored them, twice over: CaracasVenezuelaParisFranceTokyoJapanCaracasVenezuelaParisFranceTokyoJapanWe printed the contents twice to show that calling the function is repeatable. Iterating with current() and next() We like foreach, but it is really only good for situations where you want to simply loopthrough an array s values. For more control, let s look at current()and next(). The current()function returns the stored value that the current pointer points to. (Referback to Figure 9-1 for a diagram of the array internals.) When an array is newly created withNote11 #BREAK# 169Chapter 9Arrays and Array Functionselements, the element pointed to will always be the first element. The next()function firstadvances that pointer and then returns the current value pointed to. If the next()functioniscalled when the current pointer is already pointing to the last stored value and, therefore, runs off the end of the array, the function returns a false value. As an example, we can print out an array s contents with the iteration functions current() and next(). (Notice that the final function call is repeated.) function print_all_next($city_array) { // warning–doesn t quite work. See the function each() $current_item = current($city_array); if ($current_item) print( $current_item
); elseprint( There s nothing to print ); while($current_item = next($city_array)) print( $current_item
); } print_all_next($major_city_info); print_all_next($major_city_info);// again, to see what happensThere is a gotcha lurking in the preceding code example, which doesn t bite us in this partic- ular example but makes this function untrustworthy as a general method for finding every- thing in an array. The problem is that we may have stored a false value in the array, which ourwhileloop won t be able to distinguish from the false value that next()returns when ithas run out of array elements. See the discussion of the each()function later in this chap- ter under Empty values and the each()function for a solution. When we execute this array-printing code, we get the following again: CaracasVenezuelaParisFranceTokyoJapanCaracasVenezuelaParisFranceTokyoJapanNow, how is it that we are seeing the same thing from the second call to print_all_next()? How did the current pointer get back to the beginning to start all over again the second time? The answer lies in the fact that PHP function calls are call-by-value, meaning that they copytheir arguments rather than operating directly on them. Both of the function calls, then, aregetting a fresh copy of their array argument, which has never itself been disturbed by a call to next(). For more on under what circumstances functions copy their arguments rather than operatingon them directly, see Chapter 6. Cross- ReferenceCaution11 #BREAK# 170Part IPHP: The BasicsWe can test this explanation by passing the arrays by reference rather than by value. If wedefine the same function but call it with ampersands (&) like this: print_all_next(&$major_city_info); print_all_next(&$major_city_info);// againWe get the following printing behavior: CaracasVenezuelaParisFranceTokyoJapanThere s nothing to printThe trick we used to test the array behavior (passing a variable reference to a function) hasbeen deprecated, so you may get a warning when running this code, in addition to seeingthe results printed above. The reason is that this time the current pointer of the global version of the array was movedby the first function call. Most of the iteration functions have both a returned value and a side effect. In the case of thefunctions next(), prev(), reset(), and end(), the side effect is to change the positionof the internal pointer, and what is returned is the value from the key/value pair pointed toafterthe pointer s position is changed. Starting over with reset() In the preceding section, we wrote a function intended to print out all the values in an array, and we saw how it could fail if the array s internal pointer did not start off at the beginning ofthe list of key/value pairs. The reset()function gives us a way to rewind that pointer tothe beginning it sets the pointer to the first key/value pair and then returns the storedvalue. We can use it to make our printing function more robust by replacing the call to current()with a call to reset(). function print_all_array_reset($city_array) { // warning–still not reliable. See the function each() $current_item = reset($city_array); //rewind, return valueif ($current_item) print( $current_item
); elseprint( There s nothing to print ); while($current_item = next($city_array)) print( $current_item
); } This function is somewhat more predictable in that it will always start with the first element, regardless of the pointer s location in the array it is handed. (Whether this is a good ideadepends, of course, on what the function is used for and whether its arguments are passed by value or by reference.) NoteNote11 #BREAK# 171Chapter 9Arrays and Array FunctionsPerhaps confusingly, we use our call to reset()in the preceding example both for its sideeffect (rewinding the pointer) and for its return value (the first value stored). Alternatively, we could replace the first real line of the function body with these two lines: reset($city_array); // rewind to the first element$current_item = current($city_array); // the first valueReverse order with end() and prev() We have seen the functions next(), which moves the current pointer ahead by one, andreset(), which rewinds the pointer to the beginning. Analogously, there are also the func- tions prev(), which moves the pointer back by one, and end(), which jumps the pointer to the last entry in the list. We can use these, for example, to print our array entries inreverse order. function print_all_array_backwards($city_array) { // warning–still not reliable. See the function each() $current_item = end($city_array); //fast-forward to lastif ($current_item) print( $current_item
); elseprint( There s nothing to print ); while($current_item = prev($city_array)) print( $current_item
); } print_all_array_backwards($major_city_info); If we call this on the same $major_city_infodata as in previous examples, we get the sameprintout in reverse order: JapanTokyoFranceParisVenezuelaCaracasExtracting keys with key() So far, we have printed only the values stored in arrays, even though we are storing keys aswell. The keys are also retrievable from the internal linked list of an array by using the key() function this acts just like current()except that it returns the key of a key/value pair, rather than the value. (Refer to Figure 9-1.) Using the key()function, we can modify one ofour earlier printing functions to print keys as well as values. function print_keys_and_values($city_array) { // warning–See the discussion of each() belowreset($city_array); $current_value = current($city_array); $current_key = key($city_array); if ($current_value) print( Key: $current_key; Value: $current_value
); #BREAK# 172Part IPHP: The Basicselseprint( There s nothing to print ); while($current_value = next($city_array)) { $current_key = key($city_array); print( Key: $current_key; Value: $current_value
); } } print_keys_and_values($major_city_info); With the same data as before, this gives us the browser output: Key: 0; Value: CaracasKey: Caracas; Value: VenezuelaKey: 1; Value: ParisKey: Paris; Value: FranceKey: 2; Value: TokyoKey: Tokyo; Value: JapanEmpty values and the each() functionWe have written several functions that print the contents of arrays by iterating through themand, as we have pointed out, all but the foreachversion have the same weakness. Each oneof them tests for completion by seeing whether next()returns a false value. This will reliablyhappen when the array runs out of values, but it will also happen if and when we encounter afalse value that we have actually stored. False values include the empty string ( ), the num- ber 0, and the Boolean value FALSE, any or all of which we might reasonably store as a datavalue for some task or other. To the rescue comes each(), which is somewhat similar to next()but has the virtue ofreturning false only after it has run out of array to traverse. Oddly enough, if it has not runout, each()returns an array itself, which holds both keys and values for the key/value pair it is pointing at. This characteristic makes each()confusing to talk about because you needto keep two arrays straight: the array that you are traversing and the array that each() returns every time that it is called. The array that each()returnshas the following fourkey/value pairs: .Key: 0; Value: current-key .Key: 1; Value: current-value .Key: key ; Value: current-key .Key: value ; Value: current-valueThe current-keyand current-valueare the key and value from the array being traversed. Inother words, the returned array packages up the current key/value pair from the traversedarray and offers both numerical and string indices to specify whether you are interested inthe key or the value. In addition to having a different type of return value, each()differs from next()in thateach()returns the value that was pointed to beforemoving the current pointer ahead, whereas next()returns the value afterthe pointer is moved. This means if you start with acurrent pointer pointing to the first element of an array, successive calls to each()will covereach array cell, whereas successive calls to next()will skip the first value. Note11 #BREAK# 173Chapter 9Arrays and Array FunctionsWe can use each()to write a more robust version of a function to print all keys and values inan array: function print_keys_and_values_each($city_array) { // reliably prints everything in arrayreset($city_array); while ($array_cell = each($city_array)) { $current_value = $array_cell[ value ]; $current_key = $array_cell[ key ]; print( Key: $current_key; Value: $current_value
); } } print_keys_and_values_each($major_city_info); Applying this function to our standard sample array gives the following browser output: Key: 0; Value: CaracasKey: Caracas; Value: VenezuelaKey: 1; Value: ParisKey: Paris; Value: FranceKey: 2; Value: TokyoKey: Tokyo; Value: JapanThis is exactly the same as was produced by our earlier function print_keys_and_values(). The difference is that our new function will not stop prematurely if one of the values is false orempty. Walking with array_walk() Our last iteration function lets you pass an arbitrary function of your own design over anarray, doing whatever your function pleases with each key/value pair. The array_walk() function takes two arguments: an array to be traversed and the name of a function to apply toeach key/value pair. (It also takes an optional third argument, discussed later in this section.) The function that is passed in to array_walk()should take two (or three) arguments. Thefirst argument will be the value of the array cell that is visited, and the second argument willbe the key of that cell. For example, here is a function that prints a descriptive statementabout the string length of an array value: function print_value_length($array_value, $array_key_ignored) { $the_length = strlen($array_value); print( The length of $array_value is $the_length
); } (Notice that this function intentionally does nothing with the second argument.) Now let spass this function over our standard sample array using array_walk(): array_walk($major_city_info, print_value_length ); which gives the browser output: The length of Caracas is 7The length of Venezuela is 9The length of Paris is 511 #BREAK# 174Part IPHP: The BasicsThe length of France is 6The length of Tokyo is 5The length of Japan is 5The final flexibility that array_walk()offers is accepting an optional third argument that, ifpresent, will be passed on, in turn, as a third argument to the function that is applied. Thisargument will be the same throughout the array s traversal, but it offers an extra source ofruntime control for the passed function s behavior. You should not alter an array while you are iterating through the array using array_walk(). There is no guarantee how array_walk()will behave if you do this. Table 9-2 shows a summary of the behavior of the array iteration functions that we covered inthis section. Notice that foreachand listare not included; they are not functions. Table 9-2: Functions for Iterating over ArraysFunctionArgumentsSide EffectReturn Valuecurrent()One array None.The value from the key/value argumentpair currently pointed to by theinternal current pointer (orfalse if no such value). next()One array Advances the pointer The value pointed to after the argumentby one. If already at the pointer has been advanced (or last element, it will move false if no such value). the pointer past the end, and subsequent calls to current()will return false. prev()One array Moves the pointer back The value pointed to after the argumentby one. If already at the pointer has been moved back first element, will move (or false if no such value). the pointer before the beginning. reset()One array Moves the pointer back to The first value stored in the argumentpoint to the first key/value array, or false for an empty pair, or before the array. beginning if the array is empty. end() One array Moves the pointer ahead The last value that is currently argumentto the last key/value pair.in the list of key/value pairs. pos()One array None. (This function is an The value of the key/value pair argumentalias for current().)that is currently pointed to. Caution11 #BREAK# 175Chapter 9Arrays and Array FunctionsFunctionArgumentsSide EffectReturn Valueeach()One array Moves the pointer ahead An array that packages the keys argumentto the next key/value pair.and values of the key/valuepair that was current beforethe pointer was moved (orfalse if no such pair). Thereturned array stores the keyand value under its own keys 0and 1, respectively, and alsounder its own keys key and value . array_walk()1) An array This function invokes the (Returns 1.) argument, function named by its 2) the name second argument on each of a two- key/value pair. Side (or three-) effects depend on the argument side effects of the function to passed function. call on each key/value, and 3) an optiona.l third argument. Extended Example: An Exercise CalculatorNow we ll continue our exercise calculator example that we started in Chapters 7 and 8 andmake further improvements using PHP arrays. When we left this example in Chapter 8, we were allowing the user to type the name of anexercise into a Web form, and we were hoping to match the submitted string with an exerciseknown to the receiving script. Instead, let s take our advice from late in Chapter 8 and con- strain inputs from the user to a set we know we can recognize on the receiving end. Listing 9-1 shows an HTML form that presents a set of exercises that the user can choosefrom. This uses a radio-button input, so that the user can choose only one exercise to submit. Listing 9-1:Entry form with radio buttons
Workout calculator (radio buttons with arrays)Select one of the following exercises, and we ll tell you how long |
Workout calculator handler (radio buttons with arrays)The workout calculator says, $message #BREAK# 179Chapter 9Arrays and Array Functions |
Workout calculator (multiple checkboxes with arrays)Select one or more of the following exercises, and we ll tellyou |
It would take $hours of $exercise_name . to burn one pound of fat. ; } } Continued11 #BREAK# 182Part IPHP: The BasicsListing 9-4(continued) } else { // Hmmm, they didn t pick one or something strange happened$message = Ummm, did you pick an exercise? ; } //If you don t have this test, an empty form will cause an // error. //Usually you d test an array for a count of 0, but here //there is 1 automatic POST array element — $_POST[ submit ]. // Now lay out the page// ——————– $page_str = <<< EOPAGE
Workout calculator handler (multiple checkboxes with arrays)The workout calculator says: $message |
Workout calculator (multidimensional arrays)Select one or more of the following exercises, and we ll tellyou |
; } else { // Add heading$heading = $exercise_types[$key_1]; $message .= n
$heading ; foreach ($val as $key_2 => $val_2) { if ($val_2 == 1) { $exercise_name = $exercise_array[$key_1][$key_2]; $hours = $duration_array[$key_1][$key_2]; $message .=
nIt would take $hours of . $exercise_name to burn one pound of fat. ; } } } } } else { // Hmmm, they didn t pick one or something wack happened$message = Ummm, did you pick an exercise? ; } // Now lay out the page// ——————– $page_str = <<< EOPAGE
Continued11 #BREAK# 188Part IPHP: The BasicsListing 9-6(continued) Workout calculator handler (multidimensional arrays)The workout calculator says: $message |
); $count = 0; $result = ++$count; print( Pre ++: count is $count, result is $result
); $count = 0; $result = $count–; print( Post –: count is $count, result is $result
); $count = 0; $result = –$count; print( Pre –: count is $count, result is $result
); #BREAK# 194Part IPHP: The Basicswhich gives the browser output: Post ++: count is 1, result is 0Pre ++: count is 1, result is 1Post –: count is -1, result is 0Pre –: count is -1, result is 1In this example, the statement $result=$count++;is exactly equivalent to$result = $count; $count = $count + 1; while $result=++$count;is equivalent to$count = $count + 1; $result = $count; Assignment operatorsIncrementing operators like ++save keystrokes when adding one to a variable, but they don thelp when adding another number or performing another kind of arithmetic. Luckily, all fivearithmetic operators have corresponding assignment operators (+=, -=, *=, /=, and %=) thatassign to a variable the result of an arithmetic operation on that variable in one fell swoop. The statement: $count = $count * 3; can be shortened to: $count *= 3; and the statement: $count = $count + 17; becomes: $count += 17; Comparison operatorsPHP includes the standard arithmetic comparison operators, which take simple values (num- bers or strings) as arguments and evaluate to either TRUEor FALSE: For examples of using the comparison operators and also some gotcha issues with comparingdoubles and strings, see Chapter 6. .The <(less than) operator is true if its left-hand argument is strictly less than its right- hand argument but false otherwise. .The >(greater than) operator is true if its left-hand argument is strictly greater than itsright-hand argument but false otherwise. .The <=(less than or equal) operator is true if its left-hand argument is less than orequal to its right-hand argument but false otherwise. .The >=(greater than or equal) operator is true if its left-hand argument is greater thanor equal to its right-hand argument but false otherwise. Cross- Reference12 #BREAK# 195Chapter 10Numbers .The ==(equal to) operator is true if its arguments are exactly equal but false otherwise. .The !=(not equal) operator is false if its arguments are exactly equal and true otherwise. .The ===operator (identical to) is true if its two arguments are exactly equal and of thesame type. The identical tooperator (===)can, at times, be a necessary antidote to PHP s auto- matic type conversions. None of the following expressions will have a truevalue: 2 === 2.02 === 2 2.0 === 2.00 === FALSEThis behavior can be invaluable, for example, if you have a function that returns a stringwhen it succeeds (which might be the empty string) and a FALSEvalue when it fails. Testingthe truth of the return value would confuse FALSEwith the empty string, whereas the iden- tical operator can distinguish them. Precedence and parenthesesOperator precedencerules govern the relative stickiness of operators, deciding which opera- tors in an expression get first claim on the arguments that surround them. You can find acomplete table of all operator precedences in the manual at www.php.net, but the importantprecedence rules for arithmetic are: .Arithmetic operators have higher precedence (that is, bind more tightly) than compari- son operators. .Comparison operators have higher precedence than assignment operators. .The *, /, and %arithmetic operators have the same precedence. .The +and arithmetic operators have the same precedence. .The *, /, and %operators have higher precedence than +and . .When arithmetic operators are of the same precedence, associativity is left-to-right(that is, a number will associate with an operator to its left in preference to the opera- tor on its right). If you find the precedence rules difficult to remember, the next person who reads your codemay have the same problem, so feel free to parenthesize when in doubt. For example, can youeasily figure out the value of this expression? 1 + 2 * 3 - 4 - 5 / 4 % 3As it turns out, the value is 2, as we can see more easily when we add parentheses that arenot, strictly speaking, necessary: ((1 + (2 * 3)) 4) ((5 / 4) % 3) Tip12 #BREAK# 196Part IPHP: The BasicsSimple Mathematical FunctionsThe next step up in sophistication from the arithmetic operators consists of miscellaneous func- tions that perform tasks like converting between the two numerical types (which we discussedin Chapter 5) and finding the minimum and maximum of a set of numbers (see Table 10-2). Table 10-2: Simple Math FunctionsFunctionBehaviorfloor()Takes a single argument (typically a double) and returns the largest integerthat is less than or equal to that argument. ceil()Short for ceiling takes a single argument (typically a double) and returns thesmallest integer that is greater than or equal to that argument. round()Takes a single argument (typically a double) and returns the nearest integer. Ifthe fractional part is exactly 0.5, it returns the nearest even number. abs()Short for absolute value if the single numerical argument is negative, thecorresponding positive number is returned; if the argument is positive, theargument itself is returned. min()Takes any number of numerical arguments (but at least one) and returns thesmallest of the arguments. max()Takes any number of numerical arguments (but at least one) and returns thelargest of the arguments. For example, the result of the following expression: min(3, abs(-3), max(round(2.7), ceil(2.3), floor(3.9))) is 3, because the value of every function call is also 3. RandomnessPHP s functions for generating pseudo-random numbers are summarized in Table 10-3. (If youare new to random number generation and are wondering what the pseudois all about, pleasesee the accompanying sidebar.) There are two random number generators (invoked with rand()and mt_rand(), respectively), each with the same three associated functions: a seeding function, the random-number functionitself, and a function that retrieves the largest integer that might be returned by the generator. The particular pseudo-random function that is used by rand()may depend on the particularlibraries that PHP was compiled with. By contrast, the mt_rand()generator always uses the12 #BREAK# 197Chapter 10Numberssame random function (the Mersenne Twister), and the author of mt_rand() s online documen- tation argues that it is also faster and more random (in a cryptographic sense) than rand(). We have no reason to believe that this is not correct, so we prefer mt_rand()to rand(). Table 10-3: Random Number FunctionsFunctionBehaviorsrand()Takes a single positive integer argument and seeds the random numbergenerator with it. rand()If called with no arguments, returns a random number between 0 andRAND_MAX(which can be retrieved with the function getrandmax()). The function can also be called with two integer arguments to restrict therange of the number returned the first argument is the minimum andthe second is the maximum (inclusive). getrandmax()Returns the largest number that may be returned by rand(). This islimited to 32768 on Windows platforms. mt_srand()Like srand(), except that it seeds the better random number generator. mt_rand()Like rand(), except that it uses the better random number generator. mt_getrandmax()Returns the largest number that may be returned by mt_rand(). On some PHP versions and some platforms, you can apparently get seemingly random num- bers from rand()and mt_rand()without seeding first this should not be relied upon, however, both for reasons of portability and because the unseeded behavior is not guaranteed. Seeding the generatorThe typical way to seed either of the PHP random-number generators (using mt_srand()orsrand()) looks like this: mt_srand((double)microtime()*1000000); This sets the seed of the generator to be the number of microseconds that have elapsed sincethe last whole second. (Yes, the typecast to doubleis necessary here, because microtime() returns a string, which would treated as an integer in the multiplication but for the cast.) Please use this seeding statement even if you don t understand it just place it in any PHPpage, once only, before you use the corresponding mt_rand()or rand()functions, and it willensure that you have a varying starting point and therefore random sequences that are differ- ent every time. This particular seeding technique has been thought through by people whounderstand the ins and outs of pseudo-random number generation and is probably betterthan any attempt an individual programmer might make to try something trickier. Note12 #BREAK# 198Part IPHP: The BasicsHere s some representative code that uses the pseudo-random functions: print( Seeding the generator
); mt_srand((double)microtime() * 1000000); print( With no arguments: . mt_rand() .
); print( With no arguments: . mt_rand() .
); print( With no arguments: . mt_rand() .
); print( With two arguments: . mt_rand(27, 31) .
); print( With two arguments: . mt_rand(27, 31) .
); print( With two arguments: . mt_rand(27, 31) .
); with the browser output: Seeding the generatorWith no arguments: 992873415With no arguments: 656237128With no arguments: 1239053221With two arguments: 28With two arguments: 31With two arguments: 29Pseudo-random Number GeneratorsAs with all programming languages, the random number functions offered by PHP are reallyimplemented by pseudo-random number generators. This is because conventional computerarchitectures are deterministic machines that will always produce the same results given thesame starting conditions and inputs and have no good source of randomness. (Here we re talk- ing about the ideal computer as it is supposed to work, not the actual physically embodied, power-interruptible, cosmic-ray flippable, seemingly very random machines we all struggle withdaily!) You could imagine connecting a conventional computer to a source of random bits suchas a mechanical coin-flip reader, or a device that observed quantum-level events, but suchperipherals don t seem to be widely available at this time. So we must make do with pseudo-random generators, which produce a deterministic sequenceof numbers that looks random enough for most purposes. They typically work by running theirinitial input number (the seed) through a particular mathematical function to produce the firstnumber in the sequence; each subsequent number in the sequence is the result of applying thatsame function to the previous number in the sequence. The sequence will repeat at some point(once it generates a particular number for the second time, it is doomed to follow the samesequence as it did the first time around), but a good iteration function will generate a very longsequence of numbers that have little apparent pattern before the loop occurs. How do you choose a seed to start off with? Because of the generator s determinism, if you hard- code a PHP page to have a particular seed, that page will always see the same sequence fromthe generator. (Although this is not usually what you want, it can be an invaluable trick when youare trying to debug behavior that depends on the particular numbers that are generated.) Thetypical seeding technique is to use a fast-changing digit from the system clock as the initialseed although those numbers are not exactly random, they are likely to vary quickly enoughthat subsequent page executions will start with a different seed every time. #BREAK# 199Chapter 10NumbersAlthough the random-number functions only return integers, it is easy to convert a randominteger in a given range to a corresponding floating-point number (say, one between 0.0 and1.0 inclusive) with an expression like rand()/getrandmax(). You can then scale andshift the range as desired (to, say, a number between 100.0 and 120.0) with an expressionlike 100.0+20.0*(rand()/getrandmax()). Obviously, if you run exactly this code, you will get numbers that differ from those in the output shown here, because the point of seeding the generator this way is to ensure that different executions produce different sequences of numbers. In some old versions of PHP3, the rand()function buggily ignored its arguments, returningnumbers between 0and getrandmax()regardless of restrictions. We have also heardsome reports of that behavior under more recent Windows implementations. If you suspectthat you are suffering from such a bug, you can define your own restricted version of rand() like so: function my_rand ($min, $max) { return(rand() % (($max - $min) + 1) + $min); } Unlike rand(), this version requires the minand maxarguments. Example: Making a random selectionNow let s use the random functions for something useful (or, at least, something that could beused for something useful). The following two functions let you construct a random string ofletters, which could, in turn, be used as a random login or password string: function random_char($string) { $length = strlen($string); $position = mt_rand(0, $length - 1); return($string[$position]); } function random_string ($charset_string, $length) { $return_string = ; // the empty stringfor ($x = 0; $x < $length; $x++) $return_string .= random_char($charset_string); return($return_string); } The random_char()function chooses a character (or, actually, a substring of length 1) fromits input string. It does this by restricting the mt_rand()function to positions within thelength of the string (with chars numbered starting at zero), and then returning the characterthat is at that random position. The random_string()function calls random_char()a number of times on a string representing the universe of characters to be chosen from andconcatenates a string of the desired length. CautionTip12 #BREAK# 200Part IPHP: The BasicsNow, to demonstrate this code, we first seed the generator, define our universe of allowablecharacters, and then call random_string()a few times in a row: mt_srand((double)microtime() * 1000000); $charset = abcdefghijklmnopqrstuvwxyz ; $random_string = random_string($charset, 8); print( random_string: $random_string
); $random_string = random_string($charset,
); $random_string = random_string($charset,
); with the result: random_string: eisexkiorandom_string: mkvflwfyrandom_string: gpulbwthIn this example, we seed the generator only once, and we draw that seed value from the sys- tem clock. Notice what happens if we make the mistake of repeatedly seeding the generatorwith the same value: mt_srand(43); $random_string = random_string($charset,
); mt_srand(43); $random_string = random_string($charset,
); mt_srand(43); $random_string = random_string($charset,
); Because the sequence that is generated depends deterministically on the seed, we get thesame behavior each time: random_string: qgkxvurwrandom_string: qgkxvurwrandom_string: qgkxvurwIn these examples, we chose to draw random characters from strings, but this kind of selec- tion process is generalizable to draw items from arrays or to be used in any situation thatrequires choosing random members from a set. All you need is the universe of items, a way toput them in numerical order, and a way to retrieve them by order number, and you can thenuse the rand()or mt_rand()function to choose a random order number for the retrieval. Extended Example: An Exercise CalculatorNow let s return to the exercise-calculator example that we ve been developing sinceChapter7. In addition to mixing in a little bit of arithmetic calculation, we ll reorganize thecode a bit. One problem with the code as we left it was that we had our data in two different code filesand in more than one array. Changes to the data require updating more than one file and takesome care to make sure that everything stays in sync. #BREAK# 201Chapter 10NumbersWe could always keep this data in a text file or in a database. For this chapter, however, let sjust make a single PHP code file where we define a single array with everything we need: types of exercises, names of exercises, and the calories per minute that each exercise con- sumes, assuming a person of average weight. Such an array is shown in Listing 10-1; we ll call this file exercise_include.php. Listing 10-1:exercise_include.php array( biking/cycling => 9, rowing => 8, running => 14, stairclimber => 6, walking => 5), Sports => array( basketball => 12, ice hockey => 9, soccer/football => 11, table tennis => 7), Strength training => array( calisthenics => 11, weightlifting (light) => 9, weightlifting (strenuous) => 13), Stretching/flexibility => array( pilates => 5, tai chi => 6, yoga => 5) ); ?> Although we ll stick to having separate form submission and form handler pages, let s makethe form submission page a PHP file too, rather than using straight HTML. This will let us generate the form elements from the data we defined in exercise_include.php. Listing 10-2:Form submission code for fitness calculator
Workout calculator (math)For one or more of the following exercises, enter |