Using TCPDF with Symfony 2

Using TCPDF with Symfony2 is pretty simple. However there are a few problems that may arise.

namespace Acme\DemoBundle\Controller;

class PdfController extends Controller
{
    public function pdfAction()
    {
        $pdf = new \TCPDF();

        // Construct the PDF.

        $pdf->Output('filename.pdf');
    }
}

Easy enough. The PDF loads, but we get this error in the logs:

request.CRITICAL: Uncaught PHP Exception LogicException: "The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?"

We can fix that:

namespace Acme\DemoBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class PdfController extends Controller
{
    public function pdfAction()
    {
        $pdf = new \TCPDF();

        // Construct the PDF.

        $pdf->Output('filename.pdf');

        return new Response(); // To make the controller happy.
    }
}

Add some authentication and remember me tokens, close the browser, relaunch the browser, and visit the PDF page. We get a new error:

request.CRITICAL: Uncaught PHP Exception RuntimeException: "Failed to start the session because headers have already been sent by "[...]/vendor/tecnick.com/tcpdf/include/tcpdf_static.php"

Darn. TCPDF::Output() sends headers before Symfony has the chance. We can fix that too:

namespace Acme\DemoBundle\Controller;

use Symfony\Component\HttpFoundation\StreamedResponse;

class PdfController extends Controller
{
    public function pdfAction()
    {
        $pdf = new \TCPDF();

        // Construct the PDF.

        return new StreamedResponse(function () use ($pdf) {
            $pdf->Output('filename.pdf');
        });
    }
}

Perfect. Now Symfony and TCPDF::Output() can both send their headers, and everything plays nice.