barryvdh / laravel-dompdf

A DOMPDF Wrapper for Laravel
MIT License
6.74k stars 973 forks source link

Numbered pages #452

Closed barquerox closed 4 years ago

barquerox commented 6 years ago

What are the final steps or the true guide to number the pages in a pdf document with dompdf? I have googled a lot and no method works. The issues of this repository to number the pages do not work either. I use 0.8.0 version.

NickWhiu commented 6 years ago

After facing this, i've got it working. This works in laravel-dompdf v0.8.2 (and probably a few versions earlier). I've adapted this sample from a work project from today, so it should work but ive not tested :stuck_out_tongue:. This is laravel 5.4, but it should work in any laravel 5.x.

If all you want is "Page 1" in the header/footer, you can do that with pure HTML/CSS. See the sample code at https://dompdf.net/test/print_header_footer.html which converts to https://dompdf.net/dompdf.php?input_file=print_header_footer.html#toolbar=0&view=FitH&statusbar=0&messages=0&navpanes=0.

in your view:

<style>
#header,
#footer {
  position: fixed;
  left: 0;
    right: 0;
    color: #aaa;
    font-size: 0.9em;
}
#header {
  top: 0;
    border-bottom: 0.1pt solid #aaa;
}
#footer {
  bottom: 0;
  border-top: 0.1pt solid #aaa;
}
.page-number:before {
  content: "Page " counter(page);
}
</style>

<div id="footer">
  <div class="page-number"></div>
</div>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

However if you want "Page 1 of 3" then keep reading.

I would have liked to do this purely with the CSS counters feature, however it seems you can't get page total with the CSS counters yet. Instead, we need to use the embedded-php feature (for now). Hope this changes in the future.

in controller:

public function pdf()
{
  $data = array();
  $pdf = \App::make('dompdf.wrapper');
  /* Careful: use "enable_php" option only with local html & script tags you control.
  used with remote html or scripts is a major security problem (remote php injection) */
  $pdf->getDomPDF()->set_option("enable_php", true);
  $pdf->loadView('pdf.invoice', $data);
  return $pdf->stream('invoice.pdf');
}

in view './resources/views/invoice/pdf.blade.php':

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

{{-- Here's the magic. This MUST be inside body tag. Page count / total, centered at bottom of page --}}
<script type="text/php">
    if (isset($pdf)) {
        $text = "page {PAGE_NUM} / {PAGE_COUNT}";
        $size = 10;
        $font = $fontMetrics->getFont("Verdana");
        $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
        $x = ($pdf->get_width() - $width) / 2;
        $y = $pdf->get_height() - 35;
        $pdf->page_text($x, $y, $text, $font, $size);
    }
</script>
</body>
</html>
NicksonYap commented 5 years ago

@NickWhiu It is magic! thanks!

ashanrupasinghe commented 4 years ago

Thanks.

dea96 commented 4 years ago

After facing this, i've got it working. This works in laravel-dompdf v0.8.2 (and probably a few versions earlier). I've adapted this sample from a work project from today, so it should work but ive not tested 😛. This is laravel 5.4, but it should work in any laravel 5.x.

If all you want is "Page 1" in the header/footer, you can do that with pure HTML/CSS. See the sample code at https://dompdf.net/test/print_header_footer.html which converts to https://dompdf.net/dompdf.php?input_file=print_header_footer.html#toolbar=0&view=FitH&statusbar=0&messages=0&navpanes=0.

in your view:

<style>
#header,
#footer {
  position: fixed;
  left: 0;
  right: 0;
  color: #aaa;
  font-size: 0.9em;
}
#header {
  top: 0;
  border-bottom: 0.1pt solid #aaa;
}
#footer {
  bottom: 0;
  border-top: 0.1pt solid #aaa;
}
.page-number:before {
  content: "Page " counter(page);
}
</style>

<div id="footer">
  <div class="page-number"></div>
</div>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

However if you want "Page 1 of 3" then keep reading.

I would have liked to do this purely with the CSS counters feature, however it seems you can't get page total with the CSS counters yet. Instead, we need to use the embedded-php feature (for now). Hope this changes in the future.

in controller:

public function pdf()
{
  $data = array();
  $pdf = \App::make('dompdf.wrapper');
  /* Careful: use "enable_php" option only with local html & script tags you control.
  used with remote html or scripts is a major security problem (remote php injection) */
  $pdf->getDomPDF()->set_option("enable_php", true);
  $pdf->loadView('pdf.invoice', $data);
  return $pdf->stream('invoice.pdf');
}

in view './resources/views/invoice/pdf.blade.php':

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

{{-- Here's the magic. This MUST be inside body tag. Page count / total, centered at bottom of page --}}
<script type="text/php">
    if (isset($pdf)) {
        $text = "page {PAGE_NUM} / {PAGE_COUNT}";
        $size = 10;
        $font = $fontMetrics->getFont("Verdana");
        $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
        $x = ($pdf->get_width() - $width) / 2;
        $y = $pdf->get_height() - 35;
        $pdf->page_text($x, $y, $text, $font, $size);
    }
</script>
</body>
</html>

amazing!!!

jarol72 commented 4 years ago

Thank you!!!

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Any issues with PDF rendering itself that are not directly related to this package, should be reported on https://github.com/dompdf/dompdf instead. When having doubts, please try to reproduce the issue with just dompdf. If you believe this is an actual issue with the latest version of laravel-dompdf, please reply to this issue so we can investigate further. Thank you for your contribution! Apologies for any delayed response on our side.

Itzama commented 1 year ago

After facing this, i've got it working. This works in laravel-dompdf v0.8.2 (and probably a few versions earlier). I've adapted this sample from a work project from today, so it should work but ive not tested 😛. This is laravel 5.4, but it should work in any laravel 5.x.

If all you want is "Page 1" in the header/footer, you can do that with pure HTML/CSS. See the sample code at https://dompdf.net/test/print_header_footer.html which converts to https://dompdf.net/dompdf.php?input_file=print_header_footer.html#toolbar=0&view=FitH&statusbar=0&messages=0&navpanes=0.

in your view:

<style>
#header,
#footer {
  position: fixed;
  left: 0;
  right: 0;
  color: #aaa;
  font-size: 0.9em;
}
#header {
  top: 0;
  border-bottom: 0.1pt solid #aaa;
}
#footer {
  bottom: 0;
  border-top: 0.1pt solid #aaa;
}
.page-number:before {
  content: "Page " counter(page);
}
</style>

<div id="footer">
  <div class="page-number"></div>
</div>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

However if you want "Page 1 of 3" then keep reading.

I would have liked to do this purely with the CSS counters feature, however it seems you can't get page total with the CSS counters yet. Instead, we need to use the embedded-php feature (for now). Hope this changes in the future.

in controller:

public function pdf()
{
  $data = array();
  $pdf = \App::make('dompdf.wrapper');
  /* Careful: use "enable_php" option only with local html & script tags you control.
  used with remote html or scripts is a major security problem (remote php injection) */
  $pdf->getDomPDF()->set_option("enable_php", true);
  $pdf->loadView('pdf.invoice', $data);
  return $pdf->stream('invoice.pdf');
}

in view './resources/views/invoice/pdf.blade.php':

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

{{-- Here's the magic. This MUST be inside body tag. Page count / total, centered at bottom of page --}}
<script type="text/php">
    if (isset($pdf)) {
        $text = "page {PAGE_NUM} / {PAGE_COUNT}";
        $size = 10;
        $font = $fontMetrics->getFont("Verdana");
        $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
        $x = ($pdf->get_width() - $width) / 2;
        $y = $pdf->get_height() - 35;
        $pdf->page_text($x, $y, $text, $font, $size);
    }
</script>
</body>
</html>

Genial! me ha funcionado

markpavia commented 1 year ago

how can I make the $text an HTML. example

$text = "<b>page {PAGE_NUM} / {PAGE_COUNT}</b>"

Substractive commented 11 months ago

Is there any possible way to get total number of pages before displaying PDF? I have requirement to put number of pages in one field that's on first page of said PDF (don't ask me why). Tried everything I could come up with but no results yet. Pagination is working fine and that's all good but I need that total number known before displaying PDF so I can shove that number in

at start... Hope someone has some info

medab123 commented 8 months ago

After facing this, i've got it working. This works in laravel-dompdf v0.8.2 (and probably a few versions earlier). I've adapted this sample from a work project from today, so it should work but ive not tested 😛. This is laravel 5.4, but it should work in any laravel 5.x.

If all you want is "Page 1" in the header/footer, you can do that with pure HTML/CSS. See the sample code at https://dompdf.net/test/print_header_footer.html which converts to https://dompdf.net/dompdf.php?input_file=print_header_footer.html#toolbar=0&view=FitH&statusbar=0&messages=0&navpanes=0.

in your view:

<style>
#header,
#footer {
  position: fixed;
  left: 0;
  right: 0;
  color: #aaa;
  font-size: 0.9em;
}
#header {
  top: 0;
  border-bottom: 0.1pt solid #aaa;
}
#footer {
  bottom: 0;
  border-top: 0.1pt solid #aaa;
}
.page-number:before {
  content: "Page " counter(page);
}
</style>

<div id="footer">
  <div class="page-number"></div>
</div>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

However if you want "Page 1 of 3" then keep reading.

I would have liked to do this purely with the CSS counters feature, however it seems you can't get page total with the CSS counters yet. Instead, we need to use the embedded-php feature (for now). Hope this changes in the future.

in controller:

public function pdf()
{
  $data = array();
  $pdf = \App::make('dompdf.wrapper');
  /* Careful: use "enable_php" option only with local html & script tags you control.
  used with remote html or scripts is a major security problem (remote php injection) */
  $pdf->getDomPDF()->set_option("enable_php", true);
  $pdf->loadView('pdf.invoice', $data);
  return $pdf->stream('invoice.pdf');
}

in view './resources/views/invoice/pdf.blade.php':

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>

<h1>Invoice</h1>
<p>... content here, spanning many pages ...</p>

{{-- Here's the magic. This MUST be inside body tag. Page count / total, centered at bottom of page --}}
<script type="text/php">
    if (isset($pdf)) {
        $text = "page {PAGE_NUM} / {PAGE_COUNT}";
        $size = 10;
        $font = $fontMetrics->getFont("Verdana");
        $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
        $x = ($pdf->get_width() - $width) / 2;
        $y = $pdf->get_height() - 35;
        $pdf->page_text($x, $y, $text, $font, $size);
    }
</script>
</body>
</html>

I have probelm with this solution its workin fine bit its also make pdf generation proccess very slow