PHP Bible Chapter 6: Control and Functions _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 1 Wiley and the book authors, 2002 Summary Creating and combining logical tests Branching with if and switch Looping with while and for Aborting page execution with exit and die Using built-in PHP functions Exploring the online function documentation Defining your own functions Advanced tricks: variable arguments, call-by-reference, variable functions _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 2 Wiley and the book authors, 2002 Intro to control In order to have a program which responds to something (time of day, user input, or the contents of a database, etc.), programming languages require a control structure which will allow branching and looping within an application Branches are forks in the execution of your code where you can go left or right depending on the circumstances at the execution of the branch Loops allow a statement or a block of statements to execute multiple times until a terminating condition is met PHP's control structure is practically equivalent to C's structure (and consequently very similar to Perl, Java, JavaScript, etc.) _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 3 Wiley and the book authors, 2002 Boolean expressions Most control structures have 2 distinct parts, the test (which determines which part of the rest of the structure executes) and the dependent code Logical operators combine other logical (e.g. boolean) values to produce new boolean values. Standard logical operations (and, or, not, and exclusive-or) are supported by PHP and: true if and only if both of its arguments are true or: true if either (or both) of its arguments are true !: Not operator - true if its single operand (to its immediate right) is false, and false if its operand is true xor: true if either (but not both) of its arguments are true &&: same as and, but binds its arguments more tightly ||: same as or, but binds its arguments more tightly _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 4 Wiley and the book authors, 2002 Logical operator precedence Just as with the arithmetic operators, some logical operators have higher execution precedence than others and precedence can be overridden by grouping subexpressions together using parentheses In declining order of precedence, operations are performed on !, &&, ||, and, xor, and finally or One very handy feature of boolean operations is that they associate left-toright and they short-circuit, unnecessary operations (meaning they do not even evaluate their second argument if their truth value is unambiguous from their first argument) E.g. the statement, if ($denom && ($numer/$denom > 2)) print "OK"; will not cause an error even if $denom is equal to 0 since in that case, the test ($numer/$denom > 2) would not execute since the "anded" operation's outcome has already been determined since $denom evaluates to FALSE _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 5 Wiley and the book authors, 2002 Comparison operators Comparison operators can be used for either numbers or strings, however caution should be utilized in comparing anything that is not an integer Operator Name Behavior == Is equal to True if its operands are equal to each other != Not equal False if its arguments are equal to each other < Less than True if the left-hand operand is less than the right-hand operand > Greater than True if the left-hand operand is greater than the right-hand operand <= Less than or equal to Duh >= Greater than or equal to Double-duh === Identical True if its arguments are equal to each other and of the same type, and otherwise false _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 6 Wiley and the book authors, 2002 Comparison operators (cont.) Although over-reliance on precedence rules in comparison, boolean, and arithmetic operators can be confusing for the person who reads your code next, it's important to note that comparison operators have a higher precedence than boolean operators Comparing doubles (real numbers) can be problematic when testing for equality because rounding errors may make 2 values that are theoretically equal differ slightly When comparing doubles for "equality", you should test whether a number falls within an acceptable range using <= and >= Comparing strings using the comparison operators can also be tricky since strings will be converted to numbers if possible to perform the comparison which may yield unexpected results and comparisons are done on a case-sensitive basis using the ASCII values for determining order (e.g. 'B' < 'a') _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 7 Wiley and the book authors, 2002 Branching In PHP there are 2 main structures for branching if branches are the workhorse in most programming languages and is usually the first conditional structure anyone learns switch is a useful alternative for certain situations where you want multiple possible branches based on a single value and where a series of if statements would be cumbersome The syntax for the if statement is: if (test) statement-1; elseif (test) statement-2; else statement-3; When an if statement is processed, the test expression is evaluated, and the result is interpreted as a boolean value. If test is true, statement-1 is executed. If test is false, the next elseif statement is interpreted if it exists. If all if and elseif clauses' tests are false, then the statement associated with the else clause is executed if it exists _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 8 Wiley and the book authors, 2002 IF (cont.) How does PHP determine which if statement an elseif or else statement goes with? if (num % 2 == 0) if ($num > 2) print ('num is not prime<BR>'); else print('num is odd<BR>'); Each else and elseif is matched with the nearest unmatched if that can be found, while respecting the boundaries of braces. If you want to make sure that an if statement stays solo and does not get matched to an else, wrap it up in braces if (num % 2 == 0) { if ($num > 2) print ('num is not prime<BR>'); } else print('num is odd<BR>'); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 9 Wiley and the book authors, 2002 Switch For a specific kind of multiway branching, the switch construct can be useful. Rather than branch on arbitrary logical expressions, switch takes different paths according to the value of a single expression (usually a variable's value) switch ($day) { case 5: print('Five golden rings<BR>'); break; case 4: print('Four calling birds<BR>'); break; case 3: print('Three French hens<BR>'); break; case 2: print('Two turtledoves<BR>'); break; case 1: print('A partridge in a '. 'pear tree.<BR>'); break; default: print('<B>Unknown day</B><BR>'); } _______________________________________________________________________________________________________________ if ($day == 5) print('Five golden rings<BR>'); elseif ($day == 4) print('Four calling birds<BR>'); elseif ($day == 3) print('Three French hens<BR>'); elseif ($day == 2) print('Two turtledoves<BR>'); elseif ($day == 1) print('A partridge in a '. 'pear tree.<BR>'); else print('<B>Unknown day</B><BR>'); PHP Bible, 2nd Edition 10 Wiley and the book authors, 2002 Switch (cont.) The expression can be a variable or any other kind of expression as long as it evaluates to a scalar value (integer, double, or string) The construct executes by evaluating the expression and then testing the result for equality against each case value As soon as a match is found, subsequent statements are executed in sequence until the break statement or the end of the switch statement is reached A special default tag can be used at the end which will match the expression if no other case has matched it so far (analogous to the else clause in an if statement) Multiple values can be specified for an executable block by having multiple case statements preceding that block of statements switch (strtolower($up_in_the_air)) { case 'bird': case 'plane': print ('It\'s Superman<BR>'); break; _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 11 Wiley and the book authors, 2002 Looping Bounded loops vs. unbounded loops A bounded loop is a loop that will executed a fixed number of times - you can tell by looking at the code how many times the loop will iterate, and the language guarantees that it won't loop more times than that An unbounded loop is one that repeats until some condition becomes true (or false) and that condition is dependent on the action of the code within the loop PHP doesn't have any bounded loop constructs, but an unbounded loop can do anything a bounded loop can do PHP also provides looping constructs which iterate over the contents of arrays which will be discussed in a later chapter _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 12 Wiley and the book authors, 2002 While loops The simplest PHP looping construct is while, which has the following syntax: while (condition) statement; The while loop evaluates the condition expression as a boolean – if it’s true, it executes statement and then starts again by evaluating condition and repeats this process until condition is false Statement may be a single statement or it may be a braceenclosed ({}) block It’s possible that a while loop may not execute even once if condition is false upon reaching the while loop, or the will loop may continue executing indefinitely (or until the computer executing the script runs out of memory) if the condition never changes from being true _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 13 Wiley and the book authors, 2002 While loop examples The following loop will never execute $count = 1; while ($count > 10) print ($count); This loop will never stop executing (infinite loop) $count = 1; while ($count < 10) print ($count); This is probably what you wanted the loop to do $count = 1; while ($count < 10) { print ($count); $count++; // same as $count = $count + 1; } _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 14 Wiley and the book authors, 2002 Do-while The do-while loop is similar to the while loop except that the test is performed at the end of the loop rather than the beginning and consequently the loop will always execute at least one time $count = 45; do { print ("count is $count<BR>\n"); $count++; } while ($count <= 10); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 15 Wiley and the book authors, 2002 For loops The most complicated looping construct is the for loop which has the following syntax for (initial-expression;termination-check;loop-end-expression) statement When executing a for statement The initial-expression is evaluated just once, usually to initialize variables The termination-check is evaluated each iteration of the loop and if false, the loop terminates The statement or statement block is then executed The loop-end-expression is then executed and we go back to the termination-check for ($count = 0; $count < 10; $count++) print ($count); Would output "0123456789" _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 16 Wiley and the book authors, 2002 Example <?php $start_num = 1; $end_num = 10; ?> <HTML> <HEAD> <TITLE>A division table</TITLE> </HEAD> for ($x=$start_num;$x<=$end_num;$x++) { print("\n\t<TR><TH>$x</TH>"); for ($y=$start_num;$y<=$end_num;$y++) { $result = $x / $y; // see chapter 10 for printf printf("<TD>%.3f</TD>",$result); } print('</TR>'); } ?> </TABLE> </BODY> </HTML> <BODY> <H2>A division table</H2> <TABLE BORDER="1"> <?php print("<TR>\n\t<TH>&nbsp</TH>"); for ($x=$start_num;$x<=$end_num;$x++) print ("<TH>$x</TH>"); print ('</TR>'); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 17 Wiley and the book authors, 2002 Sample for loop output _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 18 Wiley and the book authors, 2002 Terminating execution Sometimes you just have to give up, and PHP offers a construct that helps you do just that The exit construct takes either a string or a number as an argument, prints out the argument, and immediately terminates the execution of the script Everything that PHP produces up to the point of invoking the exit construct is sent to the client browser as usual, and nothing in your script after that point will even be parsed Because exit is a construct and not a function, it is also legal to give no argument and even omit the parenthesis If you give a number rather than a string to the exit construct, the number will be the return code of the script The die construct is an alias for exit $connection = make_database_connection(); if (!$connection) die ('Unable to connect to database'); Or $connection = make_database_connection() or die ('Unable to connect to database'); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 19 Wiley and the book authors, 2002 Using functions Any real programming language has some kind of capacity for procedural abstraction - a way to name some pieces of code so that you can use them as building blocks in writing other pieces of code The basic syntax for using (or calling) a function is: Function_name(expression_1,expression_2,…,expression_n) This includes the name of the function followed by a parenthesized and comma-delimited list of input expressions (arguments) Functions can be called with zero or more arguments, depending on their definition When PHP encounters a function call, it first evaluates each argument expression and then uses these values as inputs ot the function. After the function executes, the returned value (if any) is the result of the entire function expression _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 20 Wiley and the book authors, 2002 Return values versus side effects Every function call is a PHP expression, and there are only two reasons why you might want to include one in your code For the return value Or the side effects This is the value of the function expression itself. You can do exactly the same things with this value as with the results of evaluating any other expression (e.g. assign it to a variable or use it in another expression) Some functions are called for the actions they cause (e.g. writing to files, manipulating databases, printing things to the browser window, etc.) Often times functions are called both for their return values and the side effects at the same time (e.g. calling a function for its side effect and then testing the return value to ensure that the function succeeded) The result of a function may be of any type _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 21 Wiley and the book authors, 2002 Function documentation Although the book covers many of the built-in functions of PHP, the manual at www.php.net is the authoritative source for function information (including functions which may be added for each new release of PHP) The HTML version of the English PHP documentation is currently located at http://www.php.net/manual/en/ The online documentation also includes a section for usercontributed notes which may address some particular questions you may have about the usage of that function, how to combine it with other functions for a particular effect, or to see what other side effects that function may cause Functions are grouped according to their respective categories with an overview of all of the functions in that category as well as individual pages for each function built into PHP _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 22 Wiley and the book authors, 2002 Headers in function documentation The very beginning of a function documentation page is formatted like: Return-type function-name(type1 arg1, type2 arg2, …) E.g. string substr(string string, int start[, int length]); Where the function substr returns a value of type string and takes 2 mandatory arguments of type string and int, and a third optional argument of type int Of course PHP will convert almost anything you pass in as an argument to the type the function is expecting Return types may also be specified as void or mixed Return type void is used if the function doesn't return a value Return type mixed is used if the function may return a value of any type _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 23 Wiley and the book authors, 2002 Defining your own functions A function is a way of wrapping up a chunk of code and giving that chunk a name so that you can use that chunk later in just one line of code Function definitions have the following form: function function-name ($argument1, $argument2, …) { statement1; statement2; return expression; } Begin with the key-word function followed by the name you give to that function followed by your parameter list in parenthesis and the body of the function inside braces The name of the function must be made up of letters, numbers, and underscores and it must not start with a number Function names are not case-sensitive Once called, a function will execute its body until it reaches the end of the body or until a return statement is reached _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 24 Wiley and the book authors, 2002 Function definition example Suppose you want to create a function which helps decide which size bottled soft drink to by: function better_deal ($amount_1, $price_1, $amount_2, $price_2) { $per_amount_1 = $price_1 / $amount_1; $per_amount_2 = $price_2 / $amount_2; return ($per_amount_1 < $per_amount_2); } Which could be used in your code as: $liters_1 = 1.0; $price_1 = 1.59; $liters_2 = 1.5; $price_2 = 2.09; if (better_deal($liters_1,$price_1,$liters_2,$price_2)) print ('The first deal is better!<BR>'); else print ('The second deal is better!<BR>'); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 25 Wiley and the book authors, 2002 Argument number mismatches As can be expected in PHP, if you pass in too few or too many arguments to a function, it will not crash the application but may print warning messages depending on your settings Too few arguments passed: If you supply fewer arguments to a function than it requires, PHP will treat the unfilled formal parameters as if they were unbound variables and may see a warning message printed to the output You can suppress these warning messages by using the error-control operator @ which can be placed in front of any expression to suppress errors from that expression only (e.g. @better_deal(1.0,1.59)) You can also write your function definition to accept a variable number of arguments by supplying default values (discussed later) Too many arguments passed: If you supply more arguments than the function expects, the extraneous arguments will simply be ignored and no warnings are issued _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 26 Wiley and the book authors, 2002 Functions and variable scope Each function is basically its own little script & barring some special declarations, the meaning of a variable name inside a function has nothing to do with the meaning of that name elsewhere Exception: the super-global arrays like $_POST, $_GET, $_SESSION, etc. are automatically visible from within function definitions The only variable values that a function has access to are the formal parameter variables (which have values copied from the actual parameters), plus any variables that are created inside the function. Local variables defined inside a function will have no effect on code executing outside that function _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 27 Wiley and the book authors, 2002 Global vs. local The scope of a variable defined within a function is local to that function by default. This behavior can be overridden by using the global declaration, informing PHP that you want a variable name to mean the same thing as it does in the context outside the function $output_string = 'This is my output'; $separator = '<BR>'."\n"; function modify_string($add_text) { global $output_string,$separator; return $output_string .= $separator.$add_text; } Would output: This is my output<BR> Line #2 And the value of the variable $output_string would be 'This is my output<BR>\nLine #2' modify_string('Line #2'); print ($output_string); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 28 Wiley and the book authors, 2002 Static variables By default, functions retain no memory of their own prior execution, and with each function call local variables act as though they have been newly created The static declaration overrides this behavior for specified variables, causing them to retain their values in between calls to the same function function count_executions() { static $count = 0; return ++$count; } Would output: 12345678910 for ($count=10;$count > 0;$count--) print (count_executions()); The static keyword allows for an initial assignment, which has an effect only if the function has not been called before The second time the function is called, static variables are initially assigned the value they had at the end of the previous execution _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 29 Wiley and the book authors, 2002 Recursion Recursive functions are those functions which call themselves (either directly or by calling a function which calls itself) function countdown ($num_arg) { if ($num_arg > 0) { print("Counting $num_arg"); countdown (--$num_arg); } } Would product the browser output: Counting 5 Counting 4 Counting 3 Counting 2 Counting 1 countdown (10); As with all recursive functions, it's important to be sure that the function has a base case (a nonrecursive branch) in addition to the recursive case, and that the base case is certain to eventually occur. Otherwise the situation would be similar to an infinite loop _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 30 Wiley and the book authors, 2002 Variable numbers of arguments It's often useful to have the number of actual arguments that are passed to a function depend on the situation in which it is called This can be accomplished by: 1. 2. 3. Defining the function with default values for the arguments - any that are missing in the call to the function will have the default value, and no warning will be printed Use an array argument to hold the values - it is the responsibility of the calling code to package up the array, and the function body must take it apart Use the variable-argument functions (func_num_args(), func_get_arg(), and func_get_args()) introduced in PHP 4 _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 31 Wiley and the book authors, 2002 Default arguments To define a function with default arguments, simply turn the formal parameter name into an assignment expression. If the actual call has fewer parameters than the definition has parameters, PHP will match parameters with the arguments until the actual arguments are exhausted and then will use the default assignments to fill in the rest function open_db ($db_name, $user="MGMT380b", $pwd="MGMT380b", $host="sql.gettelco.com") { $db_handle = mysql_connect( $host, $user, $ pwd) or die ("Cannot connect to the database server $host:". mysql_error()); mysql_select_db($db_name) or die ("Error connecting to db $db_name:". mysql_error()); return $dbHandle; } open_db ('Store'); _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 32 Wiley and the book authors, 2002 Call-by-value vs. call-by-reference By default, PHP functions are call-by-value meaning that when you pass variables to a function call, PHP makes copies of the values of the variable which are then assigned to the appropriate parameters used in the function body Consequently, no matter what a function does, it cannot change the actual variables that you pass to the function call If you want the function to actually modify the values of the variable passed into the function, you can tell PHP to use a callby-reference on the specific parameters in the function definition by putting an ampersand (&) before the parameter name (e.g. function my_function(&$modifiable_parameter)) _______________________________________________________________________________________________________________ PHP Bible, 2nd Edition 33 Wiley and the book authors, 2002