orkestra / pdf-bundle
Provides integration between Symfony and PDF generation libraries
Installs: 1 500
Dependents: 1
Suggesters: 0
Security: 0
Stars: 2
Watchers: 5
Forks: 2
Open Issues: 1
Type:symfony-bundle
Requires
- php: >=5.3.0
- tecnick.com/tcpdf: ~6.0
This package is not auto-updated.
Last update: 2024-10-23 10:48:58 UTC
README
Abstracts different PDF generation libraries. Currently supports TCPDF, Zend PDF and wkhtmltopdf.
This bundle is under active development and is prone to backwards compatibility breaks.
Installation
Using composer, in your project's root directory:
composer require "orkestra/pdf-bundle 1.0.x-dev"
Update AppKernel.
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Orkestra\Bundle\PdfBundle\OrkestraPdfBundle(),
// ...
);
}
In addition, you should add TCPDF or Zend PDF to your project, as necessary.
If planning to use wkhtmltopdf, ensure it is installed on your system.
Configuration
No configuration is necessary, unless you want to change default settings.
Configuration defaults reference:
# config.yml orkestra_pdf: # Main cache directory cache_dir: %kernel.cache_dir%/orkestra_pdf tcpdf: # Path to the tcpdf installation root_dir: %kernel.root_dir%/../vendor/tecnick.com/tcpdf # Path to tcpdf fonts fonts_dir: %kernel.root_dir%/../vendor/tecnick.com/tcpdf/fonts # Path to tcpdf images image_dir: %kernel.root_dir%/../vendor/tecnick.com/tcpdf/images wkhtmltopdf: # Path to the wkhtmltopdf binary binary_path: wkhtmltopdf
Usage
This bundle's aim is to provide a uniform API for generating PDFs using different generation tools.
Currently supported: TCPDF, Zend PDF, and wkhtmltopdf.
Generators
The basis of this bundle revolves around services called "Generators". Generators know how to take
some input, such as entities and other data, and return a PDF ready to be used. Generators encapsulate
library-specific logic, returning a subtype of Orkestra\Bundle\PdfBundle\Pdf\PdfInterface
which can
then be used to send the generated PDF to the browser, save it to the filesystem, etc.
All Generators should implement PdfGeneratorInterface
. Additionally, a base class called
AbstractPdfGenerator
is included. This document details how to extend AbstractPdfGenerator
Creating an Invoice Generator
The two main methods to implement are: doGenerate
and setDefaultParameters
.
Implementing the doGenerate
method
This method actually performs the PDF generation. It takes two parameters, $parameters
and
$options
.
$parameters
is an array of data to be sent to the templating engine.$options
is an array of options to pass to the underlying PDF library.
Implementing the setDefaultParameters
method
This method configures an OptionsResolver
and allows specification of required and available
parameters that the Generator supports.
NOTE: There's also a setDefaultOptions
method available. Parameters are intended to be passed
to the templating engine, things like entities and collections. Options are intended to allow
configuration of the generator at runtime.
Example implementation: InvoiceGenerator
In this example, we use the WkPdf adapter and the built in templating engine to render a PDF.
<?php namespace MyBundle\PdfGenerator; use Orkestra\Bundle\PdfBundle\Generator\AbstractPdfGenerator; use Symfony\Component\OptionsResolver\OptionsResolver; class InvoiceGenerator extends AbstractPdfGenerator { /** * Performs the PDF generation * * @param array $parameters An array of parameters to be used to render the PDF * @param array $options An array of options to be passed to the underlying PdfFactory * * @return \Orkestra\Bundle\PdfBundle\Pdf\PdfInterface */ protected function doGenerate(array $parameters, array $options) { // Use the createPdf method to create the desired type of PDF $pdf = $this->createPdf('wkpdf', $options); // Call any native methods on the underlying library object $builder = $pdf->getNativeObject(); $builder->useTemporaryFile(); $builder->setInput($this->render('MyBundle:Pdf/Invoice:template.html.twig', $parameters)); // Return the original PDF, calling getContents to retrieve the rendered content return $pdf; } /** * Configure the parameters OptionsResolver. * * Use this method to specify default and required options * * @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver */ protected function setDefaultParameters(OptionsResolver $resolver) { $resolver->setRequired(array( 'invoice', )); $resolver->setAllowedTypes(array( 'invoice' => 'MyBundle\Entity\Invoice', )); } }
Useful methods
AbstractPdfGenerator->createPdf($type, $options)
wraps the PDF factory registry. As the first
parameter, pass the type of PDF and options to configure it. Available PDF types: tcpdf
, wkpdf
,
and zendpdf
.
AbstractPdfGenerator->render($template, array $parameters = array())
uses the application's templating
engine to render templates for use in generating the content for the PDF.
Registering your generator
In services.yml:
my_bundle.invoice_pdf_generator: class: MyBundle\PdfGenerator\InvoiceGenerator arguments: [ @orkestra.pdf.factory_registry, @templating ]
AbstractPdfGenerator
by default, takes a PDF factory registry and the templating service. You may
need to add more dependencies, depending on your implementation.
Using your service
From within one of your controllers:
class MyController extends Controller { // ... public function someAction() { // Fetch the invoice from somewhere $invoice = $this->getInvoice(); $generator = $this->get('my_bundle.invoice_pdf_generator'); $pdf = $generator->generate(array('invoice' => $invoice)); // Write the PDF to a file file_put_contents('/some/path/to.pdf', $pdf->getContents()); // Output the PDF to the browser return new Response($pdf->getContents(), 200, array('Content-type' => 'application/pdf')); } }
Strategies
Using TCPDF to render template fragments
TCPDF can be difficult to use, especially when rendering HTML. Usually, the easiest way is to
position different smaller sections of the page, making multiple writeHTML
or writeHTMLCell
calls on the TCPDF object.
Here's an example of the same Invoice Generator from before.
class InvoiceGenerator extends AbstractPdfGenerator { protected function doGenerate(array $parameters, array $options) { $pdf = $this->createPdf('tcpdf', $options); /** @var \TCPDF $builder */ $builder = $pdf->getNativeObject(); $builder->addPage(); $builder->writeHtmlCell(0, 0, 0, 20, $this->render('MyBundle:Pdf/Invoice:invoiceHead.html.twig', $parameters)); $builder->writeHtmlCell(0, 0, 20, 43, $this->render('MyBundle:Pdf/Invoice:invoiceIntro.html.twig', $parameters)); $builder->writeHtmlCell(0, 0, 20, 66, $this->render('MyBundle:Pdf/Invoice:invoiceBody.html.twig', $parameters)); $builder->writeHtmlCell(0, 0, 20, 165, $this->render('MyBundle:Pdf/Invoice:invoiceFooter.html.twig', $parameters)); $builder->line(0, 190.5, 215.9, 190.5, array('dash' => 3)); $builder->writeHtmlCell(0, 0, 21, 200, $this->render('MyBundle:Pdf/Invoice/Detachment:detachmentCompany.html.twig', $parameters)); $builder->writeHtmlCell(0, 0, 0, 200, $this->render('MyBundle:Pdf/Invoice/Detachment:detachmentHead.html.twig', $parameters)); $builder->writeHtmlCell(0, 0, 19.5, 230, $this->render('MyBundle:Pdf/Invoice/Detachment:detachmentInfo.html.twig', $parameters)); $builder->writeHtmlCell(0, 0, 22, 210, $this->render('MyBundle:Pdf/Invoice/Detachment:detachmentDetails.html.twig', $parameters)); return $pdf; } }
See TCPDF documentation for more details.
Using custom subclasses with TCPDF
TCPDF offers the ability to extend the TCPDF class directly to implement, for example, page headers and footers.
The default TcPdfFactory
lets you specify a custom subclass by specifying the 'className'
option when creating a PDF. For example:
class MySpecialGenerator extends AbstractPdfGenerator { protected function doGenerate(array $parameters, array $options) { $options['className'] = 'My\Bundle\CustomTcpdf'; $pdf = $this->createPdf('tcpdf', $options); /** @var \My\Bundle\CustomTcpdf $builder */ $builder = $pdf->getNativeObject(); // Use your custom subclass as necessary... return $pdf; } }
Notice that $builder
in the example above is an instance of My\Bundle\CustomTcpdf
.