Laravel × PhpSpreadsheetでExcel&PDF出力!日本語対応まで完全ガイド

1. はじめに

LaravelでWebアプリケーションを構築していると、「データをExcelやPDFで出力したい」という要件は非常によくあります。特に、社内システムや管理画面などでは、ユーザーが一覧データをダウンロードしたり、帳票を出力したりする機能が求められます。

このとき便利なのが、PhpSpreadsheetというライブラリです。Excel形式(.xlsxなど)のファイルを簡単に作成・出力でき、Laravelとの相性も良いため、広く使われています。また、PhpSpreadsheetはPDF出力にも対応している…のですが、日本語の文字が文字化けしてしまうという落とし穴が存在します。

私自身もこの文字化け問題に直面し、いろいろと調べて試行錯誤した結果、LibreOfficeを使ってPDFに変換する方法にたどり着きました。この記事では、その一連の流れを「完全ガイド」としてまとめます。

  • LaravelとPhpSpreadsheetを使ったExcel出力の実装
  • PhpSpreadsheetでのPDF出力の課題
  • 日本語対応のためのLibreOffice変換の手順

実務でつまずきやすいポイントや注意点にも触れながら、できるだけわかりやすく解説していきます。「同じことで困ってる人の助けになれば」と思って書いていますので、ぜひ参考にしてください!

2. 環境構築とライブラリ導入

まずは、今回の解説で使用する環境と、必要なライブラリの導入方法について確認しましょう。

✅ 想定環境

以下は、この記事で検証した際の環境です。ご自身の環境に合わせて読み替えてください。

  • PHP: 8.1
  • Laravel: 10.x
  • OS: Ubuntu 22.04 / macOS Sonoma(※LibreOfficeの動作に差あり)
  • Webサーバー: Laravel Sail または Apache/Nginx

✅ PhpSpreadsheetのインストール

Excelファイルの生成には、PhpSpreadsheet を使用します。Composerでインストール可能です。

composer require phpoffice/phpspreadsheet

Laravelプロジェクトにインストールすれば、すぐに使い始められます。

✅ LibreOfficeのインストール

PDF出力にはLibreOfficeを使います。CLIから使えるようにインストールしておきましょう。

▼ Ubuntuの場合:
sudo apt update
sudo apt install libreoffice -y
▼ macOSの場合(Homebrewを使用):
brew install --cask libreoffice

⚠️注意:macOSでlibreofficeをCLIから使う場合、sofficeコマンドのパスを通す必要があります。インストール後に/Applications/LibreOffice.app/Contents/MacOS/sofficeを使用してください。

✅ その他注意点

  • サーバー上でLibreOfficeを使用する場合、GUI環境が不要な「ヘッドレスモード(--headless)」での実行を前提とします。
  • Docker環境(Laravel Sailなど)を使っている場合、LibreOfficeを含めたカスタムイメージを使う必要があります。

この準備ができたら、いよいよ実際のExcel出力処理に進んでいきます!

3. Excelファイルの出力(PhpSpreadsheet基本)

まずは、PhpSpreadsheetを使ってExcelファイル(.xlsx)を生成し、ダウンロードさせる基本的な方法を見ていきましょう。

✅ サンプル:ユーザー一覧をExcelで出力

ここでは、Laravelのコントローラーからユーザー一覧を出力する簡単な例を紹介します。

▼ 1. コントローラーの作成

php artisan make:controller ExportController

▼ 2. コントローラーに出力処理を記述

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Illuminate\Support\Facades\Response;

public function exportUsers()
{
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();

    // ヘッダーを設定
    $sheet->setCellValue('A1', 'ID');
    $sheet->setCellValue('B1', '名前');
    $sheet->setCellValue('C1', 'メールアドレス');

    // ユーザーデータを挿入(例として最初の10件)
    $users = \App\Models\User::limit(10)->get();
    $row = 2;

    foreach ($users as $user) {
        $sheet->setCellValue("A{$row}", $user->id);
        $sheet->setCellValue("B{$row}", $user->name);
        $sheet->setCellValue("C{$row}", $user->email);
        $row++;
    }

    // 一時的にファイルを保存してレスポンスとして返す
    $writer = new Xlsx($spreadsheet);
    $fileName = 'users.xlsx';
    $tempFile = storage_path($fileName);
    $writer->save($tempFile);

    return response()->download($tempFile)->deleteFileAfterSend(true);
}

▼ 3. ルーティングの追加(web.php

Route::get('/export-users', [ExportController::class, 'exportUsers']);

✅ 動作確認

ブラウザで /export-users にアクセスすれば、users.xlsx というファイルが自動でダウンロードされるはずです📥


🔍 ワンポイント:文字コードや日本語の扱い

PhpSpreadsheetは日本語にも基本的に対応しています。Excel出力では文字化けの心配は少なく、UTF-8で記述しておけば問題なく表示されます。

このように、Excelファイルの出力はLaravel + PhpSpreadsheetで非常にスムーズに実現できます。
次は、PDF出力で起こる問題点と、そこからどう対処していくかを見ていきましょう!

4. PDF出力に挑戦 → 文字化け問題の発生

PhpSpreadsheetには、ExcelだけでなくPDF形式でも出力できる機能が用意されています。

「おっ、じゃあこのままPDFでも出力できるんじゃん!」
と思って試してみたLaravelエンジニアの皆さん、**ここでつまずきませんでしたか?**😅


✅ 実際にPDF出力を試してみる

以下は、PhpSpreadsheetのPdfドライバを使ってPDFを出力する簡単なコード例です。

use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'こんにちは!');
$sheet->setCellValue('A2', 'テスト出力です');

$writer = new Mpdf($spreadsheet);
$tempFile = storage_path('test.pdf');
$writer->save($tempFile);

return response()->download($tempFile)->deleteFileAfterSend(true);

😱 出力してみたら…「え、日本語が全部□になってる?」

そうなんです。上記のコードでPDFを生成してみると、日本語が文字化けしてしまうケースが非常に多いです。
英数字は表示されるのに、日本語が「□□□」や「????」になってしまう…。


🔍 文字化けの原因

PhpSpreadsheetのPDF出力は、内部的に mpdftcpdf を利用していますが、これらのライブラリはデフォルトで日本語フォントに対応していません

特に、

  • 適切なTrueTypeフォント(例:IPAexゴシックなど)がインストールされていない
  • PHPからフォントのパスをうまく認識できていない

といった理由で、日本語が正しくレンダリングされず、結果として文字化けが発生します。


🧭 ここでの選択肢

この時点での対応方法としては、以下のような選択肢があります。

  1. mPDFやTCPDFに日本語フォントを追加して頑張る(設定がかなり面倒)
  2. 別の手段でPDFに変換する(←今回はこちら!)

私自身、何度もフォント設定にトライしましたが、環境依存が大きく安定しませんでした。
そこでたどり着いた解決策が LibreOfficeを使って、一度ExcelファイルをPDFに変換する方法 です!

次のセクションでは、その実装方法を詳しく紹介していきます。

5. 解決策:LibreOfficeでPDF変換する方法

日本語が文字化けせず、正しくPDFとして出力するために、ここではLibreOfficeを使ってExcelからPDFに変換する方法を紹介します。

一度Excelファイルとして出力し、それをLibreOffice経由でPDFに変換するという二段構えの手法です。


✅ 変換の全体の流れ

  1. Laravelで .xlsx ファイルを生成(前のセクションで実装済み)
  2. LibreOffice をコマンドラインで実行し、.xlsx.pdf に変換
  3. 変換したPDFをレスポンスとして返却

🔧 LibreOfficeをCLIから使う

LibreOfficeには --headless モードがあり、GUIなしでファイルを変換できます。
変換コマンドの例は以下のとおりです:

libreoffice --headless --convert-to pdf /path/to/input.xlsx --outdir /path/to/output/

Laravel内からこのコマンドを実行するには、exec() 関数や Symfony\Component\Process\Process を使う方法があります。


✅ LaravelでLibreOfficeを実行するコード例

以下は、PhpSpreadsheetでExcelファイルを作成し、その後LibreOfficeでPDFに変換、最終的にPDFを返すまでの一連のコード例です。

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Symfony\Component\Process\Process;
use Illuminate\Support\Facades\Storage;

public function exportPdfWithLibreOffice()
{
    // ① Excelファイルを生成
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    $sheet->setCellValue('A1', 'ユーザー一覧');
    $sheet->setCellValue('A2', 'こんにちはPDF世界!');

    $fileName = 'output.xlsx';
    $excelPath = storage_path($fileName);
    $writer = new Xlsx($spreadsheet);
    $writer->save($excelPath);

    // ② LibreOfficeでPDFに変換
    $process = new Process([
        'libreoffice',
        '--headless',
        '--convert-to', 'pdf',
        $excelPath,
        '--outdir', storage_path()
    ]);
    $process->run();

    if (!$process->isSuccessful()) {
        return response()->json(['error' => 'PDF変換に失敗しました'], 500);
    }

    // ③ PDFファイルをレスポンスとして返却
    $pdfPath = storage_path('output.pdf');
    return response()->download($pdfPath)->deleteFileAfterSend(true);
}

⚠️ 注意点

  • libreoffice コマンドが環境によりパス指定が必要な場合があります(例: macOSでは /Applications/LibreOffice.app/Contents/MacOS/soffice)。
  • Dockerコンテナ内で実行する場合は、LibreOfficeがインストールされているカスタムイメージが必要。
  • storage_path() によるファイル管理を適切に行い、不要ファイルは削除すること。

この方法で変換すれば、日本語も問題なく表示されるPDFをLaravelから出力することができます✨
次は、実運用で気をつけたいポイントをまとめてお伝えします!

6. 補足:実運用での注意点

LibreOfficeで日本語対応のPDF出力が実現できたとしても、本番運用には特有の注意点があります。ここでは、開発者が事前に把握しておくべきポイントをいくつか紹介します。


✅ 1. サーバー環境へのLibreOfficeインストール

ローカルでは問題なく動作していても、本番サーバーやCI環境にLibreOfficeが入っていないケースは非常に多いです。

  • Linux系サーバーならaptyumでインストール可能
  • Docker環境(Laravel Sailなど)では、LibreOffice入りのカスタムイメージを自作する必要あり
  • Windowsサーバーではパスの扱いに注意

可能であれば、ステージング環境でもLibreOfficeの挙動を事前確認しておきましょう。


✅ 2. exec()Processの使用に関するセキュリティ

外部コマンドを実行するということは、セキュリティリスクがあるということです。

  • exec()Processを使う場合は、入力値を絶対に信頼せず、サニタイズ必須
  • 実行権限のあるユーザーやコマンド制限にも注意
  • Laravelのログにコマンド出力を残さない設計が理想的

「PDF変換に失敗しても中身がログに丸出し」みたいなケースは避けたいですよね…😅


✅ 3. 一時ファイルの取り扱い

変換処理中に生成されるExcelファイルやPDFファイルは、一時的なファイルとして保存されます。
これをそのまま放置すると、ストレージ容量を圧迫する可能性があります。

  • deleteFileAfterSend(true) を活用して即削除する
  • それ以外の一時ファイルは定期的に削除する仕組み(スケジューラー等)を組み込む

✅ 4. LibreOfficeの実行失敗時のハンドリング

LibreOfficeが何らかの理由で失敗した場合、例外処理をしないとユーザーはただのエラー画面に直面することになります。

  • ProcessisSuccessful()チェックは必ず実施
  • 失敗時は、ログ記録+エラーメッセージを返す設計に
  • エラーの内容をUI側で通知するかどうかも判断する必要あり

🧭 補足まとめ

実装だけでなく、運用や保守の観点からの設計も非常に重要です。
本番環境で安定して動作させるには、

  • サーバーの構成管理
  • ファイルのライフサイクル管理
  • エラーハンドリングとセキュリティ

これらを意識しておくことで、トラブルを未然に防ぐことができます。

次は、この記事のまとめに入っていきます!

7. まとめ

Laravel × PhpSpreadsheetでのExcel出力、そして日本語に対応したPDF出力までを一通りご紹介してきました。

今回のポイントを振り返ると、次のとおりです:


✅ この記事で学んだこと

  • PhpSpreadsheetを使えば、Laravelから簡単にExcelファイルを出力できる
  • ただし、PDF出力では日本語の文字化けが発生する落とし穴がある
  • その問題は、LibreOfficeを使って .xlsx → .pdf に変換することで回避できる
  • 実運用では、セキュリティ・サーバー構成・一時ファイルの管理なども重要!

PDFの日本語対応は意外とハマりやすい部分なので、この記事が少しでも「同じことで困ってた!」という方の助けになれば嬉しいです。

もしこれをベースに、

  • 他の帳票(請求書や日報など)への応用
  • PDFテンプレートの整備
  • Laravelのサービス層やジョブとの連携

などをしていけば、実務にも十分対応できるようになるはずです!


📢 あなたの「うまくいった!」報告もお待ちしてます!
改善点や他の手法があれば、コメントやSNSでシェアしていただけると嬉しいです!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です