📄

【laravel-mdpf】導入時のエラー対応ログ

2024/09/06に公開

前提

  • Docker
  • Laravel 10
  • PHP 8.3

https://github.com/mccarlosen/laravel-mpdf

問題1. 最新バージョン(^2.1)がインストールできない

結論

  • mpdfで必要な各種設定をDockerfileに追加する
  • Dockerfile更新後はdocker-compose up -dで変更の反映を忘れずに
FROM public.ecr.aws/docker/library/php:8.3-fpm-alpine

WORKDIR /var/www/html

ENV TZ=Asia/Tokyo

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apk update && apk add --no-cache \
            autoconf \
            g++ \
            gcc \
            linux-headers \
            make \
            icu-dev \
            mysql-client \
            git \
            zip \
            unzip \
            libzip-dev \
            vim \
            nginx \
            supervisor \
            freetype-dev \ ←追加
            libjpeg-turbo-dev \ ←追加
            libpng-dev \ ←追加
    && docker-php-ext-configure intl \
    && docker-php-ext-install pdo_mysql zip opcache intl \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \ ←追加
    && docker-php-ext-install gd \ ←追加
    && curl -sS https://getcomposer.org/installer | php \
    && mv composer.phar /usr/local/bin/composer \
    && /usr/local/bin/composer self-update

参考:エラーログ

  • ざっくり内容を要約すると以下の内容が出力されている
    • PHP8.3だと依存関係にあるmpdfの実行に必要なGDライブラリがないやんけ!
      • じゃあGD入れましょうね、が↑の結論
/var/www/html # composer require carlos-meneses/laravel-mpdf:^2.1 --with-all-dependencies
./composer.json has been updated
Running composer update carlos-meneses/laravel-mpdf --with-all-dependencies
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - carlos-meneses/laravel-mpdf[2.1.0, ..., 2.1.1] require mpdf/mpdf ^7.1 -> satisfiable by mpdf/mpdf[v7.1.0, ..., v7.1.9].
    - carlos-meneses/laravel-mpdf 2.1.13 requires mpdf/mpdf ^8.0|^8.1 -> satisfiable by mpdf/mpdf[v8.0.0, ..., v8.2.4].
    - carlos-meneses/laravel-mpdf[2.1.2, ..., 2.1.12] require mpdf/mpdf ^8.0 -> satisfiable by mpdf/mpdf[v8.0.0, ..., v8.2.4].
    - carlos-meneses/laravel-mpdf 2.1.10 requires mpdf/mpdf ^8.1 -> satisfiable by mpdf/mpdf[v8.1.0, ..., v8.2.4].
    - carlos-meneses/laravel-mpdf[2.1.8, ..., 2.1.9] require mpdf/mpdf ^8.1.0 -> satisfiable by mpdf/mpdf[v8.1.0, ..., v8.2.4].
    - carlos-meneses/laravel-mpdf[2.1.6, ..., 2.1.7] require mpdf/mpdf ^8.0.0 -> satisfiable by mpdf/mpdf[v8.0.0, ..., v8.2.4].
    - mpdf/mpdf[v7.1.0, ..., v7.1.6] require php ^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v7.1.7, ..., v7.1.9, v8.0.0, ..., v8.0.3] require php ^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v8.0.4, ..., v8.0.7] require php ^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v8.0.8, ..., v8.0.9] require php ^5.6 || ^7.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v8.0.10, ..., v8.0.12] require php ^5.6 || ^7.0 || ~8.0.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v8.0.13, ..., v8.1.2] require php ^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v8.1.3, ..., v8.2.0] require php ^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 -> your php version (8.3.11) does not satisfy that requirement.
    - mpdf/mpdf[v8.2.1, ..., v8.2.4] require ext-gd * -> it is missing from your system. Install or enable PHP's gd extension.
    - Root composer.json requires carlos-meneses/laravel-mpdf ^2.1 -> satisfiable by carlos-meneses/laravel-mpdf[2.1.0, ..., 2.1.13].

To enable extensions, verify that they are enabled in your .ini files:
    - /usr/local/etc/php/conf.d/99-develop.ini
    - /usr/local/etc/php/conf.d/docker-fpm.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-intl.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-zip.ini
You can also run php --ini in a terminal to see which files are used by PHP in CLI mode.
Alternatively, you can run Composer with --ignore-platform-req=ext-gd to temporarily ignore these required extensions.

問題2. ^2.1で日本語フォント(Noto Sans JP)が反映されない

結論

  • config/pdf.phpにおけるcustom_font_data内のキーに小文字+アンダースコア以外が含まれている
<?php

return [
    // PDF生成モード; デフォルトモードの場合は空白
    'mode' => 'ja',

    // デフォルトのページフォーマット; A4, A3 など
    'format' => 'A4',

    // デフォルトのフォントサイズ
    'default_font_size' => '12',

    // デフォルトのフォントタイプ
    'default_font' => 'sans-serif',

    // 文書の左マージン(ミリメートル)
    'margin_left' => 10,

    // 文書の右マージン(ミリメートル)
    'margin_right' => 10,

    // 文書の上マージン(ミリメートル)
    'margin_top' => 10,

    // 文書の下マージン(ミリメートル)
    'margin_bottom' => 10,

    // ヘッダーのマージン(ミリメートル)
    'margin_header' => 0,

    // フッターのマージン(ミリメートル)
    'margin_footer' => 0,

    // 文書の方向: 'P' は縦向き, 'L' は横向き
    'orientation' => 'P',

    // 文書のタイトル
    'title' => 'Laravel mPDF',

    // 文書の主題
    'subject' => '',

    // 文書の著者
    'author' => '',

    // ウォーターマークとして使用されるテキスト
    'watermark' => '',

    // ウォーターマークテキストを表示するかどうかの真偽値
    'show_watermark' => false,

    // ウォーターマーク画像を表示するかどうかの真偽値
    'show_watermark_image' => false,

    // ウォーターマークテキストのフォント
    'watermark_font' => 'sans-serif',

    // PDFビューアによる文書の表示方法; fullpage, fullwidth, real, default など
    'display_mode' => 'fullpage',

    // ウォーターマークテキストの透明度
    'watermark_text_alpha' => 0.1,

    // ウォーターマークとして使用される画像ファイルへのパス
    'watermark_image_path' => '',

    // ウォーターマーク画像の透明度
    'watermark_image_alpha' => 0.2,

    // ウォーターマーク画像のサイズ; 'D' はデフォルト, 'P' は比例, 'F' はフィット
    'watermark_image_size' => 'D',

    // ウォーターマーク画像の位置; 'P' はページに対して, 'F' は固定など
    'watermark_image_position' => 'P',

    // カスタムフォントディレクトリのパス(Git管理したくないのでstorageに配置)
    'custom_font_dir' => storage_path('fonts'/), // トレイリングスラッシュを忘れずに

    // カスタムフォントデータの配列
    'custom_font_data' => [
        'notosansjp' => [ // ○ ← lowercase
            'R' => 'NotoSansJP-Regular.ttf',
            'B' => 'NotoSansJP-Bold.ttf',
        ],
        'noto_sans_jp' => [ // ○ ← snakecase
            'R' => 'NotoSansJP-Regular.ttf',
            'B' => 'NotoSansJP-Bold.ttf',
        ],
        'Noto Sans JP' => [ // ✕ ←スペ−スとか大文字が含まれていると、フォントファイルは読み込まれない
            'R' => 'NotoSansJP-Regular.ttf',
            'B' => 'NotoSansJP-Bold.ttf',
        ],
    ],

    // 言語自動検出を有効にするかどうか
    'auto_language_detection' => false,

    // 一時ファイルのディレクトリパス
    'temp_dir' => storage_path('app'),

    // PDF/A 準拠のPDFを生成するかどうか
    'pdfa' => false,

    // PDF/A 準拠のPDFを自動で生成するかどうか
    'pdfaauto' => false,

    // アクティブフォームを使用するかどうか
    'use_active_forms' => false,
];

参考:PDFの出力

  • あとはbladeファイル内で以下のようにfont-familyを指定してあげればOK
    • ↓はcustom_font_data内のキーがlowercaseの場合を想定

resources/views/foo/sample.blade.php

<html>
    <head>
        <style>
            body { font-family: notosansjp, sans-serif; margin: 0; padding: 0; }
        </style>
    </head>
    <body>
        <p>Noto Sans JPが反映されたテキスト</p>
    </body>
</html>

app/Http/Controllers/FooPdfController.php

namespace App\Http\Controllers;

use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use Mpdf\MpdfException;
use Symfony\Component\HttpFoundation\Response;

class FooPdfController extends Controller
{
    /**
     * @throws MpdfException
     */
    public function show(): Response
    {
        return LaravelMpdf::loadView('foo.sample')->stream('sample.pdf');
    }
}

Discussion