By the end of this Lab, you should be able to:
Just like any other program you may write, it's important to cleanly handle errors with your PHP web service implementation to help clients know what went wrong. Often, errors come from mis-typing query parameters, passing in parameter values that don't correspond to data that was found on the server, etc.
When something goes wrong based on the client's request, we use the 400 error code. In
PHP, you can set this in the response using the header
function as follows:
header("HTTP/1.1 400 Invalid Request");
header("Content-type: text/plain");
Note that in case of an error, you may need two calls to the header function, once to set the error code, and the second time to set the Content-Type.
PHP tends to be a little more silent in its errors. When developing, this is important to be aware of. One thing you can use to help report more errors is to use the following function call at the top of every PHP file you write:
error_reporting(E_ALL);
This command makes PHP report more errors (sort of like "use strict" in JavaScript).
contents of foo.txt | file("foo.txt") | file_get_contents("foo.txt") |
---|---|---|
Hello how r u? I'm fine |
array("Hello\n", #0 "how r u?\n", #1 "\n", #2 "I'm fine\n" #3 ) |
"Hello\n how r u\n # a single \n # string I'm fine\n" |
The file
function returns lines of a file as an array (\n at end of each).
file_get_contents
returns entire contents of a file as a single string.
file_put_contents
writes a string into a file.
# reverse a file
$text = file_get_contents("poem.txt");
$text = strrev($text);
file_put_contents("poem.txt", $text);
file_get_contents
returns entire contents of a file as a string
file_put_contents
writes a string into a file, replacing its old
contents
# add a new line to a file
$new_text = "P.S. ILY, GTG TTYL!~";
file_put_contents("poem.txt", $new_text, FILE_APPEND);
old contents | new contents |
---|---|
Roses are red
Violets are blue All my base Are belong to you. |
Roses are red
Violets are blue All my base Are belong to you. P.S. ILY, GTG TTYL!~ |
file_put_contents
can be called with an optional third parameter to append
(add to
end) rather than overwrite.
function | description |
---|---|
glob | returns an array of all file names that match a given pattern (returns a file path and name, such as "foo/bar/myfile.txt") |
scandir | returns an array of all file names in a given directory (returns just the file names, such as "myfile.txt") |
Can accept a general path with the * wildcard (more powerful).
glob
Example# reverse all poems in the poetry directory
$poems = glob("poetry/poem*.dat");
foreach ($poems as $poemfile) {
$text = file_get_contents($poemfile);
file_put_contents($poemfile, strrev($text));
echo "I just reversed " . basename($poemfile) . "\n";
}
glob can match a wildcard path with the * character
glob("foo/bar/*.doc")
returns all .doc files in the foo/bar
subdirectoryglob("food*")
returns all files whose names begin with "food"The basename
function strips any leading directory from a file path
basename("foo/bar/baz.txt")
returns "baz.txt"scandir
Exampleforeach (scandir("taxes/old") as $filename) {
echo "I found a file: {$filename}\n";
}
I found a file: .
I found a file: ..
I found a file: 2007_w2.pdf
I found a file: 2006_1099.doc
scandir
includes current directory (".") and parent ("..") in the array.
Don't need basename
with scandir
; returns file names only
without directory
In this lab, we are encouraging students to work with a peer (e.g. your neighbor) to discuss and work through writing some neat PHP web services. If you'd like to try your hand at a challenging but popular pair programming technique known as "driver and navigator", read the slide below and try it out on one or both of the following exercises - ask your neighbors if they are interested!
A challenging programming technique that involves two people working together on a single computer. It provides an opportunity to explore new problem solving approaches, especially when learning a new language.
Role | Description |
---|---|
Driver | The person at the keyboard that takes instructions from the navigator |
Navigator | The person providing instruction (code and text editor commands) to the driver |
In order to have an effective pair programming experience, it's good to refer to the details of these roles (which in practice, alternate between tasks)
If you're a navigator and you don't know what to do next, or you're a driver and you have an idea you'd like to try implementing, then switch roles with your partner.
Given a directory of character pictures (got.zip), write a PHP web service which vends these photos. These pictures represent characters in one of three "houses" (or families) in the Game of Thrones series: House Lannister, House Stark, and House Targaryen (yes, we know there are more, but you can always add more pictures!).
There are two parts in this exercise. The first outputs all image names in the images
folder, and the second filters the output based on an optional query parameter
(house
).
Go "down" to work through the slides specific to this exercise.
First, write your web service such that it simply prints out (in plain text) a list of
image names in the provided images
folder.
When the PHP page is executed, all of the file names in the images
directory should be output, each on its own line.
Expected Output:
images/lannister1.jpg
images/lannister2.jpg
images/lannister3.jpg
images/lannister4.jpg
images/stark1.jpg
images/stark2.jpg
images/stark3.jpg
images/stark4.jpg
images/stark5.jpg
images/targaryen2.jpg
images/targaryen3.jpg
images/targaryen4.jpg
After implementing the behavior when no query parameter is passed, add a query parameter handler to let a user filter the
outputted images based on a house name. There are three three houses ("lannister", "stark", or "targaryen")
that correspond to images in the images folder. If a value for house
is
included as a query parameter, your code should
print only the images which are related to a specific house.
Print out the list of files including the images/
directory. This is loosely based on the assumption that your
PHP webservice and your HTML/CSS/JS application would be served out of the same directory where images/
sits.
Source (PHP)
Running Version (PHP)
It's always fun to try new things. When it comes to cooking, sometimes it's hard to
find that spark of inspiration. In this exercise, you'll use folder and file processing to
create a web service that takes in a single parameter name
and outputs a
randomly-generated recipe idea based on the letters in the name.
The first letter of the name will correspond to the first letter of the recipe name, and the rest of the letters of the name will each correspond to a randomly-generated ingredient for that recipe. The final recipe will be output in plain text.
Go "down" to work through the slides specific to this exercise.
Download and unzip the provided recipe-generator.zip
.
In this folder, there are two sub-directories, foods
and
ingredients
. Each contains exactly 26 txt files each corresponding to a
lower-cased letter of the English alphabet. foods
includes txt files listing recipe
names, and ingredients
includes txt files include ingredients.
There is
also a starting recipe-generator.php
provided with comments for you to
fill in as well as two helper functions. In this exercise, you will work through the
steps outlined in those comments, but there are more details in the slides below.
foods
Macaroni
Manicotti
Mantou
Marmalade
Masala
Milkshake
Minestrone Soup
Mochi
Mooncake
Muffin
ingredients
1 cup rolled Oats
1 Okra
1 Olive
1 Orange
1 tsp Oregano
1 Oreo
1 box of Oreos
1 cup Onions
1 cup Orzo
1 Oyster
Note that each ingredient file contains a list of possible ingredients starting with the corresponding letter. To help generate a "reasonable" recipe, each ingredient option includes a unit (e.g. for the ingredient "Oreo" in ingredients/o.txt, it may be listed as "1 Oreo", but there is also an option for "1 box of Oreos" for extra oreo-ness in your recipe). Your code should not depend on this format though, it just makes the output nicer.
The following is an example (random) output for a request to
recipe-generator.php?name=Mowgli
:
Mowgli's Muffin
Directions:
In a bowl, mix:
1 Oreo
1 gallon of Water
1 oz of Green peas
1 Lentil
1 Ice cube
Cook for 6 minutes and serve!
Now that we know the format of the files we have in the two directories, let's
implement the recipe generator. Make sure to write your
recipe-generator.php
file in the same directory as the two
subdirectories. Follow the steps in the provided starting code to finish the web
service. Hints and expected behavior of each step are included below (remaining steps
included in the following two slides below).
In Step 1, check for a valid GET parameter, otherwise output a 400 error with a helpful error message of your choice.
In Step 2, set the appropriate header
type for the web service before
printing your output. This is used to specify what type of data your web service is
outputting (in this case, plain text).
In Step 3, generate a random recipe name based on the first letter of the passed name and
print the recipe name as the first line. Remember that you'll only need to use
foods/
in this step (the recipe name should be in the format of
<name>'s <foodname>
, replace <name> with the value
of the passed parameter, and <foodname> with the randomly-chosen food name).
In Step 4, output the intermediate text, "Directions:" and "In a bowl, mix:", each on new lines, to introduce the ingredients. We have provided a helper function for you for you to use.
In Step 5, generate a list of randomly-chosen ingredients based on the rest of the letters in
the name. Each ingredient should be printed on a new line, prepending " "
(two spaces) for indentation. Remember that you'll only need to use ingredients/
in this
step.
In Step 6, output the final line of the recipe, indicating how long to cook before serving. A recipe should be listed to cook for X minutes, where X is the length of the name parameter.
Source (PHP)
Running Version (PHP)