“; // provide links to scripts that generate the certificates echo “Please click here to download your certificate as a Microsoft Word RTF file... L ISTING 30.2 Continued ”; echo “”; ech
Trang 1F IGURE 30.2
index.htmlasks the user to answer quiz questions.
Grading the Answers
When the user submits his answers to the questions in index.html, we need to grade him and
calculate a score This is done by the script called score.php The code for this script is shown
in Listing 30.2
L ISTING 30.2 score.php—Script to Mark Exams
<?
// check that all the data was received
if($q1==’’||$q2==’’||$q3==’’||$name==’’)
{
echo “<h1><p align = center><img src = ‘rosette.gif’ alt = ‘’>
30
Trang 2L ISTING 30.2 Continued
Sorry:
<img src = ‘rosette.gif’ alt = ‘’></h1>”; echo “<p>You need to fill in your name and answer all questions”; }
else { //add up the scores
$score = 0;
if($q1 == 1) // the correct answer for q1 is 1
$score++;
if($q2 == 1) // the correct answer for q2 is 1
$score++;
if($q3 == 1) // the correct answer for q3 is 1
$score++;
//convert score to a percentage
$score = $score / 3 * 100;
if($score < 50) {
// this person failed echo “<h1><p align = center><img src = ‘rosette.gif’ alt = ‘’>
Sorry:
<img src = ‘rosette.gif’ alt = ‘’></h1>”; echo “<p>You need to score at least 50% to pass the exam”;
} else { // create a string containing the score to one decimal place
$score = number_format($score, 1);
echo “<h1><p align = center><img src = ‘rosette.gif’ alt = ‘’>
Congratulations
<img src = ‘rosette.gif’ alt = ‘’></h1>”; echo “<p>Well done $name, with a score of $score%,
you have passed the exam “;
// provide links to scripts that generate the certificates echo “<p>Please click here to download your certificate as
a Microsoft Word (RTF) file “;
echo “<form action = ‘rtf.php’ method = get>”;
echo “<center>
Trang 3L ISTING 30.2 Continued
<input type = image src = ‘certificate.gif’ border = 0>
</center>”;
echo “<input type = hidden name = score value = ‘$score’>”;
echo “<input type = hidden name = name value = ‘$name’>”;
echo “</form>”;
echo “<p>Please click here to download your certificate as
a Portable Document Format (PDF) file “;
echo “<form action = ‘pdf.php’ method = get>”;
echo “<center>
<input type = image src = ‘certificate.gif’ border = 0>
</center>”;
echo “<input type = hidden name = score value = ‘$score’>”;
echo “<input type = hidden name = name value = ‘$name’>”;
echo “</form>”;
echo “<p>Please click here to download your certificate as
a Portable Document Format (PDF) file generated with PDFLib “;
echo “<form action = ‘pdflib.php’ method = get>”;
echo “<center>
<input type = image src = ‘certificate.gif’ border = 0>
</center>”;
echo “<input type = hidden name = score value = ‘$score’>”;
echo “<input type = hidden name = name value = ‘$name’>”;
echo “</form>”;
} }
?>
This script will display a message if the user did not answer all questions or scored less than
our chosen pass mark
If the user successfully answered the questions, he will be allowed to generate a certificate
The output of a successful visit is shown in Figure 30.3
From here, the user has three options He can have an RTF certificate, or one of two PDF
certificates We will look at the script responsible for each
30
Trang 4F IGURE 30.3
score.phppresents successful visitors with the option to generate a certificate in one of three ways.
Generating an RTF Certificate
There is nothing to stop us from generating an RTF document by writing ASCII text to a file or
a string variable, but it would mean learning yet another set of syntax
Here is a very simple RTF document:
{\rtf1 {\fonttbl {\f0 Arial;}{\f1 Times New Roman;}}
\f0\fs28 Heading\par
\f1\fs20 This is an rtf document.\par }
This document sets up a font table with two fonts: Arial, to be referred to as f0, and Times New Roman, to be referred to as f1 It then writes Heading using f0(Arial) in size 28 (14 point) The control \parindicates a paragraph break We then write This is an rtf
We could generate a document like this manually, but there are no labor saving functions built
in to PHP to make the hard parts, such as incorporating graphics, easier Fortunately, in many documents, the structure, style, and much of the text are static, and only small parts change from person to person A more efficient way to generate a document is using a template
Trang 5We can build a complex document, such as the one shown in Figure 30.4, easily using a word
processor
30
F IGURE 30.4
Using a word processor, we can create a complex, attractive template easily.
Our template includes placeholders such as <<NAME>>to mark the places where dynamic data
will be inserted It is not important what these place holders look like We are using a
mean-ingful description between two sets of angled braces It is important that we choose
placehold-ers that are highly unlikely to accidentally appear in the rest of the document It will help you
to lay out your template if the placeholders are roughly the same length as the data they will
be replaced with
The placeholders in this document are <<NAME>>,<<Name>>,<<score>>, and <<mm/dd/yyyy>>
Note that we are using both NAME and Name, because we intend to use a case sensitive
method to replace them
Now that we have a template, we need a script to personalize it This script is called rtf.php,
and its code is shown in Listing 30.3
L ISTING 30.3 rtf.php—Script to Produce a Personalized RTF Certificate
<?
// check we have the parameters we need
Trang 6L ISTING 30.3 Continued
if( !$name || !$score ) {
echo “<h1>Error:</h1>This page was called incorrectly”;
} else { //generate the headers to help a browser choose the correct application header( “Content-type: application/msword” );
header( “Content-Disposition: inline, filename=cert.rtf”);
$date = date( “F d, Y” );
// open our template file
$filename = “PHPCertification.rtf”;
$fp = fopen ( $filename, “r” );
//read our template into a variable
$output = fread( $fp, filesize( $filename ) );
fclose ( $fp );
// replace the place holders in the template with our data
$output = str_replace( “<<NAME>>”, strtoupper( $name ), $output );
$output = str_replace( “<<Name>>”, $name, $output );
$output = str_replace( “<<score>>”, $score, $output );
$output = str_replace( “<<mm/dd/yyyy>>”, $date, $output );
// send the generated document to the browser echo $output;
}
?>
This script performs some basic error checking to make sure that all the user details have been passed in, and then moves to the business of creating the certificate
The output of this script will be an RTF file rather than an HTML file, so we need to alert the user’s browser to this fact This is important so that the browser can attempt to open the file with the correct application, or give a Save As… type dialog box if it doesn’t recognize the RTF extension
We specify the MIME type of the file we are outputting using PHP’s header()function to send the appropriate HTTP header as follows:
Trang 7header( “Content-type: application/msword” );
header( “Content-Disposition: inline, filename=cert.rtf”);
The first header tells the browser that we are sending a Microsoft Word file (not strictly true,
but the most likely helper application for opening the RTF file)
The second header tells the browser to automatically display the contents of the file, and that
its suggested filename is cert.rtf This is the default filename the user will see if he tries to save
the file from within his browser
After the headers are sent, we open and read our template RTF file into the $outputvariable,
and use thestr_replace()function to replace our placeholders with the actual data that we
want to appear in the file The line
$output = str_replace( “<<Name>>”, $name, $output );
will replace any occurrences of the placeholder <<Name>>with the contents of the variable
$name
Having made our substitutions, it’s just a matter of echoing the output to the browser
A sample result from this script is shown in Figure 30.5
30
F IGURE 30.5
rtf.phpgenerates a certificate from an RTF template.
Trang 8This approach works very well The calls to str_replace()run very quickly, even though our template and therefore the contents of $outputare fairly long The main problem from the point of view of this application is that the user will load the certificate in his word processor
in order to print it This is probably an invitation for people to modify the output RTF does not allow us to make a read-only document
Generating a PDF Certificate from a Template
The process of generating a PDF certificate from a template is very similar The main differ-ence is that when we create the PDF file, some of our placeholders might be interspersed with formatting codes For example, if we look in the certificate template file we have created, we can see that the placeholders now look like this:
<<N)-13(AME)-10(>)-6(>
<<Na)-9(m)0(e)-18(>>
<)-11(<)1(sc)-17(or)-6(e)-6(>)-11(>
<)-11(<)1(m)-12(m)0(/d)-6(d)-19(/)1(yy)-13(yy)-13(>>
If you look through the file, you will see that, unlike RTF, this is not a format that humans can easily read through
There are a few different ways we can deal with this
We could go through each of these placeholders and delete the formatting codes This actually makes fairly little difference to how the document looks in the end as the codes embedded in the previous template indicate how much space should be left between the letters of the place-holders that we are going to replace anyhow However, if we take this approach, we must go through and hand edit the PDF file and repeat this each time we change or update the file This
is not a big deal when dealing with only four placeholders, but it becomes a nightmare when, for example, you have multiple documents with many placeholders, and you decide to change the letterhead on all the documents
We can avoid this problem using a different technique You can use Adobe Acrobat to create a PDF form—similar to an HTML form with blank named fields You can then use a PHP script
to create what is called an FDF (Forms Data Format) file, which is basically a set of data to be merged with a template You can create FDFs using PHP’s FDF function library: specifically,
values; and the fdf_set_file()function to set the associated template form file You can then pass this file back to the browser with the appropriate MIME type, in this case vnd.fdf, and the browser’s Acrobat Reader plug-in should substitute the data into the form
Trang 9This is a neat way of doing things, but it has two limitations First, it assumes that you own a
copy of Acrobat Second, it is difficult to substitute in text that is inline rather than text that
looks like a form field This might or might not be a problem, depending on what you are
trying to do We have largely used PDF generation for generating letters where many things
must be substituted inline FDFs do not work well for this purpose If you are auto-filling for
example, a tax form online, this will not be a problem
You can read more about the FDF format at Adobe’s site:
http://www.adobe.com/support/techdocs/16196.htm
You should also look at the FDF documentation in the PHP manual if you decide to use this
approach:
http://www.php.net/manual/ref.fdf.php
We turn now to our PDF solution to the previous problem
We can still find and replace the placeholders in our PDF file if we recognize that the
addi-tional format codes consist solely of hyphens, digits, and parentheses and can therefore be
matched via a regular expression We have written a function,pdf_replace(), to automatically
generate a matching regular expression for a placeholder and replace that placeholder with the
appropriate text
Other than this addition, the code for generating the certificate via a PDF template is very
similar to the RTF version This script is shown in Listing 30.4
L ISTING 30.4 pdf.php—Script to Produce Personalized PDF Certificate Via a Template
<?
set_time_limit( 180 ); // this script can be very slow
function pdf_replace( $pattern, $replacement, $string )
{
$len = strlen( $pattern );
$regexp = ‘’;
for ( $i = 0; $i<$len; $i++ ) {
$regexp = $pattern[$i];
if ($i<$len-1)
$regexp = “(\)\-{0,1}[0-9]*\(){0,1}”;
} return ereg_replace ( $regexp, $replacement, $string );
}
30
Trang 10L ISTING 30.4 Continued
if(!$name||!$score) {
echo “<h1>Error:</h1>This page was called incorrectly”;
} else { //generate the headers to help a browser choose the correct application header( “Content-Disposition: filename=cert.pdf”);
header( “Content-type: application/pdf” );
$date = date( “F d, Y” );
// open our template file
$filename = “PHPCertification.pdf”;
$fp = fopen ( $filename, “r” );
//read our template into a variable
$output = fread( $fp, filesize( $filename ) );
fclose ( $fp );
// replace the place holders in the template with our data
$output = pdf_replace( “<<NAME>>”, strtoupper( $name ), $output );
$output = pdf_replace( “<<Name>>”, $name, $output );
$output = pdf_replace( “<<score>>”, $score, $output );
$output = pdf_replace( “<<mm/dd/yyyy>>”, $date, $output );
// send the generated document to the browser echo $output;
}
?>
This script produces a customized version of our PDF document The document, shown in Figure 30.6, will print reliably on numerous systems, and is harder for the recipient to modify
or edit You can see that the PDF document in Figure 30.6 looks almost exactly like the RTF document in Figure 30.5