User Tools

Site Tools


eg-259:homework:php-files

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
eg-259:homework:php-files [2008/12/05 14:56] eechriseg-259:homework:php-files [2011/05/05 17:36] (current) – [Additional Exercise] eechris
Line 1: Line 1:
 +====== Files and PHP ======
  
 +Hints for Coursework 2, prepared by Dr C.P. Jobling for Examples Class on Monday 9th December 2008. 
 +
 +===== Getting Started =====
 +
 +The starting point for the coursework is the //newsong.html// page that was discussed in an earlier examples class (See **Assignments> Coursework 2> Getting Started Tutorial** on Blackboard). As an html file this will be something like:
 +<code html>
 +<?xml version="1.0" encoding="utf-8" ?>
 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 +<html xmlns="http://www.w3.org/1999/xhtml">
 +  <head>
 +    <title>
 +      Song-o-Matic: Add Your Favourite Song to Our Database
 +    </title>
 +  </head>
 +  <!-- Write an XHTML document to create a form that collects
 +       favourite popular songs, including the name of the song, the
 +       composer, and the performing artist or group. This document
 +       must call one CGI program when the form is submitted and
 +       another to request a current list of survey results. -->
 +   <body>
 +   <h1>
 +      Song-o-Matic: Add Your Favourite Song!
 +   </h1>
 +   <p>
 +     Add your favourite song to the World Wide Web's database of favourite
 +     songs!
 +   </p>
 +   <form method="post"
 +    id="song" action="receipt.php">
 +     <table border="0">
 +        <tr><th>Song Title</th>
 +            <td>
 +              <input type="text" size="40" 
 +                     name="title" value="Pink Panther Theme" />
 +            </td>
 +        </tr>
 +        <tr><th>Composer</th>
 +            <td>
 +              <input type="text" size="40" 
 +                     name="composer" value="Henry Mancini" />
 +            </td>
 +        </tr>
 +        <tr><th>Artist or Group</th>
 +            <td>
 +              <input type="text" size="40" 
 +                     name="artist_or_group" value="The Henry Mancini Orchestra" />
 +            </td>
 +        </tr>
 +      </table>
 +      <input type="submit" name="newsong" value="Add Song" /> 
 +      <input type="reset" name="reset" value="Reset Form" />
 +    </form>
 +    <p>Here are the current <a href="favsongs.php">favourites</a>.
 +  </body>
 +</html>
 +</code>
 +
 +To convert this to PHP, simply rename the file to //newsong.php//. Edit the first line so that instead of
 +<code html>
 +<?xml version="1.0"?>
 +</code>
 +it says
 +<code php>
 +<?php echo("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); ?>
 +</code>
 +Also, you should remove the //value// attributes from each of the text fields. These were for the mock-up and your form will be getting real song information from its user. Copy your new file //newsong.php// to your web server's //htdocs// directory (or a subfolder thereof).
 +
 +In the demo, I shall probably use Netbeans to create a new project and complete this step using copy and paste.
 +
 +===== Create a data file =====
 +
 +To create this example web application we shall be building up the songs listing part first. So, the next thing we need is a file format. Last time,. we agreed that it would be a text file, one song per line and we'd allow comments (lines starting with ''#''). It's also useful to ignore blank lines. A suitable example data file that we can use for testing would be:
 +<code>
 +# A comment
 +# Format: Songtitle|Composer(s)|Artist or Group
 +Don't sleep in the subway darling!|Tony and Jackie Trent|Petula Clark
 +Help!|John Lennon and Paul McCartney|The Beatles
 +
 +A Song|A Composer|An Artist or Group
 +</code>
 +Save this to the project directory. If you are running a web server on Linux, make sure that the file is writable by the web server. There are a couple of ways to do this. The easiest way is to make the file writable by others: ''chmod o+w songs.dat''.((In practice this is rather insecure. It is better to change the group ownership of the file to be the same as the group that the web server runs as (say //www//): ''sudo chgrp www songs.dat'' then change permissions to be group writable ''chmod 664 songs.dat''. Now although everyone can open the file to read it, only the web server and the file owner can open the file for writing. Of course, this requires that you have administrator access to the files that you need to change group for.)) On windows, this is probably not a problem.
 +==== Create a File Reader/Displayer ====
 +
 +Opening a file for reading and displaying it is probably less challenging that extracting data from a web form and writing it into a file. So we'll start there. In this example, I will build up a file reader displayer in stages. This reflects my way of working, but it is not a bad way I think. We start small, building functionality step-by step and having working, testable code at each stage. I find that this approach works better than trying to plan a complete solution in advance and then struggling to implement it because there are too many unanswered questions, and opportunities for introducing coding errors. Also, I find that taking small steps gives me more of a sense of achievement and the impetus to keep going.
 +
 +=== Step 1: Open a file, and read it line by line ===
 +
 +Note we don't have to open the file, simply call ''$lines = file("songs.dat");'' to read the file into an array of strings with one line per array element. This will only work with text files as records are affectively deliminated by the end-of-line character which is ''\n'' on Unix and ''\r\n'' on Windows. 
 +<code php>
 +<?php 
 +// Read file into an array (one element per line)
 +$lines = file("songs.dat");
 +
 +// print every line
 +$line_no = 1;
 +foreach ($lines as $line) {
 +    print "$line_no: $line <br />\n"; // \n has no effect on the browser but makes the HTML source look better.
 +    $line_no++;
 +}
 +?>
 +</code>
 +
 +=== Step 2: Extract the data in a line into an array ===
 +
 +For thsi step, we take the line data and //explode// it on the ''|'' character which we decided to use for a field deliminator.
 +
 +<code php>
 +<?php
 +// Read file into an array (one element per line)
 +...
 +
 +// print every line
 +foreach($lines as $line) {
 +    ....
 +    // explode each line into records
 +    $data = explode("|", $line);
 +    print "$line_no: ";
 +    foreach($data as $value) {
 +        print "\$value = $value; ";
 +    }
 +    print "<br />\n";
 +    $line_no++;
 +}
 +?>
 +</code>
 +
 +
 +=== Step 3: Skip blank lines and comments ===
 +
 +To skip blank lines or lines that start with a comment we use a regular expression:
 +<code php>
 +<?php
 +// Read file into an array (one element per line)
 +...
 + 
 +// print every line
 +foreach($lines as $line) {
 +    // slip lines that start with a comment
 +    // or empty lines
 +    if (! preg_match("/(^#)|(^$)/", line) {
 +        // explode each line into records
 +        ...
 +    }
 +}
 +?>
 +</code>
 +
 +=== Step 4: Extract array data into variables for printing ===
 +
 +Once you have the data exploded into an array, it is trivial to assign the values to variables:
 +<code php>
 +<?php
 +// Read file into an array (one element per line)
 +...
 +
 +// print every line
 +foreach($lines as $line) {
 +    ....
 +    // explode each line into records
 +    // if data valid
 +      $title = $data[0];
 +      $composer = $data[1];
 +      $artist = $data[2];
 +      print "$line_no: " .
 +         "<em>Song title</em>: $title; " . // could use $data[0] here of course
 +         "<em>Composer</em>: $composer; " .
 +         "<em>Artist or Group</em>: $artist;" .
 +         "<br />\n";
 +      $line_no++;
 +   ...
 +}
 +?>
 +</code>
 +
 +=== Step 5: Format data as an HTML table ===
 +
 +The task is almost complete, simply surround the loop with a table to get the list output.
 +<code php>
 +<?php 
 +// Read file into an array (one element per line
 +?>
 +<table border="1">
 +  <tr><th>Song</th><th>Composer</th><th>Artist</th></tr>
 +<?php
 +  // Operate on every line
 +  foreach ($lines as $line) {
 +    // Ignore any line that starts with a comment or empty lines
 +    ...
 +      // Extract data values
 +      $data = explode("|", trim($line)); // trim removes trailing white space
 +      $title = $data[0];
 +      $composer = $data[1];
 +      $artist = $data[2];
 +      print "<tr> <td> $title </td> <td> $composer </td> <td> $artist </td> </tr>";
 +    }
 +  }
 +?>
 +</table>
 +</code>
 +==== Processing the web form data ====
 +
 +We have written code to read data in the format we have specified. Now we need to write some PHP to handle the form data and write it into a file. We do this in the //action// target of the form //newsong.php// which is //receipt.php//. Our intention is to extract the song data submitted in the form, create a new record for it in the form we specified, write the data to disk, then return a receipt. The format of the receipt was given to you in the last tutorial so the framework already exists:
 +<code html>
 +<?xml version="1.0" ?>
 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 +<html xmlns="http://www.w3.org/1999/xhtml">
 +  <head>
 +    <title>
 +      Song-o-Matic: Thanks for your input
 +    </title>
 +  </head>
 +  <!-- Returned to the user as a receipt for their input -->
 +   <body>
 +   <h1>
 +      Song-o-Matic: Thanks for your input
 +   </h1>
 +   <p>
 +     <strong>This is a mock-up of what we want the results to look like.
 +     Always useful to have this when you are designing a web app!</strong>
 +   </p>
 +   <p>Thanks for your input. We have added <em>Henry Mancini</em> &quot;The Pink Panther Theme&quot; 
 +   as performed by The Henry Mancini Orchestra to the Song-o-Matic database of the Web's favourite 
 +   songs.</p>\n";
 +   <p>You can <a href="newsong.php">Add another</a> or see the
 +   current <a href="favsongs.php"> complete list</a>.</p>
 +   </body>
 +</html>
 +</code>
 +
 +Extraction of the data is easy:
 +<code php>
 +<?php 
 +$title = $_POST["title"];
 +$composer = $_POST["composer"];
 +$artist_or_group = $_POST["artist_or_group"];
 +?>
 +</code>
 +
 +So is adding the data to the output. Here's one way to do it:" .
 +<code php>
 +print "<p>Thanks for your input. We have added <em>$composer</em> &quot;$title&quot; " .
 +   "as performed by $artist or group to the Song-o-Matic database of the Web's favourite " .
 +   "songs.</p>\n";
 +</code>
 +
 +If you are a java programmer you will be suprised to see that writing the data is as simple as:
 +<code php>
 +<?php
 +$songs = fopen("songs.dat","a"); // open for append
 +fwrite($songs, "$title|$composer|$artist\n"); // write data with | deliminator and end-of-line marker
 +?>
 +</code>
 +
 +On testing, the only likely problem will be with the file permissions: //song.dat// must be writable by the web server.
 +
 +In production, you would need to //lock// the file for exclusive access using ''flock'' to prevent two simultaneous form submissions attempting to write data into the file at the same time. More detail on the use of //flock// is to be found in the [[http://uk.php.net/flock|PHP manual]].
 +
 +===== Summary =====
 +
 +I have given you sufficient information here to make the implementation of the Course Work 2 exercise trivial. 
 +===== Additional Exercise =====
 +
 +
 +  - Use the ideas presented in the [[eg-259:lecture19#php_mysqlexample_2|second database]] example to put the entire application into a single PHP file. Then comment on why this might not be a good idea for very large applications.
 +  - Extend the code to allow comments that do not start at the start of the line: e.g. ''All you need is love|Lennon and McCartney|The Beatles # This is the greatest Beatles son ever!''
 +  - How could you deal with a comment symbol (hash ''#'') that was part of a song title?
 +  - Try implementing the song database in PHP with MySQL.
 +
 +
 +----
 +
 +[[eg-259:homework:home|More Homework Exercises]]