03.02.2014 Views

CSCI110 Exercise 3: Server side scripting - PHP

CSCI110 Exercise 3: Server side scripting - PHP

CSCI110 Exercise 3: Server side scripting - PHP

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!