✅ やりたいこと
Laravelアプリ上で、
・PDFを綺麗に出力し
・ブラウザで自動表示し
・印刷ダイアログまで自動で出す
という一連の流れを実現したい!
✅ 技術スタック
・Laravel 9
・spatie/browsershot
・Node.js + Puppeteer
・JavaScript (iframe.onload → print())
・Tailwind CSS(PDFでは非対応。CSSはstyle属性で対応)
✅ 完成イメージ
ボタンをクリックすると…
✅ サーバーでPDF生成
✅ 自動的に新しいタブで表示
✅ 即印刷ダイアログが開く!
↓ サンプル動画
✅ 1. Node.js & Puppeteer インストール手順
✅ 2. Laravel側に Browsershot 導入
✅ 3. PDF用Bladeテンプレートを作成
✅ 4. 印刷ボタン
// /views/receipts/show.blade.php
{{-- 印刷 --}}
<form action="{{ route('receipts.generate_and_print', [ 'id' => $receipt->id ]) }}"
target="_blank">
<button type="submit"
class="text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg">
印刷する
</button>
</form>
✅ 5. ルーティング
routes/web.php
// 印刷
// PDF生成 & 中継ページへ
Route::get('/receipts/pdf/print/{id}', [ReceiptController::class, 'generateAndPrint'])->name('receipts.generate_and_print');
// 中継ビュー(iframe + 自動印刷)
Route::get('/receipts/print/show/{filename}', [ReceiptController::class, 'showPrintView'])->name('receipts.print.show');
✅ 6. # tmpディレクトリ(storage/app/public/tmp)作成
mkdir -p storage/app/public/tmp
chmod -R 775 storage/app/public/tmp
✅ 7. ControllerにPDF生成&中継ビュー表示処理を追加
/Http/Controllers/ReceiptController.php
// ⭐️印刷
public function generateAndPrint($id)
{
// ✅ 情報の取得
/** @var \App\Models\User $user */
$user = Auth::user();
$receipt = $user
->receipts()
->with(['paymentMethod', 'bentoDetails'])
->findOrFail($id);
// ✅ PDF作成
$html = view('pdf.receipt', compact('receipt'))->render();
$customerName = preg_replace('/[^\w\-]/u', '_', $receipt->customer_name);
$filename = "receipt_{$customerName}_{$id}.pdf";
$pdfPath = storage_path("app/public/tmp/{$filename}");
Browsershot::html($html)
->setNodeBinary('/usr/local/bin/node')
->setIncludePath('/usr/local/bin')
->format('A4')
->showBackground()
->save($pdfPath);
// ✅ PDF作成完了後、中継ビューへリダイレクト
return redirect()->route('receipts.print.show', ['filename' => $filename]);
}
✅ 8. 中継ビューでPDF表示&自動印刷
// /views/pdf/print_redirect.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>印刷中...</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
iframe {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<iframe id="pdfFrame" src="{{ $pdfUrl }}"></iframe>
<script>
const iframe = document.getElementById('pdfFrame');
iframe.onload = () => {
iframe.contentWindow.focus();
iframe.contentWindow.print();
};
</script>
</body>
</html>
✅ 9. 中継ビュー用 Controller を追加
/Http/Controllers/ReceiptController.php
public function showPrintView($filename)
{
$pdfUrl = asset("storage/tmp/{$filename}");
return view('pdf.print_redirect', compact('pdfUrl'));
}
✅ 10. 1時間以上経過したPDFは自動削除
① tmp フォルダを .gitignore に追加(Git管理対象外に)
.gitignore
/storage/app/public/tmp/
② Artisanコマンドで「古いPDFファイルを削除するスクリプト」を作成
php artisan make:command DeleteOldPdfs
↓
作成後、以下のように編集:
app/Console/Commands/DeleteOldPdfs.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Carbon\Carbon;
class DeleteOldPdfs extends Command
{
protected $signature = 'pdf:cleanup'; // コマンド名
protected $description = '1時間以上前に作られたPDFを削除します';
public function handle()
{
$dir = storage_path('app/public/tmp');
$deleted = 0;
foreach(File::files($dir) as $file) {
// ファイルの作成から1時間以上経ってたら削除
if(now()->diffInMinutes(Carbon::createFromTimestamp(filemtime($file))) > 60) {
File::delete($file);
$deleted++;
}
}
$this->info("🗑️ {$deleted}個の古いPDFを削除しました!");
}
}
③ スケジュールに登録する
app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// 毎時このコマンドを実行(1時間以上前のPDF削除)
$schedule->command('pdf:cleanup')->hourly();
}
④ 本番サーバでcron登録(ローカルなら不要)
Linuxサーバでターミナルから:
crontab -e
以下を追記(Laravelのschedulerを毎分呼び出す):
* * * * * cd /your/project/path && php artisan schedule:run >> /dev/null 2>&1
※ cd のパスは artisan があるプロジェクトルートにしてください。
関連