You should download the ZIP archive of the entire project to get the full code listing and to try it out.


rml-sample-php.zip

(3.3 KB, 18 Mar 2010, md5 checksum=38f9fff2dae7ad16ebfd6cd47c1bf3e3)


Introduction

Report Markup Language™ is an XML-style language created by ReportLab that describes the precise look of a printed page. This sample application shows how you can use the RML2PDF conversion library from within PHP.

RML is commercial software which is part of the ReportLab PLUS package. You will need to create a user account to download a trial version of ReportLab PLUS.

This is a sample project which takes user input from an HTML form and generates a PDF containing what the user submitted. An RML file is read which contains the structure of the PDF document. A simple 'str_replace' replaces a variable name in the RML source with the value submitted by the user.

A similar principal could be used for generating personalised documents and mail merges by adding more fields such as address and post/zip code. For more advanced uses such as conditionals and for loops, users will probably want make use of a template engine such as Smarty or ReportLab's own Preppy text pre-processor.

Code overview

Here are some explanations of the most interesting parts of the sample application. The downloadable archive also contains a README file and commented code.

First of all index.php has some constants defined. You will want to set $RML2PDF_DIR to your own location. Windows users will also probably need to change $PYTHON to the location of python.exe.

<?php

$PYTHON = "python";  # You can use a custom python build/version
$PYTHONPATH = "\$PYTHONPATH";  # Override PYTHONPATH if you installed somewhere unusual
$RML2PDF_DIR = "/path/to/rlextra/rml2pdf/";  # Where you installed rlextra
$RML2PDF_EXE = "rml2pdf.pyc";  # RML2PDF compiled python file
$RML_INPUT = "hello.rml";  # RML document source
$RML_OUTPUT = "output.rml";  # temporary location for RML after template processing

...

There are two ways the script can be called. If a GET parameter is supplied, generate and return a PDF, otherwise show a form where the user can fill in their name.

if ($_GET['q']) {
    # Create a PDF using 'q' variable and send it to the browser
}
else {
    # This is what initially will get returned - HTML with a form for the user to enter their name
?>
...
    <form action="." method="get">
        <input type="text" name="q" />
        <input type="submit" value="Make a PDF" />
    </form>
...
<?php
}
...

The getRML() function takes a source RML XML file $RML_INPUT, replaces the occurrence ##NAME## with the supplied variable $name (GET parameter q in this case), then finally writes out the resulting string into the file named $RML_OUTPUT. This is the simplest way to make the content dynamic but you are expected to use another template system if you require more advanced features like conditionals and loops.

function getRML($RML_INPUT, $RML_OUTPUT, $name) {
    # Get content of the RML file
    $rml = file_get_contents($RML_INPUT) or die("Can't open input RML file $RML_INPUT");

    # Replace special string '##NAME##' with the variable submitted as GET request
    # This is the simplest example of templating. You can use your preferred templating system here instead (e.g. Smarty or Preppy) for more control such as iteration loops.
    $rml = str_replace("##NAME##", $name, $rml);

    # Write the new RML string to a temporary file so it can be passed in as an argument to the RML2PDF script
    $fh = fopen($RML_OUTPUT, 'w') or die("Can't open output RML file $RML_OUTPUT");
    fwrite($fh, $rml);
    fclose($fh);

    return $RML_OUTPUT;
}

When we receive our GET parameter q, call getRML(), then pass the the generated RML file along with other parameters to the rml2pdf script on the command line. We then read in the generated PDF file and return it to the browser with the correct mime/content types. If we do not set these, PHP will assume we are returning text/html and the browser will try and display binary data.

# Call function that reads RML file and does templating replacements
$rml_fn = getRML($RML_INPUT, $RML_OUTPUT, $_GET['q']);

# Execute the python command with rml2pdf.pyc and relevant arguments 
exec("PYTHONPATH=$PYTHONPATH $PYTHON $RML2PDF_DIR$RML2PDF_EXE $rml_fn");

# Output file name
$fn = str_replace(".rml", ".pdf", $RML_INPUT);

# Check a PDF file was created
$fh = fopen($RML_OUTPUT, 'r') or die("Can't open  PDF file $fn");
fclose($fh);

# Send PDF file to browser and appropriate headers
header("Content-type: application/pdf");
header("Content-disposition: attachment; filename=$fn");
readfile($fn);