如何向使用 DOMPDF 和 Laravel 5.8 生成的 PDF 添加 header 和页脚

How to add a header and footer to a PDF generated with DOMPDF and Laravel 5.8

我正在 Laravel 5.8 应用中使用 barryvdh/laravel-dompdf

我对 header 和页脚有疑问。
Preview PDF

我有生成 PDF 的功能:

public function getProductPdf(Request $request, int $id)
{
    $product = $this->cmsRepository->getProduct($id);
    $data = [
        'title' => 'First PDF for Medium',
        'heading' => 'Hello from 99Points.info',
        'content' => 'Od kilku dni w szeregach Platformy Obywatelskiej trwa czas powyborczych rozliczeń. Kolejni politycy krytykują działania partii pod kierunkiem Grzegorza Schetyny, którego kadencja na stanowisku przewodniczącego kończy się za kilka miesięcy. Walki o przywództwo nie wyklucza Borys Budka. - Jestem skłonny startować w tych wyborach, bo musi być jakiś wybór - powiedział polityk w rozmowie z "Gazetą Wyborczą".'
    ];

    $pdf = \PDF::setOptions(['dpi' => 150, 'defaultFont' => 'sans-serif', 'defaultPaperSize' => 'a3'])->loadView('psCMS.prints.product-view', $data);
    return $pdf->download('product-' . $product->id . '-' . now()->toDateString() . '.pdf');
}

这是我要打印的模板:

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>{{ $title }}</title>
    <style type="text/css">
        .page-break {
            page-break-after: always;
        }
        /*@page {*/
        /*    margin: 0px 0px 0px 0px !important;*/
        /*    padding: 0px 0px 0px 0px !important;*/
        /*}*/
        th,
        td,
        p,
        div,
        b {
            margin: 0;
            padding: 0
        }
        html {
            margin: 40px 50px
        }
        body {
            font-family: DejaVu Sans;
            font-style: normal;
            font-weight: 400;
            /*margin: 0px;*/
            font-size: 18px;
        }
        * {
            font-family: DejaVu Sans, Verdana, Arial, sans-serif;
        }
        a {
            color: black;
            text-decoration: none;
        }
        table {
            font-size: x-small;
        }
        tfoot tr td {
            font-weight: bold;
            font-size: 18px;
        }
        .gray {
            background-color: lightgray
        }
        .information {
            color: black;
            font-size: 18px;
        }
        .information .logo {
            margin: 5px;
        }
        .information table {
            padding: 10px;
            font-size: 18px;
        }
        .document {
            padding-bottom: 50px;
        }
    </style>
</head>
<body>
    <div class="information">
        <table width="100%">
            <tr>
                <td align="left" style="width: 40%;">
                    <h3>John Doe</h3>
                    <pre>
    Street 15
    123456 City
    United Kingdom
    <br/><br/>
    Date: 2018-01-01
    Identifier: #uniquehash
    Status: Paid
    </pre>
                </td>
                <td align="center">
                    <img src="/path/to/logo.png" alt="Logo" width="64" class="logo" />
                </td>
                <td align="right" style="width: 40%;">
                    <h3>CompanyName</h3>
                    <pre>
                        https://company.com
                        Street 26
                        123456 City
                        United Kingdom
                    </pre>
                </td>
            </tr>
        </table>
    </div>
    <br />
    <h1>{{ $heading}}</h1>
    <div class="document">
        <p>{{$content}}</p>
        <table width="100%">
            <tr>
                <td valign="top"><img src="{{asset('images/meteor-logo.png')}}" alt="" width="150" /></td>
                <td align="right">
                    <h3>Shinra Electric power company</h3>
                    <pre>
                    Company representative name
                    Company address
                    Tax ID
                    phone
                    fax
                </pre>
                </td>
            </tr>
        </table>
        <table width="100%">
            <tr>
                <td><strong>From:</strong> Linblum - Barrio teatral</td>
                <td><strong>To:</strong> Linblum - Barrio Comercial</td>
            </tr>
        </table>
        <br />
        <table width="100%">
            <thead style="background-color: lightgray;">
                <tr>
                    <th>#</th>
                    <th>Description</th>
                    <th>Quantity</th>
                    <th>Unit Price $</th>
                    <th>Total $</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <th scope="row">1</th>
                    <td>Playstation IV - Black</td>
                    <td align="right">1</td>
                    <td align="right">1400.00</td>
                    <td align="right">1400.00</td>
                </tr>
                <tr>
                    <th scope="row">1</th>
                    <td>Metal Gear Solid - Phantom</td>
                    <td align="right">1</td>
                    <td align="right">105.00</td>
                    <td align="right">105.00</td>
                </tr>
                <tr>
                    <th scope="row">1</th>
                    <td>Final Fantasy XV - Game</td>
                    <td align="right">1</td>
                    <td align="right">130.00</td>
                    <td align="right">130.00</td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="3"></td>
                    <td align="right">Subtotal $</td>
                    <td align="right">1635.00</td>
                </tr>
                <tr>
                    <td colspan="3"></td>
                    <td align="right">Tax $</td>
                    <td align="right">294.3</td>
                </tr>
                <tr>
                    <td colspan="3"></td>
                    <td align="right">Total $</td>
                    <td align="right" class="gray">$ 1929.3</td>
                </tr>
            </tfoot>
        </table>

        Pence poinformował po trwających ponad cztery godziny negocjacjach, że Turcja na 120 godzin zawiesi wszystkie
        operacje militarne, by pozwolić kurdyjskim bojownikom na opuszczenie przygranicznego pasa w północno-wschodniej
        Syrii, a gdy Kurdowie wycofają się, nastąpi rozejm.
        Turcja nie będzie jednak zobligowana do wycofania swoich wojsk z Syrii. Jak pisze AP, cytując przedstawiciela
        amerykańskich władz, oznacza to de facto, że Ankara otrzymała pozwolenie USA na okupowanie bezpiecznej strefy.
        Negocjatorzy obu stron wydali komunikat, w którym napisano, że stworzenie bezpiecznej strefy "będzie egzekwowane
        przede wszystkim przez siły zbrojne Turcji".
        Wiceprezydent podkreślił też, że prezydent Donald Trump zagroził, że jeśli Ankara nie zawiesi operacji
        wojskowych, to on nie wycofa obecnych sankcji nałożonych na Turcję i pozwoli na wdrożenie następnych.
        Dodał, że Ankara i Waszyngton "zobowiązały się do wypracowania pokojowego rozwiązania i przyszłości dla
        bezpiecznej strefy" na północnym wschodzie Syrii. Oznajmił, że amerykańskie siły w Syrii zaczęły już ułatwiać
        Kurdom bezpieczne wycofanie się z przygranicznych terenów.
        Pence powiedział również dziennikarzom, że Ankara obiecała, że jej wojska nie zajmą miasta Kobane (Ajn al-Arab),
        nazywanego ogniskiem zapalnym tego konfliktu. Minister spraw zagranicznych Turcji Mevlut Cavusoglu oznajmił
        jednak, że Ankara nie udzieliła gwarancji dotyczących Kobane, a jej armia jedynie "przerwała operacje". Dodał,
        że status miasta Manbidż "i innych regionów" na północnym wschodzie Syrii, zostanie przedyskutowany z Rosją.
        Kurdyjski polityk Aldar Chalil, komentując warunki rozejmu, powiedział telewizji Al-Arabija, że Erdogan chce
        wedrzeć się na terytorium Syrii na głębokość 32 km, a Kurdowie już wcześniej odrzucili takie rozwiązanie. Dodał,
        że aprobują zawieszenie broni, ale będą się bronić, jeśli zostaną zaatakowani.
        Amerykańscy senatorowie, w tym wpływy sojusznik prezydenta Lindsey Graham, poinformowali, że niezależnie od
        zapowiedzi rozejmu, będą "pełną parą" pracowali nad ustawą w sprawie nowych sankcji na Ankarę.
        "Wspaniałe wiadomości z Turcji"
        Trump podziękował na Twitterze Erodganowi i napisał, że otrzymał "wspaniałe wiadomości z Turcji". "Miliony
        istnień ludzkich będą uratowane!" - dodał. Oznajmił, że w tej sytuacji możliwa jest wizyta Erdogana w USA w
        przyszłym miesiącu.
        Nazwał też prezydenta Turcji "twardym facetem", który "zrobił to, co trzeba". Dodał: "Teraz Kurdowie będą
        bardziej skłonni robić to, co trzeba".
        Przedstawiciel strony tureckiej po negocjacjach powiedział agencji Reutera, że Turcja "dostała dokładnie to,
        czego chciała". Porozumienie pozwala Turcji uwolnić się od nałożonych już sankcji i uniknąć kolejnych, a to
        oznacza, że w żaden sposób nie zostanie ukarana za inwazję w północno-wschodniej Syrii - komentuje AP.
        Reuters przypomina, że ekspedycja sił tureckich zmusiła do ucieczki 200 tys. cywilów. Wzbudziła też niepokój
        wspólnoty międzynarodowej o odrodzenie się Państwa Islamskiego (IS), którego bojownicy są zamknięci w
        kurdyjskich więzieniach.
        Turecka ofensywa wywołała też polityczną burzę w Waszyngtonie, gdzie politycy różnych afiliacji krytykowali
        prezydenta za decyzję o wycofaniu amerykańskich żołnierzy z Syrii, co Ankara uznała za przyzwolenie na podjęcie
        operacji wojennych - komentuje Reuters.
        W środę Trump bronił swojej decyzji, nazywając ją "strategicznie błyskotliwą", ale Izba Reprezentantów tego
        samego dnia przyjęła rezolucję potępiającą decyzję prezydenta o wycofaniu amerykańskich żołnierzy z Syrii.
        Za rezolucją, w liczącej 435 miejsc niższej izbie Kongresu, głosowało 354 kongresmenów, czyli wszyscy Demokraci
        i duża grupa Republikanów. W czwartek głosowanie nad analogiczną rezolucją zapowiedział Senat.
    </div>
    <footer>
        <div class="footer" style="position: absolute; bottom: 0;">
            <table width="100%">
                <tr>
                    <td align="left" style="width: 50%;">
                        &copy; {{ date('Y') }} {{ config('app.url') }} - All rights reserved.
                    </td>
                    <td align="right" style="width: 50%;">
                        Company Slogan
                    </td>
                </tr>
            </table>
        </div>
    </footer>
</body>
</html>

我需要 Header 和页脚在 PDF 的每一页上都可见。

模板看起来不错,但是 header 和页脚有问题。

Header = John Doe、公司名称等。 Footer = 公司口号,@2019-10-17

如何在页脚中添加:[页码] 来自[页数]?

为页眉和页脚添加样式。

<style>
    @page { margin: 180px 50px; }
    #header { position: fixed; left: 0px; top: -180px; right: 0px; height: 150px; background-color: orange; text-align: center; }
    #footer { position: fixed; left: 0px; bottom: -180px; right: 0px; height: 150px; background-color: lightblue; }
    #footer .page:after { content: counter(page, upper-roman); }
</style>

在 div 中添加 header 部分。

<div id="header">

</div>

在下面的div中添加Footer部分。

 <div id="header">

 </div>
  • /config/dompdf.php
  • 启用 DOMPDF_ENABLE_PHP
  • 通过php artisan vendor:publish 命令发布供应商文件
  • 从控制器传递 $pdf 对象:
  • 列表项

您应该在 view 文件中添加以下脚本。

<script type="text/php">
    if ( isset($pdf) ) {
        // OLD 
        // $font = Font_Metrics::get_font("helvetica", "bold");
        // $pdf->page_text(72, 18, "{PAGE_NUM} of {PAGE_COUNT}", $font, 6, array(255,0,0));
        // v.0.7.0 and greater
        $x = 72;
        $y = 18;
        $text = "{PAGE_NUM} of {PAGE_COUNT}";
        $font = $fontMetrics->get_font("helvetica", "bold");
        $size = 6;
        $color = array(255,0,0);
        $word_space = 0.0;  //  default
        $char_space = 0.0;  //  default
        $angle = 0.0;   //  default
        $pdf->page_text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
    }
</script>