EC-CUBE4でwkhtmltopdfを利用する方法

EC-CUBE Advent Calendar 2022 12日目の記事です。

EC-CUBE4では、納品書出力という機能はtcpdfというライブラリを利用してPDF出力を行なっています。

このライブラリは2系から利用されており非常に便利なのですが、レイアウトの修正など煩わしい問題があります。

今回は簡単にレイアウトの修正が行えるようにするwkhtmltopdfというライブラリの利用方法を説明します。

wkhtmltopdfというライブラリはhtmlをそのままpdfへと変換するライブラリとなります。詳しくは以下のURLを参照してください。

wkhtmltopdf.org

wkhtmltopdfのインストール

EC-CUBE4で利用するためには、こちらを参考に、

github.com

wkhtmltopdfをcomposerコマンドを使ってインストールします。

composer require h4cc/wkhtmltopdf-amd64 0.12.x
composer require h4cc/wkhtmltoimage-amd64 0.12.x

Macを利用されている方で正常にインストールできないという方は、下記よりダウンロードしてください。

https://wkhtmltopdf.org/downloads.html

KnpSnappyBundleのインストール

準備が整えば、今度はKnpSnappyBundleというライブラリをインストールします。

github.com

インストール方法は記載されている通り、composerコマンドを利用します。

composer require knplabs/knp-snappy-bundle

その後、以下の設定を行います。

  • app/config/eccube/bundles.phpの修正
return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
    Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
    Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['all' => true],
    Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
    Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
    Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
    Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true, 'install' => true],
    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'install' => true],
    Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
    Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
    Exercise\HTMLPurifierBundle\ExerciseHTMLPurifierBundle::class => ['all' => true],
    Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
    DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true],
    Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
    Knp\Bundle\SnappyBundle\KnpSnappyBundle::class => ['all' => true],
];

Knp\Bundle\SnappyBundle\KnpSnappyBundle::class => ['all' => true],を最終行に追加します。

  • app/config/eccube/packages/knp_snappy.yamlの作成
knp_snappy:
    pdf:
        enabled:    true
        binary:     /usr/local/bin/wkhtmltopdf #"\"C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe\"" for Windows users
        options:    []
    image:
        enabled:    true
        binary:     /usr/local/bin/wkhtmltoimage #"\"C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltoimage.exe\"" for Windows users
        options:    []
    temporary_folder: "%kernel.cache_dir%/snappy"

上記の通り、knp_snappy.yamlファイルを作成します。

PDFファイルの作成

準備が出来れば後はhtmlファイルやtwigファイルを作成するのみとなります。

  • Contorollerに関数を追加

どのControllerクラスでも構いませんし、新規作成しても構いませんので一例として以下の関数を作成します。

<php




use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
use Knp\Snappy\Pdf;




    /**
     * @Route("/outputpdf", name="outputpdf", methods={"GET"})
     */
    public function pdfAction(Pdf $knpSnappyPdf)
    {
        $html = $this->renderView('Pdf/outputpdf.twig', [
            'name' => 'ああああ',
        ]);

        return new PdfResponse(
            $knpSnappyPdf->getOutputFromHtml($html),
            'output.pdf'
        );
    }
  • app/template/default/Pdf/outputpdf.twigファイルの作成
<!doctype html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

    <title>請求書</title>

    <style>
        body {
            font-family: "Hiragino Kaku Gothic ProN", "segoe ui", 'Noto Serif JP', serif, sans-serif;
            font-size: 1rem;
            line-height: 1.6;
            background: #fff;
        }

        main {
            position: relative;
            overflow: hidden;
        }
    </style>
</head>

<body>
<header>
    <div class="wrap">
        <div>
            <h2>請 求 書</h2>
        </div>
    </div>

</header>

<main>
    {{ name }} 様<br>
    請求書の内容を作成
</main>

</body>
</html>

以上を作成後、http://xxxx/outputpdf を入力するとtwigで作成されたものがPDFダウンロードされます。

あとは、twigファイルに対して出力したい内容を組み立てていけば、htmlを修正するだけで簡単にレイアウト変更が可能となります。 wkhtmltopdfですがflex指定が出来ない時もありますのでhtmlを作成する場合、昔ながらの方法でcss指定を行なってください。

PDFが出力されず、

Exit with code 1 due to network error: ProtocolUnknownError

というエラーが発生した場合、画像やCSSファイルはフルパスで記述する必要がありますのでご注意ください。

wkhtmltopdfは横向きや縦向きなど色んなオプションが用意されています。 getOutputFromHtml関数の第2引数に対して、

$options = [
    'encoding' => 'utf-8',
    'page-size' => 'A4',
    'margin-top' => '30px',
    'margin-bottom' => '30px',
    'margin-left' => '20px',
    'margin-right' => '20px',
];

return new PdfResponse(
    $knpSnappyPdf->getOutputFromHtml($html, $options),
    'output.pdf'
);

とオプション指定すれば設定可能です。 オプションについては下記のURLをご覧ください。

https://wkhtmltopdf.org/usage/wkhtmltopdf.txt

PDFが動作しないという方はコメントに記載ください。