Reputation: 165
I'm generating a list (some sort of appointment card for students) with PHP. I want to be able to save this as a PDF. I've successfully tried some basic layout with PHP and DOMPDF.
When I try to save the following as a PDF it does not work.
<?php
session_start();
// User session check
if(!$_SESSION['email'])
{
header("Location: login.php");//redirect to login page to secure the welcome page without login access.
}
include("php/getCustomerEvents.php");
// get row id = student id
$id = $_GET[id];
// check user language
$lang = $_SESSION['lang'];
switch ($lang)
{
case 'en':
$lang_file = 'lang.en.php';
break;
//case 'fr':
//$lang_file = 'lang.fr.php';
//break;
case 'nl':
$lang_file = 'lang.nl.php';
break;
default:
$lang_file = 'lang.nl.php';
}
include_once 'lang/'.$lang_file;
// Debug code
//print_r($_SESSION);
//echo "----------------------------------------------------------------------->".$_SESSION['lang']." = taal <br>";
//echo "----------------------------------------------------------------------->".$_SESSION['name']." = naam <br>";
//echo "----------------------------------------------------------------------->".$_SESSION['resource']." = id <br>";
//Echo "----------------------------------------------------------------------->".$_SESSION['admin']." = admin <br>";
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="css/bootstrap-select.css">
<style type="text/css">
.bs-example{
margin: 20px;
}
/* Fix alignment issue of label on extra small devices in Bootstrap 3.2 */
.form-horizontal .control-label{
padding-top: 7px;
}
</style>
</head>
<body >
<!-- Main content -->
<section class="content" >
<!-- Your Page Content Here -->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php echo $lang['LBL_LIST_EVENTS']; ?></h3>
</div><!-- /.box-header -->
<div class="box-body">
<table id="instructors" class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th><?php echo $lang['LBL_LESSON']; ?></th>
<th><?php echo $lang['LBL_LOCATION']; ?></th>
<th><?php echo $lang['LBL_TITLE']; ?></th>
<th><?php echo $lang['LBL_EVENT_START']; ?></th>
<th><?php echo $lang['LBL_EVENT_END']; ?></th>
</tr>
</thead>
<tbody>
<?php customerevents($id); ?><!-- function from getCustomerEvents.php -->
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-success" ><span class="glyphicon glyphicon-print" aria-hidden="true"></span> PDF </button>
<button type="submit" class="btn btn-success" ><span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> MAIL </button>
</div><!-- /.box-footer -->
</div><!-- /.box -->
</div><!-- /.col -->
</div><!-- /.row -->
</section><!-- /.content -->
<!-- Main Footer -->
<footer class="main-footer">
<!-- To the right -->
<div class="pull-right hidden-xs">
</div>
<!-- Default to the left -->
<strong>Copyright © 2015 <a href="http:\\www.biqsit.be">biqs it</a>.</strong> All rights reserved.
</footer>
</body>
</html>
The code I use to generate the PDF:
<?php
require_once("../dompdf/dompdf_config.inc.php");
//$content = "../" . $_GET["content"];
//$file_name = $_GET["file_name"];
$dompdf = new DOMPDF();
//$html = file_get_contents($content);
$html = file_get_contents('../pdf_customer_events.php');
$dompdf->load_html($html);
$dompdf->render();
$dompdf->stream("sample.pdf");
?>
What am i doing wrong? Or is DOMPDF not the right solution?
Upvotes: 3
Views: 5707
Reputation: 6478
To convert a file that does not contain any dependancy, you can get the content and give it to the convertion library.
$html = file_get_contents('pregenerated.html');
This method does not allow to pass variables that can be needed (session/POST...).
By bufferizing the content, you avoid to send it to the browser, it can then be given to the library.
ob_start();
include('content.php');
$html = ob_get_clean();
This way you can transmit session/post/get like you would normally do, and you can even handle errors correctly. You can also use templating engine for advanced output.
By including the php script, all sub files (scripts, css, iframes, ...) are not included. So for simple pdf that does not include image, you need to get everything in one page.
Quite not maintenable ... but feasable.
So, fortunatly there is some php tools that do interpret the page and can fetch any sub files. The most common is wkhtmltopdf, which is a binary that include Chrome's rendering engine webkit
to interpret the page and print the pdf.
And for that, you can give him the content like the previous example, or give an url. You can control the printing (margins, colors ...).
It have many php wrappers to make it easy to use in your code.
But (there is always a but...) wkhtmltopdf
does not use a recent engine of webkit
, which can be annoying if like in my company you enjoy slick css3 and javascript canvas features.
What we made was to use headless browser, to render the page as a browser and print it in pdf (which is already what does wkhtmltopdf with great optimisations and features).
The most advanced headless browser is probably PhantomJS. Based on Webkit, it can print in many formats easily.
And it have a PHP wrapper: http://jonnnnyw.github.io/php-phantomjs/
var webPage = require('webpage');
var page = webPage.create();
page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.google.com", function start(status) {
page.render('google_home.jpeg', {format: 'jpeg', quality: '100'});
phantom.exit();
});
Side note: In our company we use SlimerJS because it offers better output back in the days we build the service, this is only a concern because our pages were not made to be consistent accross browsers and the conversion messed up some part...
When we developed the service, SlimerJS did not provide full PDF printing support until 0.10 release that was in developement. So we had to compile it ourself with latest xulrunner
.
Upvotes: 5
Reputation: 165
Thanks to @Cyrbil I came to the working code below. Still having a problem with the CSS which causes the PDF to fail. From what I've found it has something to do with the bootstrap.css. Already tried to remove *before and after but still no PDF render. But I probably should post this as a new question.
<?php
session_start();
require_once("dompdf/dompdf_config.inc.php");
// User session check
// if(!$_SESSION['email'])
// {
// header("Location: login.php");//redirect to login page to secure the welcome page without login access.
// }
include("php/getCustomerEvents.php");
// get row id = student id
$id = $_GET["id"];
//check user language
$lang = $_SESSION['lang'];
switch ($lang)
{
case 'en':
$lang_file = 'lang.en.php';
break;
case 'fr':
$lang_file = 'lang.fr.php';
break;
case 'nl':
$lang_file = 'lang.nl.php';
break;
default:
$lang_file = 'lang.nl.php';
}
include_once 'lang/'.$lang_file;
ob_start(); // start output buffer
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<!--link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" /-->
<link href="css/biqs_print_bootstrap.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="css/bootstrap-select.css">
<style type="text/css">
.bs-example{
margin: 20px;
}
/* Fix alignment issue of label on extra small devices in Bootstrap 3.2 */
.form-horizontal .control-label{
padding-top: 7px;
}
tbody:before, tbody:after { display: none; }
</style>
</head>
<body >
<!-- Main content -->
<section class="content" >
<!-- Your Page Content Here -->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php echo $lang['LBL_LIST_EVENTS']; ?></h3>
</div><!-- /.box-header -->
<div class="box-body">
<table id="instructors" class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th><?php echo $lang['LBL_LESSON']; ?></th>
<th><?php echo $lang['LBL_LOCATION']; ?></th>
<th><?php echo $lang['LBL_TITLE']; ?></th>
<th><?php echo $lang['LBL_EVENT_START']; ?></th>
<th><?php echo $lang['LBL_EVENT_END']; ?></th>
</tr>
</thead>
<tbody>
<?php customerevents($id); ?><!-- function from getCustomerEvents.php -->
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
</div><!-- /.box-footer -->
</div><!-- /.box -->
</div><!-- /.col -->
</div><!-- /.row -->
</section><!-- /.content -->
<!-- Main Footer -->
<footer class="main-footer">
<!-- To the right -->
<div class="pull-right hidden-xs">
</div>
<!-- Default to the left -->
<strong>Copyright © 2015 <a href="http:\\www.biqsit.be">biqs it</a>.</strong> All rights reserved.
</footer>
</body>
</html>
<?php
$html = ob_get_contents();
ob_end_clean();
$dompdf = new DOMPDF();
$dompdf->load_html($html);
$dompdf->render();
$dompdf->stream("sample.pdf");
echo $html;
?>
Upvotes: 1