Installation
Run composer require borsaco/tcpdf-bundle in your Symfony project.
Ensure your Symfony version is compatible (last release was 2019, so test thoroughly if using newer versions).
Enable the Bundle
Add new Borsaco\TCPDFBundle\TCPDFBundle() to registerBundles() in AppKernel.php (or Kernel.php for Symfony 4+).
First Use Case: Generate a Basic PDF
Inject the tcpdf service and create a PDF object:
use Symfony\Component\DependencyInjection\ContainerInterface;
public function generatePdf(ContainerInterface $container)
{
$pdf = $container->get('tcpdf')->create();
$pdf->AddPage();
$pdf->SetFont('helvetica', 'B', 12);
$pdf->Cell(0, 10, 'Hello, TCPDF in Symfony!', 0, 1, 'C');
return $pdf->Output('example.pdf', 'I'); // 'I' forces download
}
Where to Look First
config/packages/tcpdf.yaml (auto-generated) for customization options.Borsaco\TCPDFBundle\DependencyInjection\TCPDFExtension.php for configuration logic.PDF Generation in Controllers
Use dependency injection for the tcpdf service:
public function generateReportPdf(TCPDFService $tcpdfService)
{
$pdf = $tcpdfService->create();
// Customize PDF (AddPage, SetFont, Cell, etc.)
return $pdf->Output('report.pdf', 'D'); // 'D' downloads file
}
Tip: Register the service as a controller argument in Symfony 4+ via services.yaml:
services:
App\Controller\ReportController:
arguments:
$tcpdfService: '@tcpdf'
Reusable PDF Classes
Extend TCPDF in a custom class (e.g., src/Service/CustomTCPDF.php):
namespace App\Service;
use TCPDF;
class CustomTCPDF extends TCPDF
{
public function addCompanyHeader()
{
$this->SetFont('helvetica', 'B', 12);
$this->Cell(0, 10, 'My Company', 0, 1, 'C');
}
}
Configure the bundle to use it in config/packages/tcpdf.yaml:
tcpdf:
class: 'App\Service\CustomTCPDF'
Streaming PDFs to Browser
Use Output() with 'I' (inline) to display PDFs directly:
$pdf->Output('invoice.pdf', 'I');
For large files, stream chunks to avoid memory issues:
$pdf->Output('large_report.pdf', 'S'); // 'S' sends raw bytes
Dynamic Content Injection Pass data to templates (e.g., Twig) and merge it into PDFs:
$pdf->writeHTML($this->twig->render('pdf/template.html.twig', ['data' => $data]));
tcpdf.writeHTML() with Twig-rendered strings for dynamic content.Filesystem or Flysystem:
$pdf->Output('path/to/file.pdf', 'F'); // 'F' saves to file
tcpdf service in PHPUnit:
$this->container->get('tcpdf')->expects($this->once())->method('create')->willReturn($mockPdf);
Memory Limits
Output('S') for streaming or optimize content (e.g., compress images).memory_limit in php.ini) or split PDF generation into chunks.Deprecated Symfony Versions
ServiceLocator or a modern wrapper like spatie/pdf.Configuration Overrides
TCPDF. The bundle throws an exception if invalid:
// Throws: "Class must extend TCPDF"
tcpdf:
class: 'App\Service\InvalidClass'
TCPDF programmatically:
if (!is_a($customClass, TCPDF::class, true)) {
throw new \RuntimeException('Custom class must extend TCPDF');
}
Font Paths
helvetica.ttf). Ensure they are accessible or configure custom paths:
tcpdf:
font_paths: ['%kernel.project_dir%/vendor/tcpdf/fonts']
Service Container Access
// Bad (direct container access)
$pdf = $this->container->get('tcpdf')->create();
// Good (autowired service)
public function __construct(private TCPDFService $tcpdfService) {}
Check TCPDF Errors Enable TCPDF error reporting:
$pdf = $tcpdfService->create();
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->ErrorMode = 'return'; // Return errors as strings instead of throwing exceptions
Log PDF Generation Issues Wrap PDF generation in a try-catch block:
try {
$pdf->Output('file.pdf', 'F');
} catch (\Exception $e) {
$this->logger->error('PDF generation failed: ' . $e->getMessage());
throw $e;
}
Verify Output
'D' (download) for debugging to inspect the generated PDF locally.$pdf->lastError(); // Returns the last error message
Custom Commands Create a Symfony command to generate PDFs in bulk:
namespace App\Command;
use Borsaco\TCPDFBundle\Service\TCPDFService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class GeneratePdfCommand extends Command
{
protected static $defaultName = 'app:generate-pdf';
public function __construct(private TCPDFService $tcpdfService) {}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$pdf = $this->tcpdfService->create();
// Generate PDF logic
$pdf->Output('command.pdf', 'D');
return Command::SUCCESS;
}
}
Event Listeners Trigger PDF generation on entity events (e.g., post-save):
namespace App\EventListener;
use App\Entity\Order;
use Borsaco\TCPDFBundle\Service\TCPDFService;
use Doctrine\ORM\Event\LifecycleEventArgs;
class OrderPdfListener
{
public function __construct(private TCPDFService $tcpdfService) {}
public function postPersist(Order $order, LifecycleEventArgs $args)
{
$pdf = $this->tcpdfService->create();
// Generate PDF for $order
$pdf->Output("order_{$order->getId()}.pdf", 'F');
}
}
Twig Extensions Create a Twig extension to generate PDFs from templates:
namespace App\Twig;
use Borsaco\TCPDFBundle\Service\TCPDFService;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class PdfExtension extends AbstractExtension
{
public function __construct(private TCPDFService $tcpdfService) {}
public function getFunctions(): array
{
return [
new TwigFunction('generate_p
How can I help you explore Laravel packages today?