Search code examples
phpdompdf

Creating multiple PDF files with dompdf


I am writing a script that checks a database and returns each row of a customer that account start date is on a certain date. If the customer was created on the specified date then the customer row is passed to my function to create a PDF out of the customer's information in the database.

Problem

The only way I have thought up to create one PDF for each customer is to loop through the data and create the PDF. When doing so I have one problem.

1. Only the first user's PDF is created. Nothing happens pertaining to the second.

Unable to stream PDF: headers already sent

shows in the browser and the first PDF downloads. But for testing purposes there are two customers in the database that should be created. I echo out the data to the browser and both customers do show up. So I know the data exist and is there at run time.

Example

  // create instance of customer's that need to be created
    $a = new SelectTempOne;
     // obtain response from customers in database that have met timing requirement
    $response = $a->selectUserForOne();
        // loop through each row in the results and handle then pass to the pdf creation string
    foreach($response as $i => $row) {
    // statically typing template string to render email address of user
    $temp1 = '
        <!DOCTYPE html>
    <html>

    <head>
        <title>Template 1</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <link rel="stylesheet" type="text/css" media="screen" href="pdf-templates/temp1/temp1.css" />
    </head>

    <body>
        <div id="pdf_header">
            <table>
                <tr>
                    <td>'.$response[$i]['email'].'</td>
                </tr>
            </table>
        </div>
    </body>

    </html>
    ';

     // pass html to dompdf object
    $dompdf->loadHtml($temp1);

    // set option for the paper size and orientation
    $dompdf->setPaper('A4', 'letter');

    // Render the HTML as PDF
    $dompdf->render();

    //save the file to the server
    $output = $dompdf->output();
    file_put_contents('pdf/'.$response[$i]['email'].'.pdf', $output);


    // Output the generated PDF to Browser
    $dompdf->stream();
    exit;
    } // end of the for loop
    ?>

This line is where I add the customer's email,

 <td>'.$response[$i]['email'].'</td>

Question

What do I need to do to be able to create a dynamic amount of PDF as I loop through the rows returned from the database?

* UPDATE *

Fatal error: Uncaught Dompdf\Exception: No block-level parent found. Not good. in /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/Positioner/Inline.php:45 Stack trace: #0 /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/FrameDecorator/AbstractFrameDecorator.php(872): Dompdf\Positioner\Inline->position(Object(Dompdf\FrameDecorator\Inline))

1 /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/FrameReflower/Inline.php(51):

Dompdf\FrameDecorator\AbstractFrameDecorator->position() #2 /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/FrameDecorator/AbstractFrameDecorator.php(893): Dompdf\FrameReflower\Inline->reflow(NULL) #3 /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/FrameReflower/Page.php(141): Dompdf\FrameDecorator\AbstractFrameDecorator->reflow() #4 /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/FrameDecorator/AbstractFrameDecorator.php(893): Dompdf\FrameReflower\Page->reflow(NULL) #5 /Users/wuno/Dropbox/google/devop in /Users/wuno/Dropbox/google/devops/htdocs/tracker/login/dompdf/src/Positioner/Inline.php on line 45


Solution

  • A web browser works by requesting a document. You can't expect to be able to serve multiple documents to a user. You get to call $dompdf->stream(); once and that's it. Your options: dynamically create a listing page with individual links, create a multi-page PDF, or zip the PDFs together.

    Edit: ok, based on your comment, you don't actually want to display the PDF. In addition, I took another look and you've got an exit statement in your loop. That's not going to run more than once. Also, it's a good idea to use heredoc strings when you have large blocks of text in your code, so I've done so.

    <?php
    // create instance of customer's that need to be created
    $a = new SelectTempOne;
    // obtain response from customers in database that have met timing requirement
    $response = $a->selectUserForOne();
    // loop through each row in the results and handle then pass to the pdf creation string
    foreach($response as $i => $row) {
    
        // statically typing template string to render email address of user
        $temp1 = <<< HTML
    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Template 1</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <link rel="stylesheet" type="text/css" media="screen" href="pdf-templates/temp1/temp1.css" />
    </head>
    
    <body>
        <div id="pdf_header">
            <table>
                <tr>
                    <td>$row[email]</td>
                </tr>
            </table>
        </div>
    </body>
    
    </html>
    HTML;
    
        // pass html to dompdf object
        $dompdf->loadHtml($temp1);
    
        // set option for the paper size and orientation
        $dompdf->setPaper('A4', 'letter');
    
        // Render the HTML as PDF
        $dompdf->render();
    
        //save the file to the server
        $output = $dompdf->output();
        file_put_contents("pdf/$row[email].pdf", $output);
    
    } // end of the for loop
    ?>