PHP (recursive acronym for PHP: Hypertext Preprocessor) is a free scripting language primarily used to produce dynamic web pages via an HTTP server, but it can also function like any interpreted language locally by executing programs on the command line. PHP is an imperative language that has had complete object-oriented model capabilities since version 5. Due to the richness of its library, PHP is sometimes referred to as a platform rather than just a language.
Basics
In pages containing mainly HTML, it is possible to insert small pieces of PHP to make life easier. Just use tags like:
<?phpprint"Hello, ";// Print what was submitted in the form parameter called 'user'print$_POST['user'];print"!";?>
$_POST contains the values of the form parameters as they were submitted. In programming terms, it's a variable named as such because you can modify the values it contains. In fact, it's a array variable because it can hold multiple values simultaneously.
When $_SERVER[PHP_SELF] is the form's action, you can place both the form display code and the form processing code on the same page:
<?php// Print a greeting if the form was submittedif($_POST['user']){print"Hello, ";// Print what was submitted in the form parameter called 'user'print$_POST['user'];print"!";}else{// Otherwise, print the formprint<<<_HTML_<form method="post" action="$_SERVER[PHP_SELF]">Your Name: <input type="text" name="user"><br/><input type="submit" value="Say Hello"></form>_HTML_;}?>
For comments, you can use:
//: For a single line to comment
/* to */: To comment a paragraph, we will come back to this later.
Now here is an example of PHP code that connects to a database server and retrieves a list of dishes with their prices based on the value of the "rpas" parameter, then displays these dishes and their prices in an HTML table:
<?phprequire'DB.php';// Connect to MySQL running on localhost with username "menu"// and password "good2eaT", and database "dinner"$db=DB::connect('mysql://menu:good2eaT@localhost/dinner');// Define what the allowable meals are$meals=array('breakfast','lunch','dinner');// Check if submitted form parameter "meal" is one of// "breakfast", "lunch", or "dinner"if(in_array($meals,$_POST['meal'])){// If so, get all of the dishes for the specified meal$q=$dbh->query("SELECT dish,price FROM meals WHERE meal LIKE '".$_POST['meal']."'");// If no dishes were found in the database, say soif($q->numrows==0){print"No dishes available.";}else{// Otherwise, print out each dish and its price as a row// in an HTML tableprint'<table><tr><th>Dish</th><th>Price</th></tr>';while($row=$q->fetchRow()){print"<tr><td>$row[0]</td><td>$row[1]</td></tr>";}print"</table>";}}else{// This message prints if the submitted parameter "meal" isn't// "breakfast", "lunch", or "dinner"print"Unknown meal.";}?>
Manipulation of textual and numerical data
Strings can be delimited by "". They work like strings surrounded by ', but allow more special characters:
Character
Meaning
\n
Newline (ASCII 10)
\r
Carriage return (ASCII 13)
\t
Tab (ASCII 9)
\
\
\$
$
\"
"
\0 .. \777
Octal (base 8) number
\x0 .. \xFF
Hexadecimal (base 16) number
A small example to clarify everything. Imagine $user is Pierre:
'Hello $user': Will display: Hello $user
"Hello $user": Will display: Hello Pierre
To combine 2 strings, use a "." which allows concatenation of strings:
breadfruit
It's a beautiful day in the neighborhood.
The price is: $3.95
InkyPinkyBlinkyClyde
Text manipulation
String validation
The trim() function removes spaces at the beginning or end of a string. Combined with strlen(), which tells you the length of a string, you can know the length of a value submitted by a form while ignoring leading and trailing spaces.
// $_POST['zipcode'] holds the value of the submitted form parameter
// "zipcode"
$zipcode = trim($_POST['zipcode']);
// Now $zipcode holds that value, with any leading or trailing spaces
// removed
$zip_length = strlen($zipcode);
// Complain if the ZIP code is not 5 characters long
if ($zip_length != 5) {
print "Please enter a ZIP code that is 5 characters long.";
}
You can do it shorter by combining functions. Similar to Final Fantasy when you combine mana:
if ($_POST['email'] == 'president@whitehouse.gov') {
print "Welcome, Mr. President.";
}
To compare strings without taking case into account, use the strcasecmp() function. It returns 0 if the 2 strings provided to strcasecmp() are equal (regardless of case):
The "%.2f" is replaced by the value of $price * (1 + $tax)) and formatted to have 2 digits after the decimal point.
Format rules start with %. You can then place optional modifiers that affect the rule's behavior:
A fill character: If the string replacing the format rule is too short, this character will fill it. Use a space to fill with spaces or a 0 to fill with zeros.
A sign: For numbers, a + will place a + before positive numbers (they are normally displayed without a sign). For strings, a - will make the string right-justified (by default, strings are left-justified).
A minimum width: the minimum size that the value replacing the format rule should have. If it's shorter, the fill character will be used to fill the void.
A point and a number of decimal places: For floating point numbers, this controls the number of digits after the decimal point. In the example above, the .2 formats $price * (1 + $tax)); with 2 decimal places.
The Fresh Fish with Rice Noodle was delicious, but I didn't like the Beef Tripe.
The three parameters of substr() are respectively, the string concerned, the starting position of the substring to extract and the number of characters to extract. The string starts at position 0, not 1: substr($_POST['comments'], 0, 30) therefore means "extract 30 characters from $_POST['comments'] starting from the beginning of this string".
So this is a very practical example for credit cards.
For brevity, you can use substr($_POST['card'],-4) instead of substr($_POST['card'], -4,4). If you don't provide the last parameter, substr() will return everything between the starting position (whether positive or negative) and the end of the string.
<?php$price=3.95;$tax_rate=0.08;$tax_amount=$price*$tax_rate;$total_cost=$price+$tax_amount;$username='james';$domain='@example.com';$email_address=$username.$domain;print'The tax is '.$tax_amount;print"\n";// this prints a linebreakprint'The total cost is '.$total_cost;print"\n";// this prints a linebreakprint$email_address;?>
// Add one to $birthday$birthday = $birthday + 1;// Add another one to $birthday++$birthday;// Subtract 1 from $years_left$years_left = $years_left - 1;// Subtract another 1 from $years_left
Display a special menu if a user with admin rights is logged in.
Display a different page header depending on the time of day.
Notify a user if they've received new messages since their last connection.
When making decisions, the PHP interpreter reduces an expression to a true or false value.
The value of an assignment is the assigned value. The expression $price = 5 equals 5: this price has been assigned to $price. Since assignment produces a result, you can chain assignments to assign the same value to multiple variables:
if ($logged_in) { // This runs if $logged_in is true print "Welcome aboard, trusted user.";} elseif ($new_messages) { // This runs if $logged_in is false but $new_messages is true print "Dear stranger, there are new messages.";} elseif ($emergency) { // This runs if $logged_in and $new_messages are false // But $emergency is true print "Stranger, there are no new messages, but there is an emergency.";} else { // You can put what you want}
if ($new_messages == 10) {
print "You have ten new messages.";
}
if ($new_messages == $max_messages) {
print "You have the maximum number of messages.";
}
if ($dinner == 'Braised Scallops') {
print "Yum! I love seafood.";
}
if ($new_messages != 10) {
print "You don't have ten new messages.";
}
if ($dinner != 'Braised Scallops') {
print "I guess we're out of scallops.";
}
Be careful not to use = when you want to use ==. A single equals sign assigns a value and returns the assigned value, while two equal signs test equality and return true if the values are equal. If you forget the second equals sign, you will usually get an if() test that will always be true:
Example of an assignment that should have been a comparison:
if ($age > 17) { print "You are old enough to download the movie.";}if ($age >= 65) { print "You are old enough for a discount.";}if ($celsius_temp <= 0) { print "Uh-oh, your pipes may freeze.";}if ($kelvin_temp < 20.3) { print "Your hydrogen is a liquid or a solid now.";}
Floating-point numbers have an internal representation that may be slightly different from the assigned value (the internal representation of 50.0, for example, might be 50.000000002). To test if 2 floating-point numbers are equal, check if the difference between these 2 numbers is less than a reasonably small threshold, instead of using the equality operator. If you compare monetary values, for example, an acceptable threshold would be 0.00001.
if(abs($price_1 - $price_2) < 0.00001) { print '$price_1 and $price_2 are equal.';} else { print '$price_1 and $price_2 are not equal.';}
The abs() function returns the absolute value of its parameter. With abs(), the comparison works correctly, whether $price_1 is greater than $price_2 or not.
The ASCII codes for digits are less than those for uppercase letters, which are themselves less than the codes for lowercase letters; the codes for accented letters are in the "extended" part, thus higher than all codes in international ASCII.
Generally, strings are compared alphabetically (caramel < chocolate).
if ($word < 'baa') { print "Your word isn't cookie.";}if ($word >= 'zoo') { print "Your word could be zoo or zymurgy, but not zone.";}
If you want to make sure the PHP interpreter compares strings without performing numeric conversion behind the scenes, use the strcmp() function which always compares its parameters according to the ASCII table order.
The strcmp() function takes two strings as parameters. It returns a positive number if the first string is greater than the second or a negative number if the first string is less than the second. The order is that of the extended ASCII table. This function returns 0 if the 2 strings are equal.
$x = strcmp("x54321","x5678");if ($x > 0) { print 'The string "x54321" is greater than the string "x5678".';} elseif ($x < 0) { print 'The string "x54321" is less than the string "x5678".';}
In the example below, strcmp() finds that the string "54321" is less than "5678" because the second characters of the 2 strings differ and "4" comes before "6". The alphabetical order is all that matters to the strcmp() function, no matter that numerically it's the opposite.
// These values are compared using numeric orderif ("54321" > "5678") { print 'The string "54321" is greater than the string "5678".';} else { print 'The string "54321" is not greater than the string "5678".';}
if (! strcasecmp($first_name,$last_name)) {
print '$first_name and $last_name are equal.';
}
With logical operators, you can combine multiple expressions in the same if() statement. The logical AND operator, &, tests if 2 expressions are both true. The logical OR operator, ||, tests if at least one of the 2 expressions is true:
if (($age >= 13) && ($age < 65)) { print "You are too old for a kid's discount and too young for the senior's discount.";}if (($meal == 'breakfast') || ($dessert == 'souffle')) { print "Time to eat some eggs.";}
// An array called $vegetables with string keys$vegetables['corn'] = 'yellow';$vegetables['beet'] = 'red';$vegetables['carrot'] = 'orange';// An array called $dinner with numeric keys$dinner[0] = 'Sweet Corn and Asparagus';$dinner[1] = 'Lemon Chicken';$dinner[2] = 'Braised Bamboo Fungus';// An array called $computers with numeric and string keys$computers['trs-80'] = 'Radio Shack';$computers[2600] = 'Atari';$computers['Adam'] = 'Coleco';
Array keys and values are written exactly like other strings and numbers in a PHP program: with apostrophes around strings, but not around numbers.
With array(), you specify a list of key/value pairs separated by commas. The key and value are separated by =>. The array() syntax is more concise when adding multiple elements to an array at once. The bracket syntax is preferable when adding elements one by one.
Creating an array indexed by numbers
If you create an array with array() by specifying only a list of values instead of key/value pairs, the PHP interpreter automatically assigns a numeric key to each value. The keys start at 0 and increase by 1 for each element. The example below uses this technique to create the $dinner array:
// Create $lunch array with two elements// This sets $lunch[0]$lunch[] = 'Dried Mushrooms in Brown Sauce';// This sets $lunch[1]$lunch[] = 'Pineapple and Yu Fungus';// Create $dinner with three elements$dinner = array('Sweet Corn and Asparagus', 'Lemon Chicken', 'Braised Bamboo Fungus');// Add an element to the end of $dinner// This sets $dinner[3]$dinner[] = 'Flank Skin with Spiced Flavor';
If the array doesn't exist yet, empty brackets create it by adding an element with key 0.
Finding the size of an array
The count() function returns the number of elements in an array:
$dinner = array('Sweet Corn and Asparagus', 'Lemon Chicken', 'Braised Bamboo Fungus');$dishes = count($dinner);print "There are $dishes things for dinner.";
<table><tr><td>breakfast</td><td>Walnut Bun</td></tr><tr><td>lunch</td><td>Cashew Nuts and White Mushrooms</td></tr><tr><td>snack</td><td>Dried Mulberries</td></tr><tr><td>dinner</td><td>Eggplant with Chili Sauce</td></tr></table>
<table><tr bgcolor="red"><td>breakfast</td><td>Walnut Bun</td></tr><tr bgcolor="green"><td>lunch</td><td>Cashew Nuts and White Mushrooms</td></tr><tr bgcolor="red"><td>snack</td><td>Dried Mulberries</td></tr><tr bgcolor="green"><td>dinner</td><td>Eggplant with Chili Sauce</td></tr></table>
$meals = array('Walnut Bun' => 1, 'Cashew Nuts and White Mushrooms' => 4.95, 'Dried Mulberries' => 3.00, 'Eggplant with Chili Sauce' => 6.50);foreach ($meals as $dish => $price) { // $price = $price * 2 does NOT work $meals[$dish] = $meals[$dish] * 2;}// Iterate over the array again and print the changed valuesforeach ($meals as $dish => $price) { printf("The new price of %s is \$%.2f.\n",$dish,$price);}
meals = array('Walnut Bun' => 1,
'Cashew Nuts and White Mushrooms' => 4.95,
'Dried Mulberries' => 3.00,
'Eggplant with Chili Sauce' => 6.50,
'Shrimp Puffs' => 0); // Shrimp Puffs are free!
$books = array("The Eater's Guide to Chinese Characters",
'How to Cook and Eat in Chinese');
// This is true
if (array_key_exists('Shrimp Puffs',$meals)) {
print "Yes, we have Shrimp Puffs";
}
// This is false
if (array_key_exists('Steak Sandwich',$meals)) {
print "We have a Steak Sandwich";
}
// This is true
if (array_key_exists(1, $books)) {
print "Element 1 is How to Cook in Eat in Chinese";
}
The array_search() function is similar to in_array(), but if it finds an element it returns its key rather than true. In the example below, array_search() returns the name of the dish that costs 6.50 euros:
$meals['breakfast'] = 'Walnut Bun';$meals['lunch'] = 'Eggplant with Chili Sauce';$amounts = array(3, 6);print "For breakfast, I'd like $meals[breakfast] and for lunch, ";print "I'd like $meals[lunch]. I want $amounts[0] at breakfast and ";print "$amounts[1] at lunch.";
The unset() function allows you to remove an element from an array:
Deleting an element with unset() is different from simply assigning it 0 or an empty string. When you use unset(), the element is no longer there when traversing the array or counting the number of its elements. Using unset() on an array representing an inventory is like saying that the store no longer offers a product. Setting the element's value to 0 or assigning an empty string means that this element is no longer in stock for the moment.
The sort() function sorts an array by the values of its elements. It should only be used on arrays with numeric keys because it resets these keys during sorting. Here are some arrays before and after a call to sort().
Before Sorting: $meal: breakfast Walnut Bun $meal: lunch Cashew Nuts and White Mushrooms $meal: snack Dried Mulberries $meal: dinner Eggplant with Chili SauceAfter Sorting: $meal: lunch Cashew Nuts and White Mushrooms $meal: snack Dried Mulberries $meal: dinner Eggplant with Chili Sauce $meal: breakfast Walnut Bun
While sort() and asort() sort arrays by the values of their elements, ksort() allows sorting by their keys: the key/value pairs remain identical, but are ordered by keys.
The functions rsort(), arsort() and krsort() are the respective counterparts of sort(), asort() and ksort() for sorting in descending order. They work exactly the same way, except that the largest key or value (or the last from an alphabetical point of view) will appear first in the sorted array and the following elements will be placed in descending order.
$prices['dinner']['Sweet Corn and Asparagus'] = 12.50;$prices['lunch']['Cashew Nuts and White Mushrooms'] = 4.95;$prices['dinner']['Braised Bamboo Fungus'] = 8.95;$prices['dinner']['total'] = $prices['dinner']['Sweet Corn and Asparagus'] + $prices['dinner']['Braised Bamboo Fungus'];$specials[0][0] = 'Chestnut Bun';$specials[0][1] = 'Walnut Bun';$specials[0][2] = 'Peanut Bun';$specials[1][0] = 'Chestnut Salad';$specials[1][1] = 'Walnut Salad';// Leaving out the index adds it to the end of the array// This creates $specials[1][2]$specials[1][] = 'Peanut Salad';
Traversing a multidimensional array with foreach():
$flavors = array('Japanese' => array('hot' => 'wasabi', 'salty' => 'soy sauce'), 'Chinese' => array('hot' => 'mustard', 'pepper-salty' => 'prickly ash'));// $culture is the key and $culture_flavors is the value (an array)foreach ($flavors as $culture => $culture_flavors) { // $flavor is the key and $example is the value foreach ($culture_flavors as $flavor => $example) { print "A $culture $flavor flavor is $example.\n"; }}
A Japanese hot flavor is wasabi.A Japanese salty flavor is soy sauce.A Chinese hot flavor is mustard.A Chinese pepper-salty flavor is prickly ash.
The first foreach() loop traverses the first dimension of $flavors. The keys stored in $culture are the strings Japanese and Chinese and the values stored in $culture_flavors are the arrays that are the elements of this dimension. The next foreach() traverses these arrays by copying keys like hot and salty into $flavors and values like wasabi and soy sauce into $example. The code block of the second foreach() uses the variables from both foreach() instructions to produce a complete message.
Just as nested foreach() loops traverse a multidimensional associative array, nested for() loops allow traversing a multidimensional array with numeric indices:
$specials = array( array('Chestnut Bun', 'Walnut Bun', 'Peanut Bun'), array('Chestnut Salad','Walnut Salad', 'Peanut Salad') );// $num_specials is 2: the number of elements in the first dimension of $specialsfor ($i = 0, $num_specials = count($specials); $i < $num_specials; $i++) { // $num_sub is 3: the number of elements in each sub-array for ($m = 0, $num_sub = count($specials[$i]); $m < $num_sub; $m++) { print "Element [$i][$m] is " . $specials[$i][$m] . "\n"; }}
Element [0][0] is Chestnut BunElement [0][1] is Walnut BunElement [0][2] is Peanut BunElement [1][0] is Chestnut SaladElement [1][1] is Walnut SaladElement [1][2] is Peanut Salad
To interpolate the value of a multidimensional array in a string between double apostrophes or an in-place document, we must use the syntax to produce the same result as the previous example: in fact, the only difference is the print instruction:
$specials = array( array('Chestnut Bun', 'Walnut Bun', 'Peanut Bun'), array('Chestnut Salad','Walnut Salad', 'Peanut Salad') );// $num_specials is 2: the number of elements in the first dimension of $specialsfor ($i = 0, $num_specials = count($specials); $i < $num_specials; $i++) { // $num_sub is 3: the number of elements in each sub-array for ($m = 0, $num_sub = count($specials[$i]); $m < $num_sub; $m++) { print "Element [$i][$m] is {$specials[$i][$m]}\n"; }}
function page_header( ) { print '<html><head><title>Welcome to my site</title></head>'; print '<body bgcolor="#ffffff">';}page_header( );print "Welcome, $user";page_footer( );function page_footer( ) { print '<hr>Thanks for visiting.'; print '</body></html>';}
I strongly recommend you to code "clean". Indeed, if you place functions anywhere in your code, it will quickly become messy. You should group functions together and put them at the beginning of your code. I'm not a purist (...well, maybe), but people reviewing your code after you, or even yourself if you take it up a few months later, will appreciate being able to quickly understand the code.
Passing parameters to functions
Declaration of a function with a parameter (here $color):
<html><head><title>Welcome to my site</title></head><body bgcolor="#cc00cc">
When you define a function that takes a parameter, you must pass a parameter to this function when calling it. Otherwise, the PHP interpreter will produce a warning message to complain about it. If for example, you call page_header2() as follows:
PHP Warning: Missing argument 1 for page_header2()
Using a default value for a parameter:
To avoid this warning, make it so this function can be called without parameters by providing a default value in the function declaration. In this case, if the function is called without parameters, this default value will be taken as the parameter value. To provide a default value, place it after the parameter name. Here this value is cc3399:
$my_color = '#000000';// This is incorrect: the default value can't be a variable.function page_header_bad($color = $my_color) { print '<html><head><title>Welcome to my site</title></head>'; print '<body bgcolor="#' . $color . '">';}
To return values from your own functions, use the return keyword, followed by the value to return. The execution of a function stops as soon as the return keyword is encountered and then returns the specified value. The example below defines a function that returns the total amount of a meal after adding VAT and tip. Returning a value from a function:
A return statement can only return one value: syntax like return 15, 23 is not allowed. If you want a function to return multiple values, place them in an array and return it.
Here's a modified version of the restaurant_check() function that returns a 2-element array, corresponding to the total amount before and after adding the tip.
$totals = restaurant_check2(15.22, 8.25, 15);if ($totals[0] < 20) { print 'The total without tip is less than $20.';}if ($totals[1] < 20) { print 'The total with tip is less than $20.';}
function can_pay_cash($cash_on_hand, $amount) { if ($amount > $cash_on_hand) { return false; } else { return true; }}$total = restaurant_check(15.22,8.25,15);if (can_pay_cash(20, $total)) { print "I can pay in cash.";} else { print "Time for the credit card.";}
From a function, there are 2 ways to access a global variable. The most direct method is to look them up in a special array called $GLOBALS, because any global variable is accessible as an element of this array. Here's how to use the $GLOBALS array:
$dinner = 'Curry Cuttlefish';function macrobiotic_dinner( ) { $dinner = "Some Vegetables"; print "Dinner is $dinner"; // Succumb to the delights of the ocean print " but I'd rather have "; print $GLOBALS['dinner']; print "\n";}macrobiotic_dinner( );print "Regular dinner is: $dinner";
Dinner is Some Vegetables but I'd rather have Curry Cuttlefish
Regular dinner is: Curry Cuttlefish
The 2nd way to access a global variable from a function is to use the global keyword, which tells the PHP interpreter that the subsequent use, in the function, of the indicated variable will refer to this local variable, and not to a local variable: this is called "placing a variable in the local scope". The global keyword:
$dinner = 'Curry Cuttlefish';function vegetarian_dinner( ) { global $dinner; print "Dinner was $dinner, but now it's "; $dinner = 'Sauteed Pea Shoots'; print $dinner; print "\n";}print "Regular Dinner is $dinner.\n";vegetarian_dinner( );print "Regular dinner is $dinner";