Creating PDF files with CakePHP and TCPDF

by kalileo
With CakePHP 1.2 creating PDFs with CakePHP has just gotten a lot easier. This tutorial shows how to combine CakePHP and the powerful TCPDF for easy PDF file creation.

TCPDF is an Open Source PHP class for generating PDF documents. It continues where FPDF stopped, and contains all its goodies plus support of UTF-8 Unicode and Right-To-Left languages! Especially the missing UTF-8 Unicode support in FPDF is a problem for everyone living outside the English language only countries.


Step 1: Download and install TCPDF

  1. Go to http://www.tcpdf.org and download the latest version of TCPDF.
  2. Extract to one of your vendors folders, such as app/vendors. It will create a directory tcpdf there with tcpdf.php and more in it. You need at least the folders tcpdf/config and tcpdf/fonts in your application.
  3. Configure TCPDF, see its documentation. You want at least to have a look at tcpdf/config/tcpdf_config.php.

Step 2: Extend TCPDF to customize your header and footer

There is a default header and footer in TCPDF, defined in a header() and a footer() method, which is supposed to be overwritten by you, if needed. This can be done by extending TCPDF and then calling this extended TCPDF class from your application.


In app/vendors create the file xtcpdf.php with this content:

<?php
App
::import('Vendor','tcpdf/tcpdf');

class 
XTCPDF  extends TCPDF
{

    var 
$xheadertext  'PDF created using CakePHP and TCPDF';
    var 
$xheadercolor = array(0,0,200);
    var 
$xfootertext  'Copyright Â© %d XXXXXXXXXXX. All rights reserved.';
    var 
$xfooterfont  PDF_FONT_NAME_MAIN ;
    var 
$xfooterfontsize ;


    
/**
    * Overwrites the default header
    * set the text in the view using
    *    $fpdf->xheadertext = 'YOUR ORGANIZATION';
    * set the fill color in the view using
    *    $fpdf->xheadercolor = array(0,0,100); (r, g, b)
    * set the font in the view using
    *    $fpdf->setHeaderFont(array('YourFont','',fontsize));
    */
    
function Header()
    {

        list(
$r$b$g) = $this->xheadercolor;
        
$this->setY(10); // shouldn't be needed due to page margin, but helas, otherwise it's at the page top
        
$this->SetFillColor($r$b$g);
        
$this->SetTextColor(00);
        
$this->Cell(0,20''0,1,'C'1);
        
$this->Text(15,26,$this->xheadertext );
    }

    
/**
    * Overwrites the default footer
    * set the text in the view using
    * $fpdf->xfootertext = 'Copyright Â© %d YOUR ORGANIZATION. All rights reserved.';
    */
    
function Footer()
    {
        
$year date('Y');
        
$footertext sprintf($this->xfootertext$year);
        
$this->SetY(-20);
        
$this->SetTextColor(000);
        
$this->SetFont($this->xfooterfont,'',$this->xfooterfontsize);
        
$this->Cell(0,8$footertext,'T',1,'C');
    }
}
?>

Of course, customize this to show your organization's name etc., and modify the code as you like. See the TCPDF documentation for details.


Step 3: Create your layout for PDF

You cannot use your default layout, as it would wrap the PDF file in your HTML page code. You need a layout such as this one, save it as app/views/layouts/pdf.ctp :

<?php
header
("Content-type: application/pdf");
echo 
$content_for_layout;
?>

Step 4: For your Controller

In your controller you will have a method which will output the PDF. This here is the code as it is used in one of my real world applications to print a nice PDF page with data and pictures about a property:



    function viewPdf($id = null)
    {
        if (!$id)
        {
            $this->Session->setFlash('Sorry, there was no property ID submitted.');
            $this->redirect(array('action'=>'index'), null, true);
        }
        Configure::write('debug',0); // Otherwise we cannot use this method while developing

        $id = intval($id);

        $property = $this->__view($id); // here the data is pulled from the database and set for the view

        if (empty($property))
        {
            $this->Session->setFlash('Sorry, there is no property with the submitted ID.');
            $this->redirect(array('action'=>'index'), null, true);
        }

        $this->layout = 'pdf'; //this will use the pdf.ctp layout
        $this->render();
    }

Adapt to your needs. The critical part is just to select the PDF layout before rendering.


        $this->layout = 'pdf'; //this will use the pdf.ctp layout
        $this->render();

Step 5: For your View


Here is where the magic happens. Because with CakePHP we can load the vendor directly in the view we do not need to wrap it in a helper. So the big TCPDF library with currently 9600 lines of code in the main class tcpdf.php alone will only get loaded when we really need it, that is when we actually create the PDF file. The vendor is now used here like an external helper. Note: I do not know if that was intended or not, but the more I think about it the more I like it, it's so elegant and efficient, and demonstrates the power and flexibility of CakePHP.


But enough said, here's the code for the view:


View Template:


<?php
App
::import('Vendor','xtcpdf'); 
$tcpdf = new XTCPDF();
$textfont 'freesans'// looks better, finer, and more condensed than 'dejavusans'

$tcpdf->SetAuthor("KBS Homes & Properties at http://kbs-properties.com");
$tcpdf->SetAutoPageBreakfalse );
$tcpdf->setHeaderFont(array($textfont,'',40));
$tcpdf->xheadercolor = array(150,0,0);
$tcpdf->xheadertext 'KBS Homes & Properties';
$tcpdf->xfootertext 'Copyright Â© %d KBS Homes & Properties. All rights reserved.';

// add a page (required with recent versions of tcpdf)
$tcpdf->AddPage();

// Now you position and print your page content
// example: 
$tcpdf->SetTextColor(000);
$tcpdf->SetFont($textfont,'B',20);
$tcpdf->Cell(0,14"Hello World"0,1,'L');
// ...
// etc.
// see the TCPDF examples 

echo $tcpdf->Output('filename.pdf''D');

?>

That was easy! Yes, that's all.


The Questions and Answers below are only of interest for users of the FPDF helper.


Why not FPDF?

For me the main reason is that there is no Unicode support. You can add a limited unicode support to it, as described on the Dievolution blog, by hacking the Cell method of FPDF, but then, why not go for TCPDF right away. No hack needed, and the TCPDF author, Nicola Asuni, is very active, releasing a new update almost every week.

Update: FPDF seems to have full Unicode now, but I haven't tested it. Also development seems to be going on nicely.


How about the FPDF helper, as shown here in the bakery?

I used this helper quite a lot, it worked fine with CakePHP 1.1. Somewhere between the 1.2 beta and 1.2 RC it stopped working though. The reason IMHO is that it is not implemented correctly.

It extends the FPDF class directly, but a Helper should extend a Helper, such as the AppHelper class.


This is what the FPDF helper does, works worked with CakePHP 1.1, but wrong:

class FpdfHelper extends FPDF

This would be correct but it does not work:

class FpdfHelper  extends AppHelper

Somewhere in the CakePHP 1.2 development a change happened which was that helpers receive an array as first argument when they are initialized. A Helper which extends AppHelper expects that and handles it correctly, but FPDF does not know what to do with that array, as it expects as first argument the page orientation.


Can the FPDF Helper be hacked to continue working with CakePHP 1.2?

Yes, it can, but this should be not the solution, as it is not needed (as shown above). Simply add this line in the FPDF code (the one in your vendors directory, not the helper), as first line of the FPDF method, which is in my FPDF version at line 78:

if (is_array($orientation)) return;
it will then be:

function FPDF($orientation='P',$unit='mm',$format='A4')
{
    if (is_array($orientation)) return;
    ...

This will make it ignore the Helper initialization, but let it run fine when it is called later, via

$this->FPDF($orientation, $unit, $format); 

in the FPDF helper's setup() method.


Why is this FPDF hack not needed in CakePHP 1.2?

FPDF and TCPDF are external libraries, which you can integrate in CakePHP under Vendors. Now CakePHP 1.2 changed the way Vendors are included from


vendor("fpdf/fpdf")  to
App::import('Vendor','fpdf/fpdf');
- or for TCPDF: - 
App::import('Vendor','tcpdf/tcpdf');

This alone does not change too much though. Still, you would need a helper to wrap the TCPDF calls to use them in your view, similar to:

Helper Class:

<?php  <?php
App
::import('Vendor','xtcpdf');

class 
TcpdfHelper extends AppHelper {
    var 
$pdf;
    function 
setup() {
        
$this->pdf = new XTCPDF();
    }
}

?>?>
and then call $tcpdf->pdf->whatevertcpdfmethodyouneed() from your view.

Fortunately this is not needed, because in CakePHP 1.2 RC2 you can now use App::import directly in the view. As shown above :)


Report

More on Tutorials

Tags

Advertising

Comments

  • Dimy posted on 01/31/13 03:14:12 PM
    I'm trying to use tcpdf, first had this error after I received this message:
    Missing Method in RelatoriosController
    Error: The action index is not defined in controller RelatoriosController
    Error: Create RelatoriosController::index() in file: app\Controller\RelatoriosController.php.
    What can it be?
    Can anyone help me?
  • dimsav posted on 02/11/11 03:17:41 PM
    1rst case:

    Has anyone tried to use tcpdf with unicode text and output to 'D' destination?
    // $pdf->Output('example_008.pdf', 'D');

    For some weird reason, many unicode characters are missing to the downloaded file, even to the original tcpdf example!

    2nd case:

    If 'I' destination is selected, then (without the Auth component) the result is a great in browser unicode pdf. Everything is displayed correctly. BUT, when Auth is enabled, the user is rejected and has to enter password.

    Anyone has any idea?

    Thanks
    • dimsav posted on 02/13/11 12:41:22 PM
      1st case solved. Some unicode files generated with tcpdf when opened in mac os x with the default viewer (preview) have missing characters.

      Anyone have a clue what happens with the second one?
  • rodrigoalvesnet posted on 02/09/11 08:03:44 PM
    Happens the following error:
    TCPDF ERROR: Some data has already been output, can't send PDF file
    What can it be?
    Can anyone help me?
    • adexerivera posted on 08/23/11 06:25:09 AM
      [quote] Happens the following error:
      TCPDF ERROR: Some data has already been output, can't send PDF file
      What can it be?
      Can anyone help me?
      [end quote]
      Hi, I had the same problems and solves through this link, http://pastebin.com/wZDmR2pd, take a look at the trecera line.

      I hope you serve.

      Regards
    • dimsav posted on 02/11/11 03:21:13 PM
      [quote] Happens the following error:
      TCPDF ERROR: Some data has already been output, can't send PDF file
      What can it be?
      Can anyone help me?
      [end quote]
      @rodrigoalvesnet Check your code for errors. This message occurs when text is displayed before the pdf creation
  • sachy posted on 02/05/11 12:26:22 PM
    Hi kalileo,
    thank you so much for your great article.
    I found this is very useful and let Japanese CakeBaker know about this.
    Google's auto translation is something broken, so I made Japanese translation on my blog.
    http://bakery.cakephp-users.jp/2011/02/05/creating-pdf-files-with-cakephp-and-tcpdf/
  • Narin posted on 01/26/11 04:44:34 AM
    Hi, all
    I have problem with google map I want to apply script key for google map .. how can I put in tcpdf? thank for help

    Narin
  • jadebil posted on 01/07/11 10:00:15 AM
    Thank you very much. I had to leave only this three lines in the controller viewpdf function:
    Configure::write('debug',0); //
    $this->layout = 'pdf'; //this will use the pdf.ctp layout
    $this->render();
    and comment out all your other stuff.
    Also, I had to use the code_ph0y example in the viewpdf.ctp view file. Then it worked.
  • autodevin posted on 09/08/10 12:34:54 PM
    @kalileo

    How did you configure tcpdf_config.php?

    Did you change modify the MAIN installation path and the URL path?

    If so, what did you write?

    Do you have any helpful information about the tcpdf installation, such as how to set the permissions properly? The tcpdf installation guide is vague and I usually end up blocking myself from being able to modify the files.

    Where can I find the name of my webserver so that I may grant it permission to use tcpdf?

    Will the latest tcpdf installation and latest cakephp work with this tutorial?

    I too suffer from white screen. When I type http://localhost/cake/clients/view_pdf/1. Am I calling this action correctly to get pdf output?

    Any help would be awesome.

    Thanks,
    autodevin
  • dasn posted on 08/26/10 02:14:36 PM
    Have you (or anybody else) seen QR codes created with this setup change each time they are rendere? I'm passing the same string to it each time but the QR codes is visibly different. it seems to cycle between 3-4 different variations.
  • rascoop posted on 08/25/10 07:53:24 AM
    Thank you for this article. I found it very useful. However it seems that page generation was a bit on the slow side until I found this article http://www.bitrealm.net/2010/08/tcpdf-is-slow-here-is-the-solution Performance increased substantially after the first one.
  • saeed posted on 07/12/10 05:34:26 AM
    Hi,

    I just made a post about the problem I had whilst trying to create a pdf with model data (for some reason, I can't see my post :s). The issue was with the writeHtml method.

    I just figured it out. Instead of using the writeHtml method, I just directly put the fields into the cell which contains the content.
    • kalileo posted on 08/04/10 11:13:16 AM
      Hi,

      I just figured it out. Instead of using the writeHtml method, I just directly put the fields into the cell which contains the content.

      In your code for the controller you're missing the

      $this->layout = 'pdf'; 
      right in front of

      $this->render();

      For a PDF you want an empty layout, and $this->layout = 'pdf'; gives that to you.

      Also your redirect after rendering the pdf can conflict, on one side you feed a pdf to the browser, on the other you tell it to jump to another page. You might get unexpected results if you do that.
  • saeed posted on 07/12/10 05:17:16 AM
    Hi,

    I am having trouble generating a PDF which contains values from a model. I am trying to use the writeHtml method but keep getting an error. The error I am getting is; "Fatal error: Call to a member function charset() on a non-object in /home/nikahnet/public_html/sims/cake/libs/view/layouts/default.ctp on line 23"

    Here is my controller:

    Controller Class:

    <?php 
    function invite($id null) {
            if (!
    $id) {
                
    $this->Session->setFlash(__('Invalid assessment'true));
                
    $this->redirect(array('action' => 'index'));
            } 
                
    $this->set('assessment'$this->Assessment->findById($id));
                
    //Configure::write('debug',0); // Otherwise we cannot use this method while developing

                    
    $this->render();
                
    $this->Session->setFlash(__('The letter has been created'true));
                
    $this->redirect(array('action' => 'index'));

        } 
    ?>

    ..and here is my view;

    View Template:


    <?php
    App
    ::import('Vendor','xtcpdf'); 
    $tcpdf = new XTCPDF();
    $textfont 'freesans'// looks better, finer, and more condensed than 'dejavusans'

    $tcpdf->SetAuthor("London East Academy");
    $tcpdf->SetAutoPageBreakfalse );
    $tcpdf->setPrintHeader(false);
    $tcpdf->setPrintFooter(false);
    //$tcpdf->setHeaderFont(array($textfont,'',40));
    //$tcpdf->xheadercolor = array(0,0,0);
    //$tcpdf->xheadertext = '';
    //$tcpdf->xfootertext = '';

    // add a page (required with recent versions of tcpdf)
    $tcpdf->AddPage();

    // create some HTML content
    $html '<p>blah blah</p>';

    // Now you position and print your page content
    // example: 
    $tcpdf->SetTextColor(000);
    $tcpdf->SetFont($textfont,'B',12);
    $tcpdf->Cell(0,14"Testing"0,1,'L');
    // output the HTML content
    $tcpdf->writeHTML($htmltruefalsetruefalse'');
    // ...
    // etc.
    // see the TCPDF examples 

    echo $tcpdf->Output('invite-letters/filename1.pdf''F');

    ?>

    Appreciate any help,

    Sid

  • prosch posted on 06/28/10 05:57:06 AM
    Very good
  • kalileo posted on 05/12/10 02:33:57 AM
    BTW. the code as shown in this tutorial runs fine with CakePHP 1.3 too.
  • jackkitley posted on 05/11/10 07:03:01 AM
    Hello all, was wondering if you could help me. I followed this tut and i have an older version of cake php so i had to use different methods. I finally got the pdf working in windows, works like a charm.

    The problem im having is when i try to generate the pdf on a macbook. The file downloads as test.pdf.html which is incorrect. I was wondering if anyone had the same issue. Ive tried a few things to fix it but no luck.

    Many thanks
  • code_ph0y posted on 04/30/10 12:54:30 PM
    Hi people just thought I would share this example with yous. change the code in the viewpdf.ctp file to the following code:

    View Template:


    <?php
    App
    ::import('Vendor','tcpdf/tcpdf');

    // create new PDF document
    $pdf = new TCPDF(PDF_PAGE_ORIENTATIONPDF_UNITPDF_PAGE_FORMATtrue'UTF-8'false); 

    // set document information
    $pdf->SetCreator(PDF_CREATOR);
    $pdf->SetAuthor('Ross Moroney');
    $pdf->SetTitle('TCPDF using CakePHP');
    $pdf->SetSubject('TCPDF using CakePHP');
    $pdf->SetKeywords('TCPDF, CakePHP, PDF, example, test, guide');

    // set default header data
    $pdf->SetHeaderData(PDF_HEADER_LOGOPDF_HEADER_LOGO_WIDTH'TCPDF using CakePHP''By Ross Moroney - code_ph0y');

    // set header and footer fonts
    $pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN''PDF_FONT_SIZE_MAIN));
    $pdf->setFooterFont(Array(PDF_FONT_NAME_DATA''PDF_FONT_SIZE_DATA));

    // set default monospaced font
    $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);

    //set margins
    $pdf->SetMargins(PDF_MARGIN_LEFTPDF_MARGIN_TOPPDF_MARGIN_RIGHT);
    $pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
    $pdf->SetFooterMargin(PDF_MARGIN_FOOTER);

    //set auto page breaks
    $pdf->SetAutoPageBreak(TRUEPDF_MARGIN_BOTTOM);

    //set image scale factor
    $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); 

    // set font
    $pdf->SetFont('times''BI'16);

    // add a page
    $pdf->AddPage();

    // print a line using Cell()
    $pdf->Cell(012'Its working'11'C');

    //Close and output PDF document
    $pdf->Output('filename.pdf''I');
    ?>

    This will give yous an example page to work with..which is easier than trying to fix the bugs.

    Laters
    • kalileo posted on 05/12/10 02:29:21 AM
      Hi people just thought I would share this example with yous. change the code in the viewpdf.ctp file to the following code:

      View Template:


      <?php
      App
      ::import('Vendor','tcpdf/tcpdf');

      // create new PDF document
      $pdf = new TCPDF(PDF_PAGE_ORIENTATIONPDF_UNITPDF_PAGE_FORMATtrue'UTF-8'false); 

      ...
      SNIP...

      //Close and output PDF document
      $pdf->Output('filename.pdf''I');
      ?>

      This will give yous an example page to work with..which is easier than trying to fix the bugs.

      Laters

      Hi Ross,

      Nice example to show some customizations. However please be aware that most of it is simply setting the defaults (or changing them) and not needed for a working example.

      Also the way you set headers and footers is bypassing the functions as set in the XTCPDF class as presented in the tutorial, that can cause some irritation.

      There are plenty of examples at the TCPDF website, showing how to work with TCPDF. Here I focus on the integration of TCPDF with CakePHP only.

      There was indeed one problem in the view code I originally presented, the line $tcpdf->AddPage(); was missing, as discussed in some comments here. It was not required by older TCPDF versions, but all recent versions require it. I added it to the view code in the article.

      The only other problem I see is memory. If you use any other than the standard PDF fonts then you need to give PHP enough memory to handle it, as discussed in some comments above. Especially the big unicode files are memory hungry, and not providing enough gives you nice blank pages.

      The code shown here runs fine in numerous projects, beginning with the real estate website for which I developed it some time ago.
  • shady posted on 04/20/10 09:09:18 AM
    Thank you for writing this article.
  • alscheuring posted on 02/16/10 07:31:37 PM
    Can you give me a little idea on how I can reuse the information in a regular view with writeHTML in TCPDF?

    I just have a regular html table in my view and I'd like to just pass that html to the tcpdf class for output. Is this do-able?
    • jtomlinson posted on 04/27/10 01:50:54 PM
      Can you give me a little idea on how I can reuse the information in a regular view with writeHTML in TCPDF?

      I just have a regular html table in my view and I'd like to just pass that html to the tcpdf class for output. Is this do-able?

      I am researching CakePHP/PDF solutions for an upcoming project and curious if you were able to get this working with writeHtml()?
  • WhyNotSmile posted on 12/16/09 11:18:11 AM
    This is brilliant, thank you!

    I'm running Cake on a server which has not configured PHP to run with the pdf library, so this has provided an excellent solution.

    To the person above who was getting

    Fatal error: Class 'XTCPDF' not found
    I had this too, and then realised I had renamed the file xtcpdf.php to xtcpdf.php5 in an early attempt to get the server to run PHP5 instead of PHP4. It might be that something similar has happened to you - make sure you have a file called xtcpdf.php in app/vendors and that it contains the code in the article above.
  • WidePixels posted on 10/22/09 07:46:06 PM
    I have it up and running but where is the view? I never changed anything yet so I see Hello World and the red header / footertext. Added AddPage();

    function view_pfd ($slug)

    $id = $this->User->slugToId($slug);
    $userData = $this->User->getTestInfo($id);
    $this->set('user', $userData);
    $this->layout = 'pdf';
    $this->render();

    But the pdf is empty. Where do i put the formatting for the view to be renderd in the pdf?

    Thanks,

    Dave
    • kalileo posted on 10/22/09 10:18:18 PM
      Dave, please see above "Step 5: For your View". There is an example for a view template. See the section there saying:

      View Template:


      // Now you position and print your page content 
      // example:  
      $tcpdf->SetTextColor(0, 0, 0); 
      $tcpdf->SetFont($textfont,'B',20); 
      $tcpdf->Cell(0,14, "Hello World", 0,1,'L'); 
      // ... 
      // etc. 
      // see the TCPDF examples 

      This you need to replace with whatever you want to have displayed. Because it is not an html page but a PDF page you use tcpdf to format and position, such as $tcpdf->Cell(...) in the example shown. See the tcpdf documentation for details.

      Otherwise, to see if there are any errors causing what you see (or not see ;) ), temporarily set debug to 1. You can do that either globally or in your function viewPdf() with Configure::write('debug',1);
  • nore posted on 09/18/09 04:27:00 AM
    hello, I got the following in the controller:

    function card($id = null) {
        $this->set('n', $this->Patient->field('name', $id));
        $this->layout = 'pdf'; 
        $this->render(); 
    }
    And this is used in the view like so: $tcpdf->Cell(50,5,$n, 0, 0);
    The links that point to this function are:
    /cake/patients/card/1
    /cake/patients/card/2
    when follow either one of these link, I get the same ID 1, meaning when generating the pdf, it contains the ID 1 in both cases.
    WHat could i be doing wrong ?
    • kalileo posted on 09/18/09 08:57:36 AM
      WHat could i be doing wrong ?

      @noregret: I don't really know what you try to do, because you talk about the ID, but you read the field "name".

      However I guess that you want this:


      function card($id = null) {
          // sanitize $id
          $this->Patient->id = $id;
          $this->set('n', $this->Patient->field('name'));
          $this->layout = 'pdf'; 
          $this->render(); 
      }

      And keep in mind that that should give you the name, not the ID.
  • websident posted on 09/05/09 03:40:32 AM
    Sorry guys, now it works just fine. I wrote AddPath(); into my view instead of AddPage();
    • kalileo posted on 09/06/09 12:53:56 AM
      Sorry guys, now it works just fine. I wrote AddPath(); into my view instead of AddPage();

      I'm happy to see that you got it working.

      In hindsight I think the older version of TCPDF versus new version issue was just a memory issue, see my comment 33 TCPDF 4.6.013 needs PHP set to more than 16 MB Some fonts covering a lot of the unicode chars got quite big, and the fonts used by the older versions have less unicode chars, thus they are smaller and need less memory when used.
  • websident posted on 09/05/09 03:24:47 AM
    Well, meanwhile I disabled the Configure::write('debug', 0); line, but now I receive the following error message:

    Call to undefined method XTCPDF::AddPath()
  • websident posted on 09/04/09 12:18:03 PM
    All I see is a blank page, not even PDF.
    Do I actually have to set anything in the 'tcpdf_config.php'?

    I red all the comments here, but nothing helped out. I don't find any older version of TCPDF, as you suggested in comment #17.

    What can I do?
  • bomdemais posted on 08/23/09 11:23:50 PM
    Using this library, is it possible to insert a previously created PDF as the background, and then insert text and/or images on top of the background PDF? I went through the examples but didn't see one that did this...

    Thanks!
  • bomdemais posted on 08/20/09 06:15:55 AM
    I am trying to get this working without having much familiarity with CakePHP besides a couple tutorials, so forgive me for asking questions that are probably obvious to everyone else.

    Questions:
    1 - what should the controller class name be? (class name XtcpdfsController? file name xtcpdfs_controller.php?)
    2 - does the controller class need to import XTCPDF?
    3 - what should the view directory be named? (xtcpdfs? pdfs?)
    4 - what should the view file name be? (view.ctp?)
    5 - Any chance you could post a working barebones version of the whole thing?

    Thanks!
    • kalileo posted on 08/20/09 07:25:07 PM
      @Nate Tanner

      I am trying to get this working without having much familiarity with CakePHP besides a couple tutorials, so forgive me for asking questions that are probably obvious to everyone else.

      Questions:
      1 - what should the controller class name be? (class name XtcpdfsController? file name xtcpdfs_controller.php?)

      This really depends on your application. It has nothing to do with XTCPDF.

      In my real life applications it is for example BookingsController / bookings_controller.php or PropertiesController / properties_controller.php. If you follow one of the blog tutorials it could be PostsController / posts_controller.php.

      2 - does the controller class need to import XTCPDF?

      No, why would it?

      There is nothing in the controller which uses TCPDF or XTCPDF, it only gets the data you will use in the view from the Model, and selects the PDF layout.

      We only load the TCPDF stuff when we need it, in the PDF view, thanks to App::import('Vendor','xtcpdf'); there.

      3 - what should the view directory be named? (xtcpdfs? pdfs?)

      Same answer as to your question 1. This really depends on your application. It has nothing to do with XTCPDF.

      Again, if you follow a blog tutorial it could be "/app/views/posts"

      4 - what should the view file name be? (view.ctp?)

      Follow cakePHP conventions. You might have noticed that the view in cakePHP is having the name depending on the function in the controller which renders that view.

      You could name it in the controller "function view()" and then use as view "view.ctp". In my tutorial I use "function viewPDF()" and consequently the view is "view_pdf.ctp". I would not use "view" here because that usually displays the record on screen (in your browser) and now we show a different view (of the same data), a view in PDF format.

      5 - Any chance you could post a working barebones version of the whole thing?

      Considering the answers above, do you really still need it?

      If yes, and if you follow a tutorial published somewhere, point me to it, and I see if I can find the time to add it to that.

      Thanks!

      You're welcome :)
      • bomdemais posted on 08/23/09 04:51:09 AM
        [quote]@Nate Tanner
        [quote]I am trying to get this working

        Thanks, that was very helpful!
  • Azita posted on 08/18/09 11:05:19 AM
    I have the same problem as killian tobin had. I just want to know how it is managed and what version of pdf should be used.
    I just have a simple view with lots of characters not adobe.
  • lubna posted on 08/17/09 08:43:34 AM
    I want to create form using tcpdf which shows the details on combo box onChange event.

    I have installed the tcpdf and watch the examples of that but the example number 14 is not working. please help me ..to get pdf form..
    Thank you..
  • deftonez4me posted on 07/31/09 10:53:40 AM
    I am trying to create a pdf, then save it to disk, without ever outputting it to the screen.

    $tcpdf->Output('filename.pdf', 'F');
    Using the F parameter in the output function to force the save to disk, creates the pdf, and saves it to disk properly, however, i am still left with a popup error everytime from Adode Reader..."File does not begin with '%PDF-'" ...almost like it is still trying to display the pdf to the screen as well. Does anyone know how i can just save it to disk, for future use, without ever outputting anything to the screen?
    • RasmiranjanSahoo posted on 12/10/10 07:39:35 AM
      Replace
      $tcpdf->Output('filename.pdf', 'I') with $tcpdf->Output('filename.pdf', 'FD') for saving PDF file
    • RasmiranjanSahoo posted on 12/10/10 07:37:26 AM
      Replace
      $tcpdf->Output('filename.pdf', 'I') with $tcpdf->Output('filename.pdf', 'FD') for saving PDF file
    • kalileo posted on 08/01/09 10:34:48 AM
      I am trying to create a pdf, then save it to disk, without ever outputting it to the screen.

      $tcpdf->Output('filename.pdf', 'F');
      Using the F parameter in the output function to force the save to disk, creates the pdf, and saves it to disk properly, however, i am still left with a popup error everytime from Adode Reader..."File does not begin with '%PDF-'" ...almost like it is still trying to display the pdf to the screen as well.

      Robert, you probably still send the layout as shown in the article to the browser, with
      header("Content-type: application/pdf");  This will make your browser start your PDF viewer, and then you send nothing, because you save to disk only. Thus the error message of your PDF viewer.

      In your case you need neither the layout as shown in this article, nor the call for it in the controller as shown in this article.
      $this->layout = 'pdf'; //this will use the pdf.ctp layout  Just take it off.

      The easiest way to get what you want is probably to add in the view, after your
      $tcpdf->Output('filename.pdf', 'F'); a regular cake view code, such as for a confirmation page saying that the pdf file was saved, or whatever else you want to display after you saved that pdf.
      • sluggerdog posted on 08/01/11 11:28:10 PM
        [quote]I am trying to create a pdf, then save it to disk, without ever outputting it to the screen.

        $tcpdf->Output('filename.pdf', 'F');
        Using the F parameter in the output function to force the save to disk, creates the pdf, and saves it to disk properly, however, i am still left with a popup error everytime from Adode Reader..."File does not begin with '%PDF-'" ...almost like it is still trying to display the pdf to the screen as well.

        Robert, you probably still send the layout as shown in the article to the browser, with
        header("Content-type: application/pdf");  This will make your browser start your PDF viewer, and then you send nothing, because you save to disk only. Thus the error message of your PDF viewer.

        In your case you need neither the layout as shown in this article, nor the call for it in the controller as shown in this article.
        $this->layout = 'pdf'; //this will use the pdf.ctp layout  Just take it off.

        The easiest way to get what you want is probably to add in the view, after your
        $tcpdf->Output('filename.pdf', 'F'); a regular cake view code, such as for a confirmation page saying that the pdf file was saved, or whatever else you want to display after you saved that pdf.
        [end quote]
        I have followed these instructions as I want to generate a PDF and save it to disk as soon as a record is saved in the database, then I will use it later but I don't want the PDF to show at all.

        My generate pdf function is:


        // GENERATE PDF
        // ------------------------------------------------------------------->
        function _generatePdf($id)
        {
        if ($id)
        {
        Configure::write('debug',2); // Otherwise we cannot use this method while developing

        $id = intval($id);

        $this->set('property', $this->Property->read(null, $id)); // GETS ALL THE FIELDS

        //$this->layout = 'pdf_save'; //this will use the pdf.ctp layout
        $this->render();
        }

        }
        // END PDF


        and I am calling it within another function like: $this->_generatePdf($this->Property->id);

        This is not creating the PDF as needed and it is also creating an error on the function I am calling the generate fucntion within. On the paginate of that function.

        I presume my generatePdf function is wrong?

        Thanks
  • clivebaker posted on 07/07/09 08:25:45 AM
    I've looked through the methods but didn't see anything for merging an external pdf with a pdf you're creating - i just want to append an external pdf to the end. The closest I could find was to create an annotation. Does anyone know a way to merge pdfs with tcpdf?
  • killiantobin posted on 06/14/09 04:22:35 PM
    Thanks for the great article!

    my version of Adobe Reader was the problem.
    • Azita posted on 08/18/09 11:07:12 AM
      Thanks for the great article!

      my version of Adobe Reader was the problem.
      • kalileo posted on 08/19/09 08:43:21 PM
        Thanks for the great article!

        my version of Adobe Reader was the problem.

        Azita, TCPDF produces PDF code, which should be readable with every PDF reader. I have testet several Adobe PDF reader versions on various OS', such as Linux, Mac, Windows Vista and XP, and other PDF readers such as KPDF (Linux's KDE 3.x) and Okular (Linux's KDE 4.x). I have neither encountered this problem, nor has a customer using one of my real life applications using TCPDF reported it.

        I have not tested it with very old versions of Adobe reader though.

        Azita, which version did you use which showed this problem?
  • killiantobin posted on 06/14/09 03:42:15 PM
    Everything seems to be working OK Cake-wise, except the resulting files can not be opened by Adobe reader. Do you think this is something wrong with TCPDF? Any clues?

    The first few lines of the pdf file when I open it up in a text editor look like:

      %PDF-1.7
    3 0 obj
    <</Type /Page
    /Parent 1 0 R
    /MediaBox [0 0 595.28 841.89]
    /Resources 2 0 R
    /Contents 4 0 R>>
    endobj
    4 0 obj
    <</Filter /FlateDecode /Length 245>>
    stream
  • kalileo posted on 05/31/09 02:30:48 PM
    The code as shown in this article works with the current TCPDF version, TCPDF 4.6.013 without any change.

    However if you want to use one of the best features, Unicode support, and the included font which supports it best, freeserif, you might run into internal server errors, resulting in nice white pages. The reason is that freeserif has been doubling its size, probably supporting more and more, but with the side effect of using more memory. if your server is configured to allow PHP 16 MB RAM, then that is not enough.

    Even without using freeserif, but freesans, after half a page of content the same error seems to be happening.

    Either adjust the value in your php.ini on your server, or add the line


    php_value memory_limit 36M

    to your .htaccess and all is fine, the error is gone and the pages are not so white anymore.

    • Donnovan posted on 12/28/09 08:10:06 AM
      The code as shown in this article works with the current TCPDF version, TCPDF 4.6.013 without any change.

      However if you want to use one of the best features, Unicode support, and the included font which supports it best, freeserif, you might run into internal server errors, resulting in nice white pages. The reason is that freeserif has been doubling its size, probably supporting more and more, but with the side effect of using more memory. if your server is configured to allow PHP 16 MB RAM, then that is not enough.

      Even without using freeserif, but freesans, after half a page of content the same error seems to be happening.

      Either adjust the value in your php.ini on your server, or add the line


      php_value memory_limit 36M

      to your .htaccess and all is fine, the error is gone and the pages are not so white anymore.


      Hi this was the solution for the blank page problem but it's better to change memory_limit inside a single php script because you have more control and you only use it on the place you need it.
      So add the following code if you get a blank page when trying to create a pdf.

      ini_set('memory_limit', '64M');
  • umitcel posted on 05/22/09 04:36:47 PM
    how can we conver view to pdf?
    • kalileo posted on 05/23/09 12:00:35 PM
      Umit, that's what this article is all about, and the view part is described above in step 5.

      If you explain where you're stuck I can try to answer more specific.
  • cigano posted on 05/13/09 11:07:54 PM
    In my tests, first I had the so-called blank screen. The first procedure to find the problem is re-enabling the debug:

    // Configure::write('debug',0)
    The first problem was caused by this line:

    $property = $this->__view($id); // here the data is pulled from the database and set for the view
    This '$this->__view()' function is an author function, not Cake native, as I'd supposed it was. This is the error:

    Fatal error: Call to undefined method CidadesController::__view() in ...app\controllers\my_controller.php on line ###
    The second detail is about using the AddPath() in the view:

    $tcpdf->AddPath();
    Because it generates this error:

    Fatal error: Call to undefined method XTCPDF::AddPath() in ...\app\views\my_views\view_pdf.ctp on line 17
    This can resolve the problem of the blank screen.

    I hope this comment could be useful to save time. These little details make programmers lose hours or even days to find the solution.

    Sorry for the mediocre english :P
    • kalileo posted on 05/19/09 01:56:02 PM
      @Leonel Sanches

      The first problem was caused by this line:

      $property = $this->__view($id); // here the data is pulled from the database and set for the view
      This '$this->__view()' function is an author function, not Cake native, as I'd supposed it was.

      Of course it is! Please have a look at whats written right above that sample code:

      In your controller you will have a method which will output the PDF. This here is the code as it is used in one of my real world applications to print a nice PDF page with data and pictures about a property

      So in your controller you need to do whatever is needed to pull any data you might want to publish from your database and set it.

      In my application the "view" and the "viewPdf" share the same data, and while the "view" optimizes it for screen display, "viewPdf" optimizes for PDF display. They share the same code to pull and set the data, which I have combined in $this->__view($id); as said there:

      // here the data is pulled from the database and set for the view


      So adapt that to your data and your needs please.

      The second detail is about using the AddPath() in the view:
      $tcpdf->AddPath(); Because it generates this error:
      Fatal error: Call to undefined method XTCPDF::AddPath() in ...\app\views\my_views\view_pdf.ctp on line 17

      As you might have seen, my sample code above does not contain $tcpdf->AddPath() so I don't know where and why you have added it.

      There are many different versions of TCPDF out there, and many different server environments. Some seem to need it (see comment 9 from Dec 24, 2008 by ohforreal), others not.

      In any case, if you get a blank screen, your approach to re-enable debug output by commenting the line


      Configure::write('debug',0)

      is a good and fast way to see any error messages.
  • khbohm posted on 05/11/09 12:14:10 AM
    Great tutorial. Thanks.
    Using the code as is in this tutorial, I see only this error message:
    "  TCPDF ERROR: Some data has already been output, can't send PDF file". Only when I change the output type 'D' to 'S', in the Output method of the $tcpdf method, can I see the PDF file in the browser.
    I have reviewed the files of PHP controllers, models and helpers, and I've removed all the spaces that were before " What can be wrong?
    • sluggerdog posted on 07/01/11 12:44:53 AM
      [quote] Great tutorial. Thanks.
      Using the code as is in this tutorial, I see only this error message:
      "  TCPDF ERROR: Some data has already been output, can't send PDF file". Only when I change the output type 'D' to 'S', in the Output method of the $tcpdf method, can I see the PDF file in the browser.
      I have reviewed the files of PHP controllers, models and helpers, and I've removed all the spaces that were before " What can be wrong?
      [end quote]
      I am getting this same issue, any ideas how I can address this? Thanks
    • kalileo posted on 05/12/09 11:38:01 AM
      Great tutorial. Thanks.
      :)
      Using the code as is in this tutorial, I see only this error message:
      "  TCPDF ERROR: Some data has already been output, can't send PDF file". Only when I change the output type 'D' to 'S', in the Output method of the $tcpdf method, can I see the PDF file in the browser.
      I have reviewed the files of PHP controllers, models and helpers, and I've removed all the spaces that were before <? Php  , but I do not get a direct download of the PDF file.
      What can be wrong?

      You mention that you checked "controllers, models and helpers", but how about view and layout? See the pdf.ctp in app/views/layouts/pdf.ctp which should look as described above, and then set in the controller with $this->layout = 'pdf'; before calling $this->render();
      oh yes, and check also for spaces after the PHP closing tag, not just before the PHP opening tag
      • faniesmith posted on 07/08/09 02:04:37 AM
        Great tutorial. Thanks.
        :)
        Using the code as is in this tutorial, I see only this error message:
        "  TCPDF ERROR: Some data has already been output, can't send PDF file". Only when I change the output type 'D' to 'S', in the Output method of the $tcpdf method, can I see the PDF file in the browser.
        I have reviewed the files of PHP controllers, models and helpers, and I've removed all the spaces that were before <? Php  , but I do not get a direct download of the PDF file.
        What can be wrong?

        You mention that you checked "controllers, models and helpers", but how about view and layout? See the pdf.ctp in app/views/layouts/pdf.ctp which should look as described above, and then set in the controller with $this->layout = 'pdf'; before calling $this->render();
        oh yes, and check also for spaces after the PHP closing tag, not just before the PHP opening tag

        I had the same problem, but I found spaces after the closing ?> tag in one of the models included in the controller that uses the tcpdf and the vendor class xtcpdf.php file.

        So take the time and check all the included views, controllers and models. Do not forget to check the app_controller.php and the app_model.php as well.

        Just thought this might help someone that get the same error.
    • kalileo posted on 05/12/09 11:21:25 AM
      .

      The comment above was posted May 11, 2009 by Claudio Juan Böhm but it is not displayed completely because he uses < > in it and the bakery comment validation lets it through without sanitation. Konqueror gets a big hiccup, Firefox not so much. Anyway, see the missing part in the quote in the next comment, which is my reply to it.
  • kalileo posted on 04/26/09 07:47:42 AM
    @Al Scheuring: yes, thanks for mentioning that! In the meantime also my code has $pdf->AddPage(); exactly at the place you specify, however when I wrote the article it was not there, so it seems to have worked without.

    As mentioned earlier, TCPDF is seeing a lot of development, so that might be just one visible result.

    The code in the view, as I use it now, has changed to:

    View Template:


    App::import('Vendor','xtcpdf');
    $pdf = new XTCPDF();
    $textfont      = 'freesans'; // looks better, finer, and more condensed than 'dejavusans'

    $footerHeight = 25;

    $tcpdf->SetAuthor("KBS Homes & Properties at http://kbs-properties.com ");
    $tcpdf->SetAutoPageBreak( true, $footerHeight );
    $tcpdf->SetTopMargin(34);
    $tcpdf->setHeaderFont(array($textfont,'',40));
    $tcpdf->xheadercolor = array(150,0,0);
    $tcpdf->xheadertext = 'KBS Homes & Properties';
    $tcpdf->xfootertext = 'Copyright Â© %d KBS Homes & Properties. All rights reserved.';

    // Now you position and print your page content
    // example: 
    $tcpdf->AddPage();
    $tcpdf->SetTextColor(0, 0, 0);
    $tcpdf->SetFont($textfont,'B',20);
    $tcpdf->Cell(0,14, "Hello World", 0,1,'L');
    // ...
    // etc.
    // see the TCPDF examples 

    echo $tcpdf->Output('filename.pdf', 'D');
    ?>
  • kalileo posted on 04/26/09 07:32:29 AM
    @Johnny Cake: with the App::import('Vendor','xtcpdf'); in the view TCPDF will only get loaded when you use it. I don't see how that can get reduced ;) except you could additionally wrap it in code to cache it, Cake makes that easy.

    However, as you say, such code should only be used for dynamic data, such as vouchers, or price lists with limited validity. If you have static data, then offer a static PDF file for download.

    FPDF has a problem with unicode, it cannot mix e.g. English and Thai. A big thank to Nicola Asuni to have bloated ;) TCPDF to fix that..
  • kalileo posted on 04/26/09 07:15:34 AM
    @Johnny Cake: you can treat such a PDF view the same way you treat a regular view, so you use the same logic and procedure to get your data ready to show. Then you pack it either in the TCPDF cell/multicell/write methods or you pack it into html code and print that using the TCDPF methods for printing HTML. There are examples in the TCPDF code / on the TCPDF website.
  • kalileo posted on 04/26/09 07:08:20 AM
    @ohforreal: Yes, keeping the header and footer area clear is tricky, IIRC this code, before starting to print something on the page, helped:

    View Template:


    $pdf->SetAutoPageBreak( true, 25 );
    $pdf->SetTopMargin(34);
  • kalileo posted on 04/26/09 06:51:21 AM
    @Thomas Heinrich:
    A few moths ago I needed to move a site with this code running from one server to another, and used the opportunity to update cake and tcpdf. All fine on the development server, but not on the production server.

    Similar problems as you saw, it just didn't work, something with the fonts was messed up. It printed lines, borders, but no fonts. Which is kinda stupid :(

    The solution was to rollback TCPDF to the old version. And again, working like a charm :) for an example see http://kbs-properties.com/properties/view/46 - click on the PDF icon at the top right above the content.

    The working version was TCPDF 4.0.017 with release date 2008-08-05, the problematic one TCPDF 4.5.023 with release date: 2009-03-06.
  • kalileo posted on 04/26/09 06:35:53 AM
    you need to call in your view

    View Template:


    App::import('Vendor','xtcpdf');
    before you call

    View Template:


    $tcpdf = new XTCPDF(); 
    If xtcpdf.php with the Class XTCPDF is in app/vendors, and no typos etc, then it will be found.
  • kalileo posted on 04/26/09 06:27:53 AM
    I have to apologize to all commenters here, it took me until now to see that I have to click on view comments in the my account page to see (and publish) your comments. Sorry Bakers!
  • alscheuring posted on 04/02/09 07:04:11 AM
    Thank you for the great article. I had some trouble getting this to work in that the header and footer were there, but no text I added. This was until I found that adding:

    $tcpdf->AddPage();

    in the view right before:

    $tcpdf->SetTextColor(0, 0, 0);

    in the view fixed it.
  • cakemate posted on 03/04/09 04:46:37 AM
    There is one important idea in this tutorial: generate the pdf only when needed. So why do you want to generate the pdf over and over again for every request? On a site with many visitors this will take your server down, especially if you are using the bloated tcpdf lib and not fpdf. You will especially have much fun if a spider follows all your "generate pdf"-links. You NOT have to generate the pdf on every request, but only when the content you want to output has changed. A lot of cpu cycles could be saved that way and climate will stay cool.
    Of course this depends on your content, but if you have an article or a newsitem or a tutorial like this page and the content will not change very fast or maybe never - it would be much better design to generate the pdf after inserting or updating and keep the generated pdf downloadable and link to it.
    I do not understand cake very well right now, but I think a component would be the right place for this kind of thing... I will check that out later.
  • cakemate posted on 03/02/09 03:40:35 AM
    Thanks, this is a very interesting article about howto integrate things like fpdf or tcpdf into cake infrastructure, I am really glad, that you wrote this, as it is not possible to understand from the manuals or any book out there how this could be achieved. Thanks!
    However, it would be very nice to go one step further and show how to use this thing in a more productive way - say how would you print your models to pdf? How would you print tabe data?
  • kangghee posted on 02/13/09 10:55:13 PM
    I need this indeed. Great article. Thanks!
    • thomthom posted on 07/11/10 03:57:13 AM
      I need this indeed. Great article. Thanks!
      Me too and it helped a lot.
  • mindblip posted on 01/07/09 05:11:57 AM
    Followed this through and got PDFs generating from my model data in no time. There are lots of easy examples on the tcpdf website. Well Done!!!
  • oh4real posted on 12/24/08 11:05:18 AM
    THANKS HEAPS!!!! This got my App PDFing within a couple days.

    Example worked OK, but didn't see "Hello, world." until I added $tcpdf->AddPath(); in the view in front of the SetTextColor() bit.

    Also, it showed up inside the header, until I repositioned it from Cell(0,14, ...); to Cell(75,75, ...); May just need $tcpdf->lastPath(); ahead of the AddPath();

    Using writeHTML() for now to keep it 'easy' making invoices and POs, but when I learn about headers and footers, I'll figure out why "Hello, world" was inside the header...

    regards,
    oh4real
  • voroex posted on 11/20/08 06:42:43 AM
    If it doesn't work (ie. blank page instead of pdf) you may try checking these:
    * www-data (or whatever user your webserver is running as) has read access to tcpfg/ -R
    * increase memory limit in php.ini
    * remove "echo" before "$tcpdf->Output"
  • draikin posted on 11/13/08 05:24:38 AM
    If i try the above example in my cakePHP application, the result is an empty page. No content, no download. Has anyone got a PDF page with the above code? Did i miss something? Any hints?

    draikin
  • battez posted on 11/05/08 07:38:15 AM
    Hi Kalileo thanks for providing this - it seems cool.

    I had a problem getting it to work at the beginning until I gave the whole tcpdf dir a 755 permission. the instructions are not clear on the TCPDF site about how to set the permissions and it would not work for me easily until I did this. I use XAMPP
  • draikin posted on 11/02/08 01:13:34 PM
    First, thank you for this great tutorial. Unfortunatly it dosn't work for me. I tried your example code but only get an empty page. The only thing i changed was the class name for the extended vendor class. I don't if I miss anything. Has anyone a similar problem with the above code?
  • cybercoder posted on 10/30/08 06:04:01 AM
    when i use tcpdf directly ( samples in example folder ) i see the result right, but when i use it as helper in cake or vendor all of persian characters are reverse! can anyone help me?
  • draikin posted on 10/29/08 07:23:43 AM
    I tried your tutorial to create PDFs with my cakrPHP application. The first try I use your code as you discribe above to create a simple PDF. But if i call the view, i get an empty page instead of the PDF. The only thing i changed is the classname for my own extended TCPDF class. Any hint? Has anyone else the same problem? If needed i can post the relevant code here.
    Any help would be appreciated.

    draikin
  • xelios posted on 10/23/08 12:16:23 AM
    Hi;

    I followed the tutorial but having some problem:
    Following is the error...

    Fatal error: Class 'XTCPDF' not found in C:\xampp\htdocs\cake12\CakePHP\app\views\books\view_pdf.ctp on line 3



  • ucasano posted on 08/28/08 07:10:30 AM
    Hi,
    maybe you should spent a little more on how you set tcpdf paths in configuration file.
    I tried to make it run bur I always got "TCPDF error: Could not include font definition file".
    Nice post, really interesting.
    Bye!!
login to post a comment.