Last active
January 29, 2025 06:44
-
-
Save Mwamitovi/e444dc06c6b13c6ca9369dccbd3c7bb4 to your computer and use it in GitHub Desktop.
learningPHP: Chapters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter - 2: Exercises | |
// Question-1 | |
// 1. Find the errors in this PHP program: | |
// 1. The opening PHP tag should be just <?php with no space between the <? and php. | |
// 2. Because the string I'm fine contains a ', | |
// it should be surrounded by double quotes ("I'm fine") or the ' should be escaped ('I\'m fine'). | |
// 3. The closing PHP tag should be \?\>, not ?\?\>. | |
// Or, if this code were the last thing in its file, the closing PHP tag could be omitted. | |
// Question-2 | |
// 2. Write a PHP program that computes the total cost of this restaurant meal: two | |
// hamburgers at $4.95 each, one chocolate milkshake at $1.95, and one cola at 85 | |
// cents. The sales tax rate is 7.5%, and you left a pre-tax tip of 16%. | |
// Answer-2 | |
$hamburger = 4.95; | |
$shake = 1.95; | |
$cola = 0.85; | |
$tip_rate = 0.16; | |
$tax_rate = 0.075; | |
$food = (2 * $hamburger) + $shake + $cola; | |
$tip = $food * $tip_rate; | |
$tax = $food * $tax_rate; | |
$total = $food + $tip + $tax; | |
print 'The total cost of the meal is $' . $total; | |
// Question-3 | |
// 3. Modify your solution to the previous exercise to print out a formatted bill. For | |
// each item in the meal, print the price, quantity, and total cost. Print the pre-tax | |
// food and drink total, the post-tax total, and the total with tax and tip. Make sure | |
// that prices in your output are vertically aligned. | |
// Answer-3 | |
$hamburger = 4.95; | |
$shake = 1.95; | |
$cola = 0.85; | |
$tip_rate = 0.16; | |
$tax_rate = 0.075; | |
$food = (2 * $hamburger) + $shake + $cola; | |
$tip = $food * $tip_rate; | |
$tax = $food * $tax_rate; | |
$total = $food + $tip + $tax; | |
printf("%d %-9s at \$%.2f each: \$%5.2f\n", 2, 'Hamburger', $hamburger, 2 * $hamburger); | |
printf("%d %-9s at \$%.2f each: \$%5.2f\n", 1, 'Shake', $shake, $hamburger); | |
printf("%d %-9s at \$%.2f each: \$%5.2f\n", 1, 'Cola', $cola, $cola); | |
printf("%25s: \$%5.2f\n", 'Food Total', $food); | |
printf("%25s: \$%5.2f\n", 'Food and Tax Total', $food + $tax); | |
printf("%25s: \$%5.2f\n", 'Food, Tax, and Tip Total', $total); | |
// Question-4 | |
// 4. Write a PHP program that sets the variable $first_name to your first name and | |
// $last_name to your last name. Print out a string containing your first and last | |
// name separated by a space. Also print out the length of that string. | |
// Answer-4 | |
$first_name = 'Srinivasa'; | |
$last_name = 'Ramanujan'; | |
$name = "$first_name $last_name"; | |
print $name; | |
print strlen($name); | |
// Question-5 | |
// 5. Write a PHP program that uses the increment operator (++) and the combined | |
// multiplication operator (*=) to print out the numbers from 1 to 5 and powers of | |
// 2 from 2 (21) to 32 (25). | |
// Answer-5 | |
$n = 1; | |
$p = 2; | |
print "$n, $p\n"; | |
$n++; | |
$p *= 2; | |
print "$n, $p\n"; | |
$n++; | |
$p *= 2; | |
print "$n, $p\n"; | |
$n++; | |
$p *= 2; | |
print "$n, $p\n"; | |
$n++; | |
$p *= 2; | |
print "$n, $p\n"; | |
// Question-6 | |
// 6. Add comments to the PHP programs you’ve written for the other exercises. Try | |
// both single and multiline comments. After you’ve added the comments, run the | |
// programs to make sure they work properly and your comment syntax is correct. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter - 3: Exercises | |
// Question-1 | |
// 1. Without using a PHP program to evaluate them, determine whether each of | |
// these expressions is true or false: | |
// a. 100.00 - 100 | |
// b. "zero" | |
// c. "false" | |
// d. 0 + "true" | |
// e. 0.000 | |
// f. "0.0" | |
// g. strcmp("false","False") | |
// h. 0 <=> "0" | |
// Answer-1 | |
// 1. false | |
// 2. true | |
// 3. true | |
// 4. false | |
// 5. false | |
// 6. true | |
// 7. true | |
// 8. false | |
// Question-2 | |
// 2. Without running it through the PHP engine, figure out what this program prints: | |
// $age = 12; | |
// $shoe_size = 13; | |
// if ($age > $shoe_size) { | |
// print "Message 1."; | |
// } elseif (($shoe_size++) && ($age > 20)) { | |
// print "Message 2."; | |
// } else { | |
// print "Message 3."; | |
// } | |
// print "Age: $age. Shoe Size: $shoe_size"; | |
// Answer-2 | |
// Message 3.Age: 12. Shoe Size: 14 | |
// Question-3 | |
// 3. Use while() to print a table of Fahrenheit and Celsius temperature equivalents | |
// from –50 degrees F to 50 degrees F in 5-degree increments. On the Fahrenheit | |
// temperature scale, water freezes at 32 degrees and boils at 212 degrees. On the | |
// Celsius scale, water freezes at 0 degrees and boils at 100 degrees. So, to convert | |
// from Fahrenheit to Celsius, you subtract 32 from the temperature, multiply by 5, | |
// and divide by 9. To convert from Celsius to Fahrenheit, you multiply by 9, divide | |
// by 5, and then add 32. | |
// Answer-3 | |
$f = -50; | |
while ($f <= 50) { | |
$c = ($f - 32) * (5 / 9); | |
printf("%d degrees F = %d degrees C\n", $f, $c); | |
$f += 5; | |
} | |
// 4. Modify your answer to Exercise 3 to use for() instead of while(). | |
// Answer-4 | |
for ($f = -50; $f <= 50; $f += 5) { | |
$c = ($f - 32) * (5 / 9); | |
printf("%d degrees F = %d degrees C\n", $f, $c); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter-4: Exercises | |
// Question-1 | |
// 1. According to the US Census Bureau, the 10 largest American cities (by population) in 2010 were as follows: | |
// • New York, NY (8,175,133 people) | |
// • Los Angeles, CA (3,792,621) | |
// • Chicago, IL (2,695,598) | |
// • Houston, TX (2,100,263) | |
// • Philadelphia, PA (1,526,006) | |
// • Phoenix, AZ (1,445,632) | |
// • San Antonio, TX (1,327,407) | |
// • San Diego, CA (1,307,402) | |
// • Dallas, TX (1,197,816) | |
// • San Jose, CA (945,942) | |
// | |
// Define an array (or arrays) that holds this information about locations and populations. | |
// Print a table of locations and population information that includes the total population in all 10 cities. | |
// Answer-1 ?> | |
<table> | |
<tr> | |
<th>City</th> | |
<th>Population</th> | |
</tr> | |
<?php | |
$census = [ | |
'New York, NY' => 8175133, | |
'Los Angeles, CA' => 3792621, | |
'Chicago, IL' => 2695598, | |
'Houston, TX' => 2100263, | |
'Philadelphia, PA' => 1526006, | |
'Phoenix, AZ' => 1445632, | |
'San Antonio, TX' => 1327407, | |
'San Diego, CA' => 1307402, | |
'Dallas, TX' => 1197816, | |
'San Jose, CA' => 945942 | |
]; | |
$total = 0; | |
foreach ($census as $city => $population) { | |
$total += $population; | |
print "<tr><td>$city</td><td>$population</td></tr>\n"; | |
} | |
print "<tr><td>Total</td><td>$total</td></tr>\n"; | |
print "</table>"; | |
?> | |
<?php | |
// Question-2 | |
// 2. Modify your solution to the previous exercise so that the rows in the result table are ordered by population. | |
// Then modify your solution so that the rows are ordered by city name. | |
// Answer-2 | |
$census = [ | |
'New York, NY' => 8175133, | |
'Los Angeles, CA' => 3792621, | |
'Chicago, IL' => 2695598, | |
'Houston, TX' => 2100263, | |
'Philadelphia, PA' => 1526006, | |
'Phoenix, AZ' => 1445632, | |
'San Antonio, TX' => 1327407, | |
'San Diego, CA' => 1307402, | |
'Dallas, TX' => 1197816, | |
'San Jose, CA' => 945942 | |
]; | |
// Sort the associative array by value | |
asort($census); | |
print "<table>\n"; | |
print "<tr><th>City</th><th>Population</th></tr>\n"; | |
$total = 0; | |
foreach ($census as $city => $population) { | |
$total += $population; | |
print "<tr><td>$city</td><td>$population</td></tr>\n"; | |
} | |
print "<tr><td>Total</td><td>$total</td></tr>\n"; | |
print "</table>"; | |
// Sort the associative array by key | |
ksort($census); | |
print "<table>\n"; | |
print "<tr><th>City</th><th>Population</th></tr>\n"; | |
$total = 0; | |
foreach ($census as $city => $population) { | |
$total += $population; | |
print "<tr><td>$city</td><td>$population</td></tr>\n"; | |
} | |
print "<tr><td>Total</td><td>$total</td></tr>\n"; | |
print "</table>"; | |
// Question-3 | |
// 3. Modify your solution to the first exercise so that the table also contains rows that hold state population totals for each state represented in the list of cities. | |
// Answer-3 ?> | |
<table> | |
<tr> | |
<th>City</th> | |
<th>Population</th> | |
</tr><?php | |
// Each element in $census is a three-element array containing city name, state, and population | |
$census = [ | |
['New York', 'NY', 8175133], | |
['Los Angeles', 'CA', 3792621], | |
['Chicago', 'IL', 2695598], | |
['Houston', 'TX', 2100263], | |
['Philadelphia', 'PA', 1526006], | |
['Phoenix', 'AZ', 1445632], | |
['San Antonio', 'TX', 1327407], | |
['San Diego', 'CA', 1307402], | |
['Dallas', 'TX', 1197816], | |
['San Jose', 'CA', 945942] | |
]; | |
$total = 0; | |
$state_totals = array(); | |
foreach ($census as $city_info) { | |
// Update the total population | |
$total += $city_info[2]; | |
// If we haven't seen this state yet, initialize its population total to 0 | |
if (!array_key_exists($city_info[1], $state_totals)) { | |
$state_totals[$city_info[1]] = 0; | |
} | |
// Update the per-state population | |
$state_totals[$city_info[1]] += $city_info[2]; | |
print "<tr><td>$city_info[0], $city_info[1]</td><td>$city_info[2]</td></tr>\n"; | |
} | |
print "<tr><td>Total</td><td>$total</td></tr>\n"; | |
// Print the per-state totals | |
foreach ($state_totals as $state => $population) { | |
print "<tr><td>$state</td><td>$population</td></tr>\n"; | |
} | |
print "</table>"; | |
// Question-4 | |
// 4. For each of the following kinds of information, | |
// state how you would store it in an array and then give sample code that creates such an array with a few elements. | |
// For example, for the first item, you might say, “An associative array whose key is the student’s name | |
// and whose value is an associative array of grade and ID number,” as in the following: | |
$students = [ | |
'James D. McCawley' => ['grade' => 'A+', 'id' => 271231], | |
'Buwei Yang Chao' => ['grade' => 'A', 'id' => 818211] | |
]; | |
// Answer-4 | |
// a. The grades and ID numbers of students in a class | |
/* The grades and ID numbers of students in a class: | |
An associative array whose key is the student's name and whose value is an associative array of grade and ID number | |
*/ | |
$students = [ | |
'James D. McCawley' => [ 'grade' => 'A+','id' => 271231 ], | |
'Buwei Yang Chao' => [ 'grade' => 'A', 'id' => 818211] | |
]; | |
// b. How many of each item in a store inventory are in stock | |
/* How many of each item in a store inventory are in stock: | |
An associative array whose key is the item name and whose value is the number in stock | |
*/ | |
$inventory = [ 'Wok' => 5, 'Steamer' => 3, 'Heavy Cleaver' => 3, 'Light Cleaver' => 0 ]; | |
// c. School lunches for a week: the different parts of each meal (entrée, side dish, drink, etc.) and the cost for each day | |
/* School lunches for a week — the different parts of each meal (entree, side dish, drink, etc.) and the cost for each day: | |
An associative array whose key is the day and whose value is an associative array describing the meal. | |
This associative array has a key/value pair for cost and a key/value pair for each part of the meal. | |
*/ | |
$lunches = [ | |
'Monday' => [ | |
'cost' => 1.50, | |
'entree' => 'Beef Shu-Mai', | |
'side' => 'Salty Fried Cake', | |
'drink' => 'Black Tea' | |
], | |
'Tuesday' => [ | |
'cost' => 2.50, | |
'entree' => 'Clear-steamed Fish', | |
'side' => 'Turnip Cake', | |
'drink' => 'Bubble Tea' | |
], | |
'Wednesday' => [ | |
'cost' => 2.00, | |
'entree' => 'Braised Sea Cucumber', | |
'side' => 'Turnip Cake', | |
'drink' => 'Green Tea' | |
], | |
'Thursday' => [ | |
'cost' => 1.35, | |
'entree' => 'Stir-fried Two Winters', | |
'side' => 'Egg Puff', | |
'drink' => 'Black Tea' | |
], | |
'Friday' => [ | |
'cost' => 3.25, | |
'entree' => 'Stewed Pork with Taro', | |
'side' => 'Duck Feet', | |
'drink' => 'Jasmine Tea' | |
] | |
]; | |
// d. The names of people in your family | |
/* The names of people in your family: | |
A numeric array whose indices are implicit and whose values are the names of family members | |
*/ | |
$family = [ 'Bart', 'Lisa', 'Homer', 'Marge', 'Maggie' ]; | |
// e. The names, ages, and relationship to you of people in your family | |
/* The names, ages, and relationship to you of people in your family: | |
An associative array whose keys are the names of family members and whose | |
values are associative arrays with age and relationship key/value pairs | |
*/ | |
$family = [ | |
'Bart' => [ | |
'age' => 10, | |
'relation' => 'brother' | |
], | |
'Lisa' => [ | |
'age' => 7, | |
'relation' => 'sister' | |
], | |
'Homer' => [ | |
'age' => 36, | |
'relation' => 'father' | |
], | |
'Marge' => [ | |
'age' => 34, | |
'relation' => 'mother' | |
], | |
'Maggie' => [ | |
'age' => 1, | |
'relation' => 'self' | |
] | |
]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter-5 | |
// Question-1 | |
// 1. Write a function to return an HTML <img /> tag. | |
// The function should accept a mandatory argument of the image URL and optional arguments for alt text, height, and width. | |
// Answer-1 | |
function html_img($url, $alt = null, $height = null, $width = null) | |
{ | |
$html = '<img src="' . $url . '"'; | |
if (isset($alt)) { | |
$html .= ' alt="' . $alt . '"'; | |
} | |
if (isset($height)) { | |
$html .= ' height="' . $height . '"'; | |
} | |
if (isset($width)) { | |
$html .= ' width="' . $width . '"'; | |
} | |
$html .= '/>'; | |
return $html; | |
} | |
// Question-2 | |
// 2. Modify the function in the previous exercise so that only the filename is passed to the function in the URL argument. | |
// Inside the function, prepend a global variable to the filename to make the full URL. | |
// For example, if you pass photo.png to the function, and the global variable contains /images/, | |
// then the src attribute of the returned <img> tag would be /images/photo.png. | |
// A function like this is an easy way to keep your image tags correct, even if the images move to a new path or server. | |
// Just change the global variable—for example, from /images/ to http://images.example.com/. | |
// Answer-2 | |
function html_img2($file, $alt = null, $height = null, $width = null) | |
{ | |
if (isset($GLOBALS['image_path'])) { | |
$file = $GLOBALS['image_path'] . $file; | |
} | |
$html = '<img src="' . $file . '"'; | |
if (isset($alt)) { | |
$html .= ' alt="' . $alt . '"'; | |
} | |
if (isset($height)) { | |
$html .= ' height="' . $height . '"'; | |
} | |
if (isset($width)) { | |
$html .= ' width="' . $width . '"'; | |
} | |
$html .= '/>'; | |
return $html; | |
} | |
// Question-3 | |
// 3. Put your function from the previous exercise in one file. | |
// Then make another file that loads the first file and uses it to print out some <img /> tags. | |
// Answer-3 | |
// The html_img2() function from the previous exercise is saved in this file | |
include "html-img2.php"; | |
$image_path = '/images/'; | |
print html_img2('puppy.png'); | |
print html_img2('kitten.png', 'fuzzy'); | |
print html_img2('dragon.png', null, 640, 480); | |
// Question-4 | |
// 4. What does the following code print out? ?> | |
<?php | |
function restaurant_check($meal, $tax, $tip) | |
{ | |
$tax_amount = $meal * ($tax / 100); | |
$tip_amount = $meal * ($tip / 100); | |
return $meal + $tax_amount + $tip_amount; | |
} | |
$cash_on_hand = 31; | |
$meal = 25; | |
$tax = 10; | |
$tip = 10; | |
while (($cost = restaurant_check($meal, $tax, $tip)) < $cash_on_hand) { | |
$tip++; | |
print "I can afford a tip of $tip% ($cost)\n"; | |
} | |
?><?php | |
// Answer-4 | |
// I can afford a tip of 11% (30) | |
// I can afford a tip of 12% (30.25) | |
// I can afford a tip of 13% (30.5) | |
// I can afford a tip of 14% (30.75) | |
// Question-5 | |
// 5. Web colors such as #ffffff and #cc3399 are made by concatenating the hexadecimal color values for red, green, and blue. | |
// Write a function that accepts decimal red, green, and blue arguments and returns a string containing | |
// the appropriate color for use in a web page. For example, if the arguments are 255, 0, and 255, | |
// then the returned string should be #ff00ff. You may find it helpful to use the built-in function dechex(), | |
// which is documented at http://www.php.net/dechex. | |
// Answer-5 | |
/* Using dechex(): */ | |
function web_color1($red, $green, $blue) | |
{ | |
$hex = [dechex($red), dechex($green), dechex($blue)]; | |
// Prepend a leading 0 if necessary to 1-digit hex values | |
foreach ($hex as $i => $val) { | |
if (strlen($i) == 1) { | |
$hex[$i] = "0$val"; | |
} | |
} | |
return '#' . implode( | |
'' | |
, | |
$hex | |
); | |
} | |
/* You can also rely on sprintf()'s %x format character to do hex-to-decimal conversion: */ | |
function web_color2($red, $green, $blue) | |
{ | |
return sprintf('#%02x%02x%02x', $red, $green, $blue); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The PricedEntree class referencing that namespace: | |
class PricedEntree extends Entree { | |
public function __construct($name, $ingredients) { | |
parent::__construct($name, $ingredients); | |
foreach ($this->ingredients as $ingredient) { | |
if (! $ingredient instanceof \Meals\Ingredient) { | |
throw new Exception('Elements of $ingredients must be Ingredient objects'); | |
} | |
} | |
} | |
public function getCost() { | |
$cost = 0; | |
foreach ($this->ingredients as $ingredient) { | |
$cost += $ingredient->getCost(); | |
} | |
return $cost; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter-7: Exercises | |
// Question-1 | |
// 1. What does $_POST look like when the following form is submitted with the third option in the Braised Noodles menu selected, | |
// the first and last options in the Sweet menu selected, and 4 entered into the text box? ?> | |
<form method="POST" action="order.php"> | |
Braised Noodles with: <select name="noodle"> | |
<option>crab meat</option> | |
Chapter Summary | 153 | |
<option>mushroom</option> | |
<option>barbecued pork</option> | |
<option>shredded ginger and green onion</option> | |
</select> | |
<br /> | |
Sweet: <select name="sweet[]" multiple> | |
<option value="puff"> Sesame Seed Puff | |
<option value="square"> Coconut Milk Gelatin Square | |
<option value="cake"> Brown Sugar Cake | |
<option value="ricemeat"> Sweet Rice and Meat | |
</select> | |
<br /> | |
Sweet Quantity: <input type="text" name="sweet_q"> | |
<br /> | |
<input type="submit" name="submit" value="Order"> | |
</form><?php | |
// Answer-1 | |
$_POST['noodle'] = 'barbecued pork'; | |
$_POST['sweet'] = ['puff', 'ricemeat']; | |
$_POST['sweet_q'] = '4'; | |
$_POST['submit'] = 'Order'; | |
// Question-2 | |
// 2. Write a process_form() function that prints out all submitted form parameters and their values. | |
// You can assume that form parameters have only scalar values. | |
// Answer-2 | |
// Since this is operating on form data, it looks directly at $_POST instead of a validated $input array | |
function process_form() | |
{ | |
print '<ul>'; | |
foreach ($_POST as $k => $v) { | |
print '<li>' . htmlentities($k) . '=' . htmlentities($v) . '</li>'; | |
} | |
print '</ul>'; | |
} | |
// Question-3 | |
// 3. Write a program that does basic arithmetic. | |
// Display a form with text box inputs for two operands and a <select> menu to choose an operation: addition, subtraction, multiplication, or division. | |
// Validate the inputs to make sure that they are numeric and appropriate for the chosen operation. | |
// The processing function should display the operands, the operator, and the result. | |
// For example, if the operands are 4 and 2 and the operation is multiplication, | |
// the processing function should display something like 4 * 2 = 8. | |
// Answer-3 | |
// This assumes FormHelper.php is in the same directory as this file. | |
require 'FormHelper.php'; | |
// Set up the arrays of choices in the select menu. | |
// This is needed in display_form(), validate_form(), and process_form(), so it is declared in the global scope. | |
$ops = array('+', '-', '*', '/'); | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form($input); | |
// And then show the form again to do another calculation | |
show_form(); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form(); | |
} | |
function show_form($errors = array()) | |
{ | |
$defaults = array( | |
'num1' => 2, | |
'op' => 2, // the index of '*' in $ops | |
'num2' => 8 | |
); | |
// Set up the $form object with proper defaults | |
$form = new FormHelper($defaults); | |
// All the HTML and form display is in a separate file for clarity | |
include 'math-form.php'; | |
} | |
function validate_form() | |
{ | |
$input = array(); | |
$errors = array(); | |
// op is required | |
$input['op'] = $GLOBALS['ops'][$_POST['op']] ?? ''; | |
if (!in_array($input['op'], $GLOBALS['ops'])) { | |
$errors[] = 'Please select a valid operation.'; | |
} | |
// num1 and num2 must be numbers | |
$input['num1'] = filter_input(INPUT_POST, 'num1', FILTER_VALIDATE_FLOAT); | |
if (is_null($input['num1']) || ($input['num1'] === false)) { | |
$errors[] = 'Please enter a valid first number.'; | |
} | |
$input['num2'] = filter_input(INPUT_POST, 'num2', FILTER_VALIDATE_FLOAT); | |
if (is_null($input['num2']) || ($input['num2'] === false)) { | |
$errors[] = 'Please enter a valid second number.'; | |
} | |
// Can't divide by zero | |
if (($input['op'] == '/') && ($input['num2'] == 0)) { | |
$errors[] = 'Division by zero is not allowed.'; | |
} | |
return array($errors, $input); | |
} | |
function process_form2($input) | |
{ | |
$result = 0; | |
if ($input['op'] == '+') { | |
$result = $input['num1'] + $input['num2']; | |
} else if ($input['op'] == '-') { | |
$result = $input['num1'] - $input['num2']; | |
} else if ($input['op'] == '*') { | |
$result = $input['num1'] * $input['num2']; | |
} else if ($input['op'] == '/') { | |
$result = $input['num1'] / $input['num2']; | |
} | |
$message = | |
"{$input['num1']} {$input['op']} {$input['num2']} = $result"; | |
print "<h3>$message</h3>"; | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The mathform.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<td>First Number:</td> | |
<td><?= $form->input('text', ['name' => 'num1']) ?></td> | |
</tr> | |
<tr> | |
<td>Operation:</td> | |
<td><?= $form->select($GLOBALS['ops'], ['name' => 'op']) ?></td> | |
</tr> | |
<tr> | |
<td>Second Number:</td> | |
<td><?= $form->input('text', ['name' => 'num2']) ?></td> | |
</tr> | |
<tr> | |
<td colspan="2" align="center"><?= $form->input( | |
'submit', | |
['value' => 'Calculate'] | |
) ?> | |
</td> | |
</tr> | |
</table><?php | |
// Question-4 | |
// 4. Write a program that displays, validates, and processes a form for entering information about a package to be shipped. | |
// The form should contain inputs for the from and to addresses for the package, dimensions of the package, and weight of the package. | |
// The validation should check (at least) that the package weighs no more than 150 pounds and that no dimension of the package is more than 36 inches. | |
// You can assume that the addresses entered on the form are both US addresses, | |
// but you should check that a valid state and a zip code with valid syntax are entered. | |
// The processing function in your program should print out the information about the package in an organized, formatted report. | |
// Answer-4 | |
// This assumes FormHelper.php is in the same directory as this file. | |
require 'FormHelper.php'; | |
// Set up the array of choices in the select menu. | |
// This is needed in display_form(), validate_form(), | |
// and process_form(), so it is declared in the global scope. | |
$states = [ 'AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA', | |
'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', | |
'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', | |
'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', | |
'WY' ]; | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form2($input); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form(); | |
} | |
function show_form2($errors = array()) | |
{ | |
// Set up the $form object with proper defaults | |
$form = new FormHelper(); | |
// All the HTML and form display is in a separate file for clarity | |
include 'shipping-form.php'; | |
} | |
function validate_form2() | |
{ | |
$input = array(); | |
$errors = array(); | |
foreach (['from', 'to'] as $addr) { | |
// Check required fields | |
foreach (['Name' => 'name', 'Address 1' => 'address1', 'City' => 'city', 'State' => 'state'] as $label => $field) { | |
$input[$addr . '_' . $field] = $_POST[$addr . '_' . $field] ?? ''; | |
if (strlen($input[$addr . '_' . $field]) == 0) { | |
$errors[] = "Please enter a value for $addr $label."; | |
} | |
} | |
// Check state | |
$input[$addr . '_state'] = | |
$GLOBALS['states'][$input[$addr . '_state']] ?? ''; | |
if (!in_array($input[$addr . '_state'], $GLOBALS['states'])) { | |
$errors[] = "Please select a valid $addr state."; | |
} | |
// Check zip code | |
$input[$addr . '_zip'] = filter_input( | |
INPUT_POST, | |
$addr . '_zip', | |
FILTER_VALIDATE_INT, | |
[ | |
'options' => [ | |
'min_range' => 10000, | |
'max_range' => 99999 | |
] | |
] | |
); | |
if (is_null($input[$addr . '_zip']) || ($input[$addr . '_zip'] === false)) { | |
$errors[] = "Please enter a valid $addr ZIP"; | |
} | |
// Don't forget about address2! | |
$input[$addr . '_address2'] = $_POST[$addr . '_address2'] ?? ''; | |
} | |
// height, width, depth, weight must all be numbers > 0 | |
foreach (['height', 'width', 'depth', 'weight'] as $field) { | |
$input[$field] = filter_input(INPUT_POST, $field, FILTER_VALIDATE_FLOAT); | |
// Since 0 is not valid, we can just test for truth rather than | |
// null or exactly false | |
if (!($input[$field] && ($input[$field] > 0))) { | |
$errors[] = "Please enter a valid $field."; | |
} | |
} | |
// Check weight | |
if ($input['weight'] > 150) { | |
$errors[] = "The package must weigh no more than 150 lbs."; | |
} | |
// Check dimensions | |
foreach (['height', 'width', 'depth'] as $dim) { | |
if ($input[$dim] > 36) { | |
$errors[] = "The package $dim must be no more than 36 inches."; | |
} | |
} | |
return array($errors, $input); | |
} | |
function process_form3($input) | |
{ | |
// Make a template for the report | |
$tpl = <<<HTML | |
<p>Your package is {height}" x {width}" x {depth}" and weighs {weight} lbs.</p> | |
<p>It is coming from:</p> | |
<pre> | |
{from_name} | |
{from_address} | |
{from_city}, {from_state} {from_zip} | |
</pre> | |
<p>It is going to:</p> | |
<pre> | |
{to_name} | |
{to_address} | |
{to_city}, {to_state} {to_zip} | |
</pre> | |
HTML; | |
// Adjust addresses in $input for easier output | |
foreach (['from', 'to'] as $addr) { | |
$input[$addr . '_address'] = $input[$addr . '_address1']; | |
if (strlen($input[$addr . '_address2'])) { | |
$input[$addr . '_address'] .= "\n" . $input[$addr . '_address2']; | |
} | |
} | |
// Replace each template variable with the corresponding value | |
// in $input | |
$html = $tpl; | |
foreach ($input as $k => $v) { | |
$html = str_replace('{' . $k . '}', $v, $html); | |
} | |
// Print the report | |
print $html; | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The shipping-form.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<th>From:</th> | |
<td></td> | |
</tr> | |
<tr> | |
<td>Name:</td> | |
<td><?= $form->input('text', ['name' => 'from_name']) ?></td> | |
</tr> | |
<tr> | |
<td>Address 1:</td> | |
<td><?= $form->input('text', ['name' => 'from_address1']) ?></td> | |
</tr> | |
<tr> | |
<td>Address 2:</td> | |
<td><?= $form->input('text', ['name' => 'from_address2']) ?></td> | |
</tr> | |
<tr> | |
<td>City:</td> | |
<td><?= $form->input('text', ['name' => 'from_city']) ?></td> | |
</tr> | |
<tr> | |
<td>State:</td> | |
<td><?= $form->select($GLOBALS['states'], ['name' => 'from_state']) ?> | |
</td> | |
</tr> | |
<tr> | |
<td>ZIP:</td> | |
<td><?= $form->input('text', ['name' => 'from_zip', 'size' => 5]) ?> | |
</td> | |
</tr> | |
<tr> | |
<th>To:</th> | |
<td></td> | |
</tr> | |
<tr> | |
<td>Name:</td> | |
<td><?= $form->input('text', ['name' => 'to_name']) ?></td> | |
</tr> | |
<tr> | |
<td>Address 1:</td> | |
<td><?= $form->input('text', ['name' => 'to_address1']) ?></td> | |
</tr> | |
<tr> | |
<td>Address 2:</td> | |
<td><?= $form->input('text', ['name' => 'to_address2']) ?></td> | |
</tr> | |
<tr> | |
<td>City:</td> | |
<td><?= $form->input('text', ['name' => 'to_city']) ?></td> | |
</tr> | |
<tr> | |
<td>State:</td> | |
<td><?= $form->select($GLOBALS['states'], ['name' => 'to_state']) ?> | |
</td> | |
</tr> | |
<tr> | |
<td>ZIP:</td> | |
<td><?= $form->input('text', ['name' => 'to_zip', 'size' => 5]) ?> | |
</td> | |
</tr> | |
<tr> | |
<th>Package:</th> | |
<td></td> | |
</tr> | |
<tr> | |
<td>Weight:</td> | |
<td><?= $form->input('text', ['name' => 'weight']) ?></td> | |
</tr> | |
<tr> | |
<td>Height:</td> | |
<td><?= $form->input('text', ['name' => 'height']) ?></td> | |
</tr> | |
<tr> | |
<td>Width:</td> | |
<td><?= $form->input('text', ['name' => 'width']) ?></td> | |
</tr> | |
<tr> | |
<td>Depth:</td> | |
<td><?= $form->input('text', ['name' => 'depth']) ?></td> | |
</tr> | |
<tr> | |
<td colspan="2" align="center"> | |
<?= $form->input('submit', ['value' => 'Ship!']) ?> | |
</td> | |
</tr> | |
</table> | |
</form><?php | |
// Question-5 | |
// 5. (Optional) Modify your process_form() function that enumerates all submitted form parameters | |
// and their values so that it correctly handles submitted form parameters that have array values. | |
// Remember, those array values could themselves contain arrays. | |
// Answer-5 | |
function print_array($ar) | |
{ | |
print '<ul>'; | |
foreach ($ar as $k => $v) { | |
if (is_array($v)) { | |
print '<li>' . htmlentities($k) . ':</li>'; | |
print_array($v); | |
} else { | |
print '<li>' . htmlentities($k) . '=' . htmlentities($v) . '</li>'; | |
} | |
} | |
print '</ul>'; | |
} | |
/* Since this is operating on form data, it looks directly at $_POST | |
instead of a validated $input array */ | |
function process_form4() | |
{ | |
print_array($_POST); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter-8: Exercises | |
// The following exercises use a database table called dishes with the following structure: | |
// -- CREATE TABLE dishes ( | |
// -- dish_id INT, | |
// -- dish_name VARCHAR(255), | |
// -- price DECIMAL(4,2), | |
// -- is_spicy INT | |
// -- ) | |
// Here is some sample data to put into the dishes table: | |
// -- INSERT INTO dishes VALUES (1,'Walnut Bun',1.00,0) | |
// -- INSERT INTO dishes VALUES (2,'Cashew Nuts and White Mushrooms',4.95,0) | |
// -- INSERT INTO dishes VALUES (3,'Dried Mulberries',3.00,0) | |
// -- INSERT INTO dishes VALUES (4,'Eggplant with Chili Sauce',6.50,1) | |
// -- INSERT INTO dishes VALUES (5,'Red Bean Bun',1.00,0) | |
// -- INSERT INTO dishes VALUES (6,'General Tso''s Chicken',5.50,1) | |
// Question-1 | |
// 1. Write a program that lists all of the dishes in the table, sorted by price. | |
// Answer-1 | |
try { | |
// Connect | |
$db = new PDO('sqlite:/tmp/restaurant.db'); | |
// Set up exceptions on DB errors | |
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
$stmt = $db->query('SELECT * FROM dishes ORDER BY price'); | |
$dishes = $stmt->fetchAll(); | |
if (count($dishes) == 0) { | |
$html = '<p>No dishes to display</p>'; | |
} else { | |
$html = "<table>\n"; | |
$html .= "<tr><th>Dish Name</th><th>Price</th><th>Spicy?</th></tr>\n"; | |
foreach ($dishes as $dish) { | |
$html .= '<tr><td>' . | |
htmlentities($dish['dish_name']) . '</td><td>$' . | |
sprintf('%.02f', $dish['price']) . '</td><td>' . | |
($dish['is_spicy'] ? 'Yes' : 'No') . "</td></tr>\n"; | |
} | |
$html .= "</table>"; | |
} | |
} catch (PDOException $e) { | |
$html = "Can't show dishes: " . $e->getMessage(); | |
} | |
print $html; | |
// Question-2 | |
// 2. Write a program that displays a form asking for a price. When the form is submitted, | |
// the program should print out the names and prices of the dishes whose price is at least the submitted price. | |
// Don’t retrieve from the database any rows or columns that aren’t printed in the table. | |
// Answer-2 | |
// Load the form helper class | |
require 'FormHelper.php'; | |
// Connect to the database | |
try { | |
$db = new PDO('sqlite:/tmp/restaurant.db'); | |
} catch (PDOException $e) { | |
print "Can't connect: " . $e->getMessage(); | |
exit(); | |
} | |
// Set up exceptions on DB errors | |
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
// Set up fetch mode: rows as objects | |
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form($input); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form(); | |
} | |
function show_form($errors = array()) | |
{ | |
// Set up the $form object with proper defaults | |
$form = new FormHelper(); | |
// All the HTML and form display is in a separate file for clarity | |
include 'price-form.php'; | |
} | |
function validate_form() | |
{ | |
$input = array(); | |
$errors = array(); | |
// Minimum price must be a valid floating-point number | |
$input['min_price'] = filter_input( | |
INPUT_POST, | |
'min_price', | |
FILTER_VALIDATE_FLOAT | |
); | |
if ($input['min_price'] === null || $input['min_price'] === false) { | |
$errors[] = 'Please enter a valid minimum price.'; | |
} | |
return array($errors, $input); | |
} | |
function process_form($input) | |
{ | |
// Access the global variable $db inside this function | |
global $db; | |
// Build up the query | |
$sql = 'SELECT dish_name, price, is_spicy FROM dishes WHERE | |
price >= ?'; | |
// Send the query to the database program and get all the rows back | |
$stmt = $db->prepare($sql); | |
$stmt->execute(array($input['min_price'])); | |
$dishes = $stmt->fetchAll(); | |
if (count($dishes) == 0) { | |
print 'No dishes matched.'; | |
} else { | |
print '<table>'; | |
print '<tr><th>Dish Name</th><th>Price</th><th>Spicy?</th></tr>'; | |
foreach ($dishes as $dish) { | |
if ($dish->is_spicy == 1) { | |
$spicy = 'Yes'; | |
} else { | |
$spicy = 'No'; | |
} | |
} | |
printf( | |
'<tr><td>%s</td><td>$%.02f</td><td>%s</td></tr>', | |
htmlentities($dish->dish_name), | |
$dish->price, | |
$spicy | |
); | |
print '</table>'; | |
} | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The price-form.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<td>Minimum Price:</td> | |
<td><?= $form->input('text', ['name' => 'min_price']) ?></td> | |
</tr> | |
<tr> | |
<td colspan="2" align="center"> | |
<?= $form->input('submit', [ | |
'name' => 'search', | |
'value' => 'Search' | |
]) ?> | |
</td> | |
</tr> | |
</table> | |
</form><?php | |
// Question-3 | |
// 3. Write a program that displays a form with a <select> menu of dish names. | |
// Create the dish names to display by retrieving them from the database. | |
// When the form is submitted, the program should print out all of the information in the table (ID, name, price, and spiciness) for the selected dish. | |
// Answer-3 | |
// Load the form helper class | |
require 'FormHelper.php'; | |
// Connect to the database | |
try { | |
$db = new PDO('sqlite:/tmp/restaurant.db'); | |
} catch (PDOException $e) { | |
print "Can't connect: " . $e->getMessage(); | |
exit(); | |
} | |
// Set up exceptions on DB errors | |
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
// Set up fetch mode: rows as objects | |
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form($input); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form(); | |
} | |
function show_form2($errors = array()) | |
{ | |
global $db; | |
// Set up the $form object with proper defaults | |
$form = new FormHelper(); | |
// Retrieve the list of dish names to use from the database | |
$sql = 'SELECT dish_id, dish_name FROM dishes ORDER BY dish_name'; | |
$stmt = $db->query($sql); | |
$dishes = array(); | |
while ($row = $stmt->fetch()) { | |
$dishes[$row->dish_id] = $row->dish_name; | |
} | |
// All the HTML and form display is in a separate file for clarity | |
include 'dish-form.php'; | |
} | |
function validate_form2() | |
{ | |
$input = array(); | |
$errors = array(); | |
// As long as some dish_id value is submitted, we'll consider it OK. | |
// If it doesn't match any dishes in the database, process_form() | |
// can report that. | |
if (isset($_POST['dish_id'])) { | |
$input['dish_id'] = $_POST['dish_id']; | |
} else { | |
$errors[] = 'Please select a dish.'; | |
} | |
return array($errors, $input); | |
} | |
function process_form2($input) | |
{ | |
// Access the global variable $db inside this function | |
global $db; | |
// Build up the query | |
$sql = 'SELECT dish_id, dish_name, price, is_spicy FROM dishes WHERE | |
dish_id = ?'; | |
// Send the query to the database program and get all the rows back | |
$stmt = $db->prepare($sql); | |
$stmt->execute(array($input['dish_id'])); | |
$dish = $stmt->fetch(); | |
if (count($dish) == 0) { | |
print 'No dishes matched.'; | |
} else { | |
print '<table>'; | |
print '<tr><th>ID</th><th>Dish Name</th><th>Price</th>'; | |
print '<th>Spicy?</th></tr>'; | |
if ($dish->is_spicy == 1) { | |
$spicy = 'Yes'; | |
} else { | |
$spicy = 'No'; | |
} | |
printf( | |
'<tr><td>%d</td><td>%s</td><td>$%.02f</td><td>%s</td></tr>', | |
$dish->dish_id, | |
htmlentities($dish->dish_name), | |
$dish->price, | |
$spicy | |
); | |
print '</table>'; | |
} | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The dish-form.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<td>Dish:</td> | |
<td><?= $form->select($dishes, ['name' => 'dish_id']) ?></td> | |
</tr> | |
<tr> | |
<td colspan="2" align="center"> | |
<?= $form->input('submit', [ | |
'name' => 'info', | |
'value' => 'Get Dish Info' | |
]) ?> | |
</td> | |
</tr> | |
</table> | |
<?php | |
// Question-4 | |
// 4. Create a new table that holds information about restaurant customers. | |
// The table should store the following information about each customer: customer ID, name, phone number, | |
// and the ID of the customer’s favorite dish. Write a program that displays a form for putting a new customer into the table. | |
// The part of the form for entering the customer’s favorite dish should be a <select> menu of dish names. | |
// The customer’s ID should be generated by your program, not entered in the form. | |
// Answer-4 | |
// Load the form helper class | |
require 'FormHelper.php'; | |
// Connect to the database | |
try { | |
$db = new PDO('sqlite:/tmp/restaurant.db'); | |
} catch (PDOException $e) { | |
print "Can't connect: " . $e->getMessage(); | |
exit(); | |
} | |
// Set up exceptions on DB errors | |
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
// Set up fetch mode: rows as objects | |
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); | |
// Put the list of dish IDs and names in a global array because | |
// we'll need it in show_form() and validate_form() | |
$dishes = array(); | |
$sql = 'SELECT dish_id, dish_name FROM dishes ORDER BY dish_name'; | |
$stmt = $db->query($sql); | |
while ($row = $stmt->fetch()) { | |
$dishes[$row->dish_id] = $row->dish_name; | |
} | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form($input); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form(); | |
} | |
function show_form3($errors = array()) | |
{ | |
global $db, $dishes; | |
// Set up the $form object with proper defaults | |
$form = new FormHelper(); | |
// All the HTML and form display is in a separate file for clarity | |
include 'customer-form.php'; | |
} | |
function validate_form3() | |
{ | |
global $dishes; | |
$input = array(); | |
$errors = array(); | |
// Make sure a dish_id valid is submitted and in $dishes. | |
// As long as some dish_id value is submitted, we'll consider it OK. | |
// If it doesn't match any dishes in the database, process_form() | |
// can report that. | |
$input['dish_id'] = $_POST['dish_id'] ?? ''; | |
if (!array_key_exists($input['dish_id'], $dishes)) { | |
$errors[] = 'Please select a valid dish.'; | |
} | |
// Name is required | |
$input['name'] = trim($_POST['name'] ?? ''); | |
if (0 == strlen($input['name'])) { | |
$errors[] = 'Please enter a name.'; | |
} | |
// Phone number is required | |
$input['phone'] = trim($_POST['phone'] ?? ''); | |
if (0 == strlen($input['phone'])) { | |
$errors[] = 'Please enter a phone number.'; | |
} else { | |
// Be US-centric and ensure that the phone number contains | |
// at least 10 digits. Using ctype_digit() on each | |
// character is not the most efficient way to do this, | |
// but is logically straightforward and avoids | |
// regular expressions. | |
$digits = 0; | |
for ($i = 0; $i < strlen($input['phone']); $i++) { | |
if (ctype_digit($input['phone'][$i])) { | |
$digits++; | |
} | |
} | |
if ($digits < 10) { | |
$errors[] = 'Phone number needs at least ten digits.'; | |
} | |
} | |
return array($errors, $input); | |
} | |
function process_form4($input) | |
{ | |
// Access the global variable $db inside this function | |
global $db; | |
// Build up the query. No need to specify customer_id because | |
// the database will automatically assign a unique one. | |
$sql = 'INSERT INTO customers (name,phone,favorite_dish_id) ' . | |
'VALUES (?,?,?)'; | |
// Send the query to the database program and get all the rows back | |
try { | |
$stmt = $db->prepare($sql); | |
$stmt->execute(array($input['name'], $input['phone'], $input['dish_id'])); | |
print '<p>Inserted new customer.</p>'; | |
} catch (Exception $e) { | |
print "<p>Couldn't insert customer: {$e->getMessage()}.</p>"; | |
} | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The customer-form.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<tr> | |
<td>Name:</td> | |
<td><?= $form->input('text', ['name' => 'name']) ?> | |
</td> | |
</tr> | |
<tr> | |
<td>Phone Number:</td> | |
<td><?= $form->input('text', ['name' => 'phone']) ?></td> | |
</tr> | |
<tr> | |
<td>Favorite Dish:</td> | |
<td><?= $form->select($dishes, ['name' => 'dish_id']) ?></td> | |
</tr> | |
<tr> | |
<td colspan="2" align="center"> | |
<?= $form->input('submit', ['name' => 'add', 'value' => 'Add Customer']) ?> | |
</td> | |
</tr> | |
</table> | |
</form> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter-10: Exercises | |
// Question-1 | |
// 1. Make a web page that uses a cookie to keep track of how many times a user has viewed the page. | |
// The first time a particular user looks at the page, it should print something like “Number of views: 1.” | |
// The second time the user looks at the page, it should print “Number of views: 2,” and so on. | |
// Answer-1 | |
$view_count = 1 + ($_COOKIE['view_count'] ?? 0); | |
setcookie('view_count', $view_count); | |
print "<p>Hi! Number of times you've viewed this page: $view_count.</p>"; | |
// Question-2 | |
// 2. Modify the web page from the first exercise so that it prints out a special message on the 5th, 10th, | |
// and 15th times the user looks at the page. Also modify it so that on the 20th time the user looks at the page, | |
// it deletes the cookie and the page count starts over. | |
// Answer-2 | |
$view_count = 1 + ($_COOKIE['view_count'] ?? 0); | |
if ($view_count == 20) { | |
// An empty value for setcookie() removes the cookie | |
setcookie( | |
'view_count', | |
'' | |
); | |
$msg = "<p>Time to start over.</p>"; | |
} else { | |
setcookie('view_count', $view_count); | |
$msg = "<p>Hi! Number of times you've viewed this page: $view_count.</p>"; | |
if ($view_count == 5) { | |
$msg .= "<p>This is your fifth visit.</p>"; | |
} elseif ($view_count == 10) { | |
$msg .= "<p>This is your tenth visit. You must like this page.</p>"; | |
} elseif ($view_count == 15) { | |
$msg .= "<p>This is your fifteenth visit. " . | |
"Don't you have anything else to do?</p>"; | |
} | |
} | |
print $msg; | |
// Question-3 | |
// 3. Write a PHP program that displays a form for a user to pick his favorite color from a list of colors. | |
// Make another page whose background color is set to the color that the user picks in the form. | |
// Store the color value in $_SESSION so that both pages can access it. | |
// Answer-3 | |
// The color-picking page: | |
// Start sessions first thing so we can use $_SESSION freely later | |
session_start(); | |
// Load the form helper class | |
require 'FormHelper.php'; | |
$colors = array( | |
'ff0000' => 'Red', | |
'ffa500' => 'Orange', | |
'ffffff' => 'Yellow', | |
'008000' => 'Green', | |
'0000ff' => 'Blue', | |
'4b0082' => 'Indigo', | |
'663399' => 'Rebecca Purple' | |
); | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form($input); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form(); | |
} | |
function show_form($errors = array()) | |
{ | |
global $colors; | |
// Set up the $form object with proper defaults | |
$form = new FormHelper(); | |
// All the HTML and form display is in a separate file for clarity | |
include 'color-form.php'; | |
} | |
function validate_form() | |
{ | |
$input = array(); | |
$errors = array(); | |
// color must be a valid color | |
$input['color'] = $_POST['color'] ?? ''; | |
if (!array_key_exists($input['color'], $GLOBALS['colors'])) { | |
$errors[] = 'Please select a valid color.'; | |
} | |
return array($errors, $input); | |
} | |
function process_form($input) | |
{ | |
global $colors; | |
$_SESSION['background_color'] = $input['color']; | |
print '<p>Your color has been set.</p>'; | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The color-form.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<td>Favorite Color:</td> | |
<td><?= $form->select($colors, ['name' => 'color']) ?></td> | |
</tr> | |
<tr> | |
<td colspan="2" align="center"> | |
<?= $form->input('submit', [ | |
'name' => 'set', | |
'value' => 'Set Color' | |
]) ?> | |
</td> | |
</tr> | |
</table> | |
<?php | |
// The page with background color set: | |
// Start sessions first thing so we can use $_SESSION freely later | |
session_start(); | |
?> | |
<html> | |
<head> | |
<title>Background Color Example</title> | |
<body style="background-color:<?= $_SESSION['background_color'] ?>"> | |
<p>What color did you pick?</p> | |
</body> | |
</html><?php | |
// Question-4 | |
// 4. Write a PHP program that displays an order form. The order form should list six products. | |
// Next to each product name there should be a text box into which a user can enter how many of | |
// that product she wants to order. | |
// When the form is submitted, the submitted form data should be saved into the session. | |
// Make another page that displays the contents of the saved order, a link back to the order form page, | |
// and a Check Out button. If the link back to the order form page is clicked, the order form page should be | |
// displayed with the saved order quantities from the session in the text boxes. | |
// When the Check Out button is clicked, the order should be cleared from the session. | |
// Answer-4 | |
// The ordering page: | |
session_start(); | |
// This assumes FormHelper.php is in the same directory as this file. | |
require 'FormHelper.php'; | |
// Set up the array of choices in the select menu. | |
// This is needed in display_form(), validate_form(), | |
// and process_form(), so it is declared in the global scope. | |
$products = [ | |
'cuke' => 'Braised Sea Cucumber', | |
'stomach' => "Sauteed Pig's Stomach", | |
'tripe' => 'Sauteed Tripe with Wine Sauce', | |
'taro' => 'Stewed Pork with Taro', | |
'giblets' => 'Baked Giblets with Salt', | |
'abalone' => 'Abalone with Marrow and Duck Feet' | |
]; | |
// The main page logic: | |
// - If the form is submitted, validate and then process or redisplay | |
// - If it's not submitted, display | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
// If validate_form() returns errors, pass them to show_form() | |
list($errors, $input) = validate_form2(); | |
if ($errors) { | |
show_form($errors); | |
} else { | |
// The submitted data is valid, so process it | |
process_form2($input); | |
} | |
} else { | |
// The form wasn't submitted, so display | |
show_form2(); | |
} | |
function show_form2($errors = array()) | |
{ | |
global $products; | |
$defaults = array(); | |
// Start out with 0 as a default | |
foreach ($products as $code => $label) { | |
$defaults["quantity_$code"] = 0; | |
} | |
// If quantities are in the session, use those | |
if (isset($_SESSION['quantities'])) { | |
foreach ($_SESSION['quantities'] as $field => $quantity) { | |
$defaults[$field] = $quantity; | |
} | |
} | |
$form = new FormHelper($defaults); | |
// All the HTML and form display is in a separate file for clarity | |
include 'order-form.php'; | |
} | |
function validate_form2() | |
{ | |
global $products; | |
$input = array(); | |
$errors = array(); | |
// For each quantity box, make sure the value is | |
// a valid integer >= 0 | |
foreach ($products as $code => $name) { | |
$field = "quantity_$code"; | |
$input[$field] = filter_input( | |
INPUT_POST, | |
$field, | |
FILTER_VALIDATE_INT, | |
['options' => ['min_range' => 0]] | |
); | |
if (is_null($input[$field]) || ($input[$field] === false)) { | |
$errors[] = "Please enter a valid quantity for $name."; | |
} | |
} | |
return array($errors, $input); | |
} | |
function process_form2($input) | |
{ | |
$_SESSION['quantities'] = $input; | |
print "Thank you for your order."; | |
} | |
// The code relies on the FormHelper.php file discussed in Chapter 7. | |
// The order-form.php file referenced, which displays the form HTML, contains: ?> | |
<form method="POST" action="<?= $form->encode($_SERVER['PHP_SELF']) ?>"> | |
<table> | |
<?php if ($errors) { ?> | |
<tr> | |
<td>You need to correct the following errors:</td> | |
<td> | |
<ul> | |
<?php foreach ($errors as $error) { ?> | |
<li><?= $form->encode($error) ?></li> | |
<?php } ?> | |
</ul> | |
</td> | |
<?php } ?> | |
<tr> | |
<th>Product</th> | |
<td>Quantity</td> | |
</tr> | |
<?php foreach ($products as $code => $name) { ?> | |
<tr> | |
<td><?= htmlentities($name) ?>:</td> | |
<td><?= $form->input('text', ['name' => "quantity_$code"]) ?></td> | |
</tr> | |
<?php } ?> | |
<tr> | |
<td colspan="2" align="center"><?= $form->input('submit', ['value' => 'Order']) ?> | |
</td> | |
</tr> | |
</table> | |
</form><?php | |
// The checkout page: | |
session_start(); | |
// The same products from the order page | |
$products = [ | |
'cuke' => 'Braised Sea Cucumber', | |
'stomach' => "Sauteed Pig's Stomach", | |
'tripe' => 'Sauteed Tripe with Wine Sauce', | |
'taro' => 'Stewed Pork with Taro', | |
'giblets' => 'Baked Giblets with Salt', | |
'abalone' => 'Abalone with Marrow and Duck Feet' | |
]; | |
// Simplified main page logic without form validation | |
if ($_SERVER['REQUEST_METHOD'] == 'POST') { | |
process_form3(); | |
} else { | |
// The form wasn't submitted, so display | |
show_form3(); | |
} | |
function show_form3() | |
{ | |
global $products; | |
// The "form" is just a single submit button, so we won't use | |
// FormHelper and just inline all the HTML here | |
if (isset($_SESSION['quantities']) && (count($_SESSION['quantities']) > 0)) { | |
print "<p>Your order:</p><ul>"; | |
foreach ($_SESSION['quantities'] as $field => $amount) { | |
list($junk, $code) = explode('_', $field); | |
$product = $products[$code]; | |
print "<li>$amount $product</li>"; | |
} | |
print "</ul>"; | |
print '<form method="POST" action=' . | |
htmlentities($_SERVER['PHP_SELF']) . '>'; | |
print '<input type="submit" value="Check Out" />'; | |
print '</form>'; | |
} else { | |
print "<p>You don't have a saved order.</p>"; | |
} | |
// This assumes the order form page is saved as "order.php" | |
print '<a href="order.php">Return to Order page</a>'; | |
} | |
function process_form3() | |
{ | |
// This removes the data from the session | |
unset($_SESSION['quantities']); | |
print "<p>Thanks for your order.</p>"; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Chapter-12: Exercises | |
// Question-1 | |
// 1. This program has a syntax error in it: | |
$name = 'Umberto'; | |
function say_hello() { | |
print 'Hello, '; | |
// print global $name; | |
} | |
say_hello(); | |
// Without running the program through the PHP engine, | |
// figure out what the parse error that gets printed when the engine tries to run the program looks like. | |
// What change must you make to the program to get it to run properly and print Hello, Umberto? | |
// Answer-1 | |
// The keyword global should not be in line 5, so the parse error should report that unexpected keyword. | |
// The actual parse error is: | |
// PHP Parse error: syntax error, unexpected 'global' (T_GLOBAL) in debugging-12.php on line 5 | |
// To make the program run properly, change the line print global $name; to print | |
// $GLOBALS['name'];. Or, you can add global name; as the first line of the function and then change print global $name; to print $name;. | |
// Question-2 | |
// 2. Modify the validate_form() function in your answer to Exercise 3 in Chapter 7 (see “Exercise 3” on page 345) | |
// so that it prints in the web server error log the names and values of all of the submitted form parameters. | |
// Answer-2 | |
function validate_form() | |
{ | |
$input = array(); | |
$errors = array(); | |
// turn on output buffering | |
ob_start(); | |
// dump all the submitted data | |
var_dump($_POST); | |
// capture the generated "output" | |
$output = ob_get_contents(); | |
// turn off output buffering | |
ob_end_clean(); | |
// send the variable dump to the error log | |
error_log($output); | |
// op is required | |
$input['op'] = $GLOBALS['ops'][$_POST['op']] ?? ''; | |
if (!in_array($input['op'], $GLOBALS['ops'])) { | |
$errors[] = 'Please select a valid operation.'; | |
} | |
// num1 and num2 must be numbers | |
$input['num1'] = filter_input(INPUT_POST, 'num1', FILTER_VALIDATE_FLOAT); | |
if (is_null($input['num1']) || ($input['num1'] === false)) { | |
$errors[] = 'Please enter a valid first number.'; | |
} | |
$input['num2'] = filter_input(INPUT_POST, 'num2', FILTER_VALIDATE_FLOAT); | |
if (is_null($input['num2']) || ($input['num2'] === false)) { | |
$errors[] = 'Please enter a valid second number.'; | |
} | |
// can't divide by zero | |
if (($input['op'] == '/') && ($input['num2'] == 0)) { | |
$errors[] = 'Division by zero is not allowed.'; | |
} | |
return array($errors, $input); | |
} | |
// Question-3 | |
// 3. Modify your answer to Exercise 4 in Chapter 8 (see “Exercise 4” on page 357) to use a custom database | |
// error-handling function that prints out different messages in the web browser and in the web server error log. | |
// The error-handling function should make the program exit after it prints the error messages. | |
// Answer-3 | |
// At the top of the program, this code defines an exception handler and sets it up to be called on unhandled exceptions: | |
function exceptionHandler($ex) | |
{ | |
// Log the specifics to the error log | |
error_log("ERROR: " . $ex->getMessage()); | |
// Print something less specific for users to see | |
// and exit | |
die("<p>Sorry, something went wrong.</p>"); | |
} | |
set_exception_handler('exceptionHandler'); | |
// Question-4 | |
// Then the try/catch blocks can be removed from the two places they are used (once around creating the PDO object and once in process_form()) | |
// because the exceptions will be handled by the exception handler. | |
// 4. The following program is supposed to print out an alphabetical list of all the customers in the table from | |
// Exercise 4 in Chapter 8 (see “Exercise 4” on page 357). Find and fix the errors in it. | |
// Connect to the database | |
try { | |
} catch ($e) { | |
$db = new PDO('sqlite::/tmp/restaurant.db'); | |
die("Can't connect: " . $e->getMessage()); | |
} | |
// Set up exception error handling | |
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
// Set up fetch mode: rows as arrays | |
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); | |
// Get the array of dish names from the database | |
$dish_names = array(); | |
$res = $db->query('SELECT dish_id,dish_name FROM dishes'); | |
foreach ($res->fetchAll() as $row) { | |
$dish_names[ $row['dish_id']]] = $row['dish_name']; | |
} | |
$res = $db->query('SELECT ** FROM customers ORDER BY phone DESC'); | |
$customers = $res->fetchAll(); | |
if (count($customers) = 0) { | |
print "No customers."; | |
} else { | |
print '<table>'; | |
print '<tr><th>ID</th><th>Name</th><th>Phone</th> | |
<th>Favorite Dish</th></tr>'; | |
foreach ($customers as $customer) { | |
printf("<tr><td>%d</td><td>%s</td><td>%f</td><td>%s</td></tr>\n" | |
$customer['customer_id'], | |
htmlentities($customer['customer_name']), | |
$customer['phone'], | |
$customer['favorite_dish_id']); | |
} | |
print '</table>'; | |
// Answer-4 | |
// • Line 4: Change :: to : in the DSN. | |
// • Line 5: Change catch ($e) to catch (Exception $e). | |
// • Line 16: Change $row['dish_id']] to $row['dish_id'] as the key to look up in the $dish_names array. | |
// • Line 18: Change ** to * in the SQL query. | |
// • Line 20: Change = to ==. | |
// • Line 26: Change the third format specifier from %f to %s—$customer['phone'] is a string. | |
// • Line 30: Change $customer['favorite_dish_id'] to $dish_names [$customer['favorite_dish_id']] so that | |
// the dish ID is translated into the name of the corresponding dish. | |
// • Line 33: Insert a } to match the opening { in line 22. | |
// The complete corrected program is: | |
// Connect to the database | |
try { | |
$db = new PDO('sqlite:/tmp/restaurant.db'); | |
} catch (Exception $e) { | |
die("Can't connect: " . $e->getMessage()); | |
} | |
// Set up exception error handling | |
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
// Set up fetch mode: rows as arrays | |
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); | |
// Get the array of dish names from the database | |
$dish_names = array(); | |
$res = $db->query('SELECT dish_id,dish_name FROM dishes'); | |
foreach ($res->fetchAll() as $row) { | |
$dish_names[$row['dish_id']] = $row['dish_name']; | |
} | |
$res = $db->query('SELECT * FROM customers ORDER BY phone DESC'); | |
$customers = $res->fetchAll(); | |
if (count($customers) == 0) { | |
print "No customers."; | |
} else { | |
print '<table>'; | |
print '<tr><th>ID</th><th>Name</th> | |
<th>Phone</th><th>Favorite Dish</th></tr>'; | |
foreach ($customers as $customer) { | |
printf( | |
"<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", | |
$customer['customer_id'], | |
htmlentities($customer['customer_name']), | |
$customer['phone'], | |
$dish_names[$customer['favorite_dish_id']] | |
); | |
} | |
print '</table>'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment