<< back
Using PD4ML with Zend Framework 2 (ZF2)
Prerequisites
For this example we are going to use Albums sample application
explained in ZF2 tutorial. We recommend to follow the tutorial steps first, to get the demo application up
and running.
After you did that, download pd4ml_php_wrapper, unpack it to the application root. A directory
structure should look like on the picture:
Make sure Java runtime is installed on the server and php.ini enables
external processes execution. Try to run the just installed PD4ML PHP wrapper
demo. See http://old.pd4ml.com/php.htm
An adding of "Page as PDF" button to a view
In the sample we plan add "Page as PDF" button to the list of albums. "Page as PDF" feature probably makes not much prcatical sense;
it just shows the main configuration/adjustment steps. In real life use cases you would probably only need to create a print-optimized report or invoice view with a known URL
and to point PD4ML converter action directly to it, skipping the below tricks with HTTP refferer.
1. Add a pdf generation link to the list of albums view
module/Album/view/album/album/index.phtml
...
</tr>
<?php endforeach; ?>
<!-- edit begin -->
<tr style="pd4ml-display: none">
<td> </td>
<td> </td>
<td>
<a href="<?php echo $this->url('album', array('action'=>'pdf'));?>">Page as PDF</a>
</td>
</tr>
<!-- edit end -->
</table>
(An added section is inbetween edit begin and edit end comments).
pd4ml-display: none style is applied to the added code to hide the
link in the generated PDF as it may look confusing there.
A list of albums should look like that now:
The link refers to a new, currently not handled action pdf
2. Add pdf action handler to module/Album/src/Album/Controller/AlbumController.php
public function pdfAction()
{
$url = $this->getRequest()->getHeader('Referer')->getUri();
$enc = base64_encode($url);
$this->redirect()->toUrl($this->getRequest()->getBaseUrl() . '/pd4ml.php?url=' . $enc);
}
The handler takes a referrer page URL (in our case it is an URL of an album list) and forwards it to PDF converter page as url parameter. In order to avoid possible troubles with special characters,
it base64-encodes the URL.
3. The redirect command in the step above assumes an existence of
pd4ml.php converter script in public/ directory. Create it:
<?php
$evaluation = 1;
$java = "java";
$url = base64_decode($_GET['url']) . '?layout=pdf';
if ( $evaluation == 1 ) {
$jar = "../pd4ml_php_wrapper/pd4ml_demo.jar";
} else {
$jar = "../pd4ml_php_wrapper/pd4ml.jar";
}
header("Pragma: cache");
header("Expires: 0");
header("Cache-control: private");
header('Content-type: application/pdf');
header('Content-disposition: inline');
if ( strpos(php_uname(), 'Windows' ) !== FALSE) {
// server platform: Windows
$jar = preg_replace('/\//', "\\", $jar);
$cmdline = "$java -Xmx512m -cp $jar Pd4Cmd \"$url\" 800 A4";
} else {
// server platform: UNIX-derived
$cmdline = "$java -Xmx512m -Djava.awt.headless=true -cp $jar Pd4Cmd \"$url\" 800 A4";
}
// see for more command-line parameters: http://old.pd4ml.com/html-to-pdf-command-line-tool.htm
passthru( $cmdline );
?>
Make sure there is no whitespaces before <?php and after ?>
The script reads url parameter, decodes it, converts a decoded URL to
a PDF and sends the generated PDF bytes to HTTP. Also, as you may see, the script
appends to the URL ?layout=pdf parameter: we'll use it to signal the application to
optimize the page layout for PDF rendering.
4. The original album list view includes a navigation bar, which
is great for an interactive web application, but makes not much sense in a PDF
document (or by print). For the case we'll create a lightweight layout template,
with a navigation bar removed. The best way would be to copy-paste the default
module/Application/view/layout/layout.phtml to the same directory under
blank.phtml name. After a navigation removal the template looks like
that:
<?php echo $this->doctype(); ?>
<html lang="en">
<head>
<meta charset="utf-8">
<?php echo $this->headTitle('ZF2 '. $this->translate('Skeleton Application'))->setSeparator(' - ')->setAutoEscape(false) ?>
<?php echo $this->headMeta()->appendName('viewport', 'width=device-width, initial-scale=1.0') ?>
<!-- Le styles -->
<?php echo $this->headLink(array('rel' => 'shortcut icon', 'type' => 'image/vnd.microsoft.icon', 'href' => $this->basePath() . '/images/favicon.ico'))
->appendStylesheet($this->basePath() . '/css/bootstrap.min.css')
->appendStylesheet($this->basePath() . '/css/style.css')
->appendStylesheet($this->basePath() . '/css/bootstrap-responsive.min.css') ?>
<!-- Scripts -->
<?php echo $this->headScript()->appendFile($this->basePath() . '/js/html5.js', 'text/javascript', array('conditional' => 'lt IE 9',))
->appendFile($this->basePath() . '/js/jquery-1.7.2.min.js') ?>
</head>
<body>
<div class="container">
<br>
<?php echo $this->content; ?>
</div>
</body>
</html>
5. Register the new template in the module config file module/Album/config/module.config.php
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
// edit begin
'template_map' => array(
'layout/blank' => __DIR__ . '/../view/layout/blank.phtml',
),
// edit end
6. Add a template switch to index action handler of module/Album/src/Album/Controller/AlbumController.php:
public function indexAction()
{
// edit begin
$flag = $this->params()->fromQuery('layout');
if ('pdf' == $flag) {
$layout = $this->layout();
$layout->setTemplate('layout/blank');
}
// edit end
return new ViewModel(array(
'albums' => $this->getAlbumTable()->fetchAll(),
));
}
The code checks an URL for a parameter layout=pdf and, if defined, switches a view. Now a click to "Page as PDF" link should generate and open a PDF like
this.
You may download the complete application structure (excluding pd4ml_php_wrapper)
by the link.
(Do not forget to adjust database access credentials in config/autoload/local.php)
|