CSCI110 Exercise 3: Server side scripting - PHP
CSCI110 Exercise 3: Server side scripting - PHP
CSCI110 Exercise 3: Server side scripting - PHP
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>CSCI110</strong><br />
<strong>Exercise</strong> 3: <strong>Server</strong> <strong>side</strong> <strong>scripting</strong> - <strong>PHP</strong><br />
The exercise<br />
This exercise is to be completed in the laboratory and your completed work is to be<br />
shown to the laboratory tutor. The work should be done in week-6 but completion by<br />
the end of week-9 is acceptable. (No marks unless demonstrated by week 9.) The<br />
completed exercise is worth 4 marks. When you have demonstrated your work to the<br />
laboratory tutor, you should sign off on the tutor’s marking sheet.<br />
Overview<br />
This exercise has HTML data entry forms sending data to simple server-<strong>side</strong> <strong>PHP</strong><br />
scripts. The little applications here have no need to update persistent data, and so no<br />
need for a database (which we probably won’t have covered in lectures at the time<br />
you do the exercise).<br />
One of the examples does use input from server files. Generally, file storage is<br />
problematic with web applications. Read access isn’t too difficult – you simply have<br />
to allocate the appropriate file access permission; the problems come with write<br />
access. If files have to be updated you encounter all sorts of problems relating to<br />
attempts at concurrent updates; databases offer much better mechanisms for dealing<br />
with concurrency issues.<br />
<strong>PHP</strong> is another <strong>scripting</strong> language akin to Javascript. So, you must expect all the<br />
“sloppiness” of a <strong>scripting</strong> language – no real data types, no need to declare variables,<br />
etc. Again, the coding will seem like a simplified version of the C++ that you did in<br />
CSCI114. You define global variables and functions. Functions have sequences of<br />
statements, conditionals, and loops. You do have a little “main-line” code (there is no<br />
main() function as such) which is often embedded in amongst some standard HTML<br />
markup and content text. One thing that will seem odd is that <strong>PHP</strong> variables have<br />
names that start with a dollar ‘$’ character (this feature is inherited from the Perl<br />
language).<br />
There is con<strong>side</strong>rable flexibility in code layout. Some of these examples will use a<br />
style where <strong>PHP</strong> globals and functions are defined in (or before) the section<br />
of the page; HTML markup, content text and snippets of embedded “main-line” <strong>PHP</strong><br />
code will follow. Others consist largely of <strong>PHP</strong> code with the HTML and static<br />
content text being generated through echo (print) statements. The style with code<br />
embedded in HTML helped popularize <strong>PHP</strong> and is useful when the amount of code is<br />
small. In more complex applications, there is much more code than HTML and<br />
content text; in such more complex cases, the coding style dominates.<br />
The web applications that you create in this exercise are:<br />
©nabg
1. Fortune<br />
A <strong>PHP</strong> script that requires no input; it is invoked via a GET operation (type its<br />
URL in the browser address field); it returns an aphorism – some amusing<br />
saying to brighten the day of the user.<br />
2. PieChart<br />
A static HTML form is used to enter category names and values that are<br />
submitted to a <strong>PHP</strong> script which responds with a page that is simply a graphic<br />
pie-chart of the data.<br />
3. Hangman<br />
A web-based version of the word-guessing game.<br />
This example introduces “state” – the state of the game, what letters have you<br />
picked, how close are you to being hung, what parts of the word have you<br />
matched.<br />
The lectures may not have covered the better mechanisms for maintaining state<br />
data at the time you do this exercise. Consequently, state maintenance is done<br />
using the clumsy but simple “hidden fields” approach.<br />
©nabg
Caution! You are now working with both <strong>PHP</strong> and Javascript. It is not uncommon<br />
to have a dynamic web-page (.php file type) that contains both <strong>PHP</strong> code (that<br />
generates the dynamic content that will be sent to the client) and some Javascript<br />
(that gets sent to the client to be interpreted by the browser). It is easy to get<br />
confused and try to call a <strong>PHP</strong> function in Javascript or try to use a Javascript object<br />
in your <strong>PHP</strong> code. You are likely to do better if you put any Javascript in a separate<br />
.js file identified by a link in the page header. Another thing – just remember that<br />
variables that start with $ are for <strong>PHP</strong>, the variables without a $ are for Javascript.<br />
Tasks<br />
Fortune<br />
1. Use NetBeans to create a new “<strong>PHP</strong>” project (“<strong>Exercise</strong>3”) in<strong>side</strong> your<br />
public_html directory.<br />
©nabg
2. NetBeans generates a file index.php with a little bit of starting HTML code<br />
containing a block for some minimal amount of embedded <strong>PHP</strong>. Rename this file<br />
as Fortune.php.<br />
3. The “fortune” program works by having a collection of aphorisms (“wise or witty<br />
sayings”) from which a particular example is chosen at random and returned in the<br />
generated page.<br />
The application requires a little <strong>PHP</strong> code in the section of the page – here<br />
the collection of aphorisms will be defined along with a function that selects one<br />
at random.<br />
The body of the page involves a little HTML markup and standard content text<br />
along with an embedded fragment of <strong>PHP</strong> that invokes the fortune selection<br />
function and prints the result in the returned page.<br />
Edit the HTML and content text:<br />
4. The main part of the <strong>PHP</strong> code should be declared within a script<br />
section in the part of the page:<br />
©nabg
5. The code defines two <strong>PHP</strong> global variables – the initialized array $fortunes and an<br />
integer $numfortunes representing the number of fortune messages.<br />
The todaysFortune() function:<br />
Specifies that it is using the global variables $numfortunes and $fortunes!<br />
Uses <strong>PHP</strong>’s rand() function (http://au.php.net/manual/en/function.rand.php)<br />
to pick from the collection.<br />
Returns the selected message.<br />
6. Pick your own selection of wise and witty sayings for the fortunes!<br />
$fortunes = array(<br />
"It has been discovered that C++ provides a remarkable facility for concealing the<br />
trivial details of a program - such as where its bugs are.",<br />
...<br />
"Don't worry about avoiding temptation... as you grow older, it will avoid you.",<br />
"Some people talk in their sleep. Lecturers talk while other people sleep."<br />
);<br />
7. Save, then aim your browser at http://localhost/~userid/<strong>Exercise</strong>3/Fortune.php and<br />
you should receive your fortune:<br />
8. Ask a friend for the URL of their fortune service (something like http://megapc16.cs.uow.edu.au/~xyz123/<strong>Exercise</strong>3/Fortune.php)<br />
and try their service; let<br />
them try yours.<br />
Pie chart<br />
9. In your NetBeans <strong>Exercise</strong>3 project create the HTML files PieForm.html, and<br />
Errors.html, a Javascript file (checksubmit.js), and a “<strong>PHP</strong> file” (not a “<strong>PHP</strong> web<br />
page”) called PieGraph.php.<br />
©nabg
The “Errors” page will be displayed if the PieGraph script cannot process the data<br />
for some reason – no data supplied, too much data supplied, non-numeric data in<br />
the numerics field, or some other problem.<br />
10. Edit the PieForm.html page (either entering all the HTML by hand or by using the<br />
HTML palette in NetBeans) and create a form page like the following:<br />
11. This form page should have a link to the checksubmit.js Javascript code file:<br />
©nabg
12. There are three Javascript functions:<br />
Function doReset() clears the numadded global, the values in the two text areas,<br />
and the values in all the fields. (This function definition<br />
is left as an exercise; you can clear all the form’s input fields by getting a<br />
reference to the form object and invoking its built in rest() function; you have to<br />
zero out the global variables used in your script.)<br />
Function checkData() is called “onsubmit” and acts to prevent submission if there<br />
are obvious problems with any of the data; if there are problems with data it<br />
displays an alert with some explanatory message. It checks that at least one and at<br />
most ten data pairs have been added and that the input field for the “Title” has<br />
some text with alphanumeric characters and spaces. (This function definition is<br />
left as an exercise.)<br />
Function doAdd() is called when the Add Item button is used. It checks the input<br />
data. If there are problems, an alert is displayed. If the data are valid, they are<br />
added to the text areas.<br />
The data checks make use of “Regular Expressions” (“regex”s). These get a brief<br />
mention in the <strong>PHP</strong> lectures (and the <strong>PHP</strong> code for this example also uses regexs).<br />
Regular expressions are covered properly at 200-level. Their use is easy – the<br />
difficulty with them is defining the “patterns” that describe valid text data.<br />
However, as noted in the <strong>PHP</strong> lectures, most of the time you are doing fairly<br />
standard checks (e.g. “Does the string represent a decimal number with an<br />
optional fraction part such as 7.1, 0.5, or 3?”). There are “cheat sheets” on the<br />
web that give you the appropriate regex pattern for such checks. (There are<br />
different regular expression grammars, but <strong>PHP</strong> and Javascript use very similar<br />
forms derived from those originally created for Perl.)<br />
©nabg
The code for doAdd() is:<br />
13. At this point you should test you PieForm.html page and its associated Javascript<br />
in a browser.<br />
Try entering valid and invalid data and confirm that the data checking works.<br />
Of course, nothing much happens if you submit the data as the server <strong>side</strong> script<br />
hasn’t been written yet.<br />
14. Get used to using Javascript debuggers!<br />
Modify your script by introducing a deliberate error – at one of points where it<br />
uses document.getElementById(…) try introducing a typing error (either in the<br />
string naming the element or in the function name itself).<br />
IE has a Javascript debugger (Tools/Development Tools menu).<br />
©nabg
You have to install Firefox’s Firebug debugger from http://getfirebug.com/ .<br />
Equivalent report from Firebug:<br />
15. Remove your deliberate bug.<br />
16. Implement the first part of the <strong>PHP</strong> script.<br />
Never attempt to implement a complete script straight off; always work<br />
incrementally, testing as you go.<br />
The first part of the <strong>PHP</strong> script checks the data input and redirects the user to the<br />
Errors.html page if something is wrong.<br />
Weren’t the data checked by Javascript?<br />
Checking on the client <strong>side</strong> with Javascript catches careless mistakes by<br />
inattentive or dumb users (catch fools).<br />
Checking on the server <strong>side</strong> catches hacker attacks (catch villains).<br />
17. The checking part of the <strong>PHP</strong> script.<br />
Pick up the strings with data in the form’s two textareas and the title input.<br />
If any of these are empty – redirect user to error page.<br />
The textareas were supposed to contain multiple lines – use split() to break<br />
into arrays that will have an entry for each line.<br />
The arrays for the category names and the numbers should have equal<br />
numbers of entries – redirect user to error page if this isn’t so.<br />
©nabg
There should be at least one and at most ten rows in these arrays – redirect<br />
user to error page if too few or too many data rows.<br />
Repeat those regex based checks – values in numbers array should match<br />
regex for number, values in category names array should match regex for<br />
name.<br />
<strong>PHP</strong>’s regex checking doesn’t involve any “RegExp” objects – there is<br />
instead a function that takes a pattern and a string and does the check.<br />
Check the title.<br />
Report success<br />
18. My code was as follows (you may need to adjust to match the names that you<br />
gave to fields in your form):<br />
19. <strong>PHP</strong>’s rtrim() function removes trailing white space from a string. When you split<br />
the contents of the textareas at newline characters, the “\n” characters are left<br />
appended to the strings.<br />
©nabg
You can lookup functions like rtrim() and split() at<br />
http://www.php.net/manual/en/funcref.php<br />
20. Try running your web application now. Submissions of valid data should result in<br />
a page with “data ok”.<br />
The only way that you will be able to feed bad data to your <strong>PHP</strong> script (and test its<br />
error handling) will be to disable Javascript on the client (or comment out parts of<br />
your Javascript code).<br />
21. Once you have data checking implemented, continue by implementing the<br />
graphics:<br />
Remove all echo statements!<br />
Change the response type to image/png<br />
Allocate an image in memory for use with the GD graphics library – specify<br />
number of pixels wide and high.<br />
<br />
<br />
Create colours that will be used.<br />
Create reference to a file with a “TrueType” font (find one first – on Windows<br />
there will be some in C:\\Windows\\Fonts\\; on Linux, look for fonts in the lib<br />
directory associated with your “Java Runtime Engine” (jre) – where that is will<br />
be installation dependent).<br />
Work out arc angles for the pie graph (CSCI114 level programming!).<br />
Use GD graphics to draw text, pie slice arcs etc.<br />
Convert in memory image into a coded stream for a png image that gets<br />
returned to client.<br />
22. My code for the first few steps was:<br />
©nabg
You will need to append the lines that encode and send the image to the client:<br />
(Those lines will go at the very end of your <strong>PHP</strong> script – after the code listed<br />
below that actually generates the image. Put those lines in now, so that you can<br />
test the production of a graphics response page with the title. Remember, all the<br />
other code for the image goes before the line $imagpng().)<br />
Remember also to change the value of the font directory – find some ttf fonts on<br />
your system, use the directory where you found them.<br />
23. Test the code implemented so far – submission from your PieForm.html should<br />
produce a graphics response page with the title.<br />
24. Calculate and plot the arc angles and display the legend with category names.<br />
My code was:<br />
©nabg
25. It should now all work.<br />
(Actually, it’s a bit long for a single mainline <strong>PHP</strong> script. The code would be<br />
better if it were broken down into functions. Remember this when doing<br />
assignments – you will probably lose a mark for not using functions enough if you<br />
submit code with a mainline this long.)<br />
26. Tidy the code by breaking into functions. Retest in case you introduced any bugs<br />
during your “refactoring”.<br />
Hangman<br />
27. Create a new <strong>PHP</strong> script, Hangman.php, and a text file words.txt (use “New<br />
Empty File”) in your NetBeans <strong>Exercise</strong> 3 project.<br />
©nabg
Add some words, one per line, to words.txt. (If you want interesting words for a<br />
hangman game you can get sets from web sites relating to the Scrabble game –<br />
just ask Google. I found a file with ~15000 words.) You should make your words<br />
all lower case or all upper case.<br />
28. The Hangman program will work as follows:<br />
It will read in its collection of words from a file.<br />
It will check whether its been called by “GET” or “POST”<br />
“GET” means start a new game.<br />
Randomly pick the index number for a word from the collection.<br />
Return a web-form page showing an empty scaffold, a set of underscore<br />
characters representing the word, a form component that has a field<br />
where the user can enter a letter, a hidden field with all letters used – this<br />
field is currently empty, a hidden field with number of incorrect guesses<br />
– currently 0, and a hidden field with the index number of the word that<br />
is to be guessed.<br />
“POST” means the user guessed a letter<br />
Pick up posted data – word’s index number, letters previously guessed,<br />
newly guessed letter.<br />
Take word from collection and create copy checking off all guessed<br />
letters.<br />
If all letters guessed correctly, return a page congratulating user on<br />
winning a game.<br />
If user has not guessed word, and has now reached limit of incorrect<br />
guesses (limit 6), return a page informing the user that the game was lost.<br />
Pick the scaffold “picture” appropriate to number of incorrect guesses.<br />
Return a response page showing scaffold with possibly partially hung<br />
man, a string showing letters guessed and underscores for letters not yet<br />
guessed, a form field for a new guess, and appropriate hidden fields<br />
holding the values of the new updated game state.<br />
29. What “pictures” will the game use for the scaffold?<br />
You could create a set of actual images and handle this by an link – but it’s<br />
sufficient to work with pre-formatted text.<br />
30. Develop the program in incremental steps.<br />
First, a program that reads in the words.txt file and responds to a GET with details<br />
of a randomly chosen word.<br />
This step gets the program started and resolves any file I/O issues.<br />
31. Hangman.php – version 0:<br />
©nabg
When starting, its best to ignore issues of markup – so temporarily set the<br />
response type to text/plain.<br />
The loadWords() function opens the words.txt file, and processes the file<br />
assuming that it will contain one word per line. The words are placed in the<br />
global array $words.<br />
The startGame() function called for a GET request will print details of a word.<br />
(The handleGuess() function isn’t even defined; a POST request would cause<br />
program to fail).<br />
This program is sufficient to check file I/O. It should work.<br />
©nabg
32. If you don’t have the time to waste on constructing little images of hanged men,<br />
the following text can be pasted into a file “hangedmen.php”:<br />
?><br />
33. Hangman.php – version 1;<br />
Modify the Hangman.php file to include the text images in hanged.php. (Use<br />
include or require on the file. What’s the difference? If the requested file isn’t<br />
there then an include operation results in a warning message whereas a require<br />
operation results in program termination.)<br />
Modify the startGame() function so that it generates a draft of the HTML form<br />
page that a player will get at the start of a game:<br />
©nabg
View the (plain text) page that this script now generates – it’s an easy way of<br />
checking that hidden fields are being set, that action attribute of form is defined<br />
etc.<br />
If everything looks ok, remove the line that sets the content type to plain text and<br />
view the form as a form:<br />
©nabg
34. Similar form pages will need to be displayed after some guesses have been made.<br />
Rather than duplicate the code for generating a form page, “refactor” the existing<br />
code to make the actual HTML generation the task of a separate subroutine.<br />
(“Refactor” is a lovely word; it sounds so much better than “hack”.)<br />
©nabg
Retest the code to make sure nothing broken during the “refactoring” process.<br />
35. Hangman.php – Version 2:<br />
The code has to take input from the form. It really should check the input data –<br />
but I was lazy and didn’t bother. (So, some hacker will crash my hangman game.)<br />
It should then determine how much of the target word has been guessed.<br />
If the user has now guessed all the letters in the target word, then he/she should be<br />
congratulated.<br />
If the user has reached the limit of six incorrect guesses, the game should<br />
terminate.<br />
Otherwise, a new form page with updated information should be returned.<br />
It seems that four functions are needed:<br />
36. The killplayer() and congratulateWinner() functions are both simple – just the<br />
output of a little static content and markup:<br />
©nabg
37. The matchLetters() function takes as arguments a string value for the word that is<br />
to be guessed, and a string that contains the letters that the player has used as<br />
guesses.<br />
It is to return a string representing the word with _ (underscore) characters for<br />
letters still unguessed and actual letters where these have been guessed. (The<br />
letter or underscore characters are separated by space characters so that this string<br />
will appear more clearly in the form display).<br />
It works by checking each successive letter in the word, using the strstr() function<br />
to determine whether this letter is among those used as guesses:<br />
38. The handleGuess() function:<br />
©nabg
39. It should now work – test it.<br />
©nabg