🐥
barryvdh/laravel-dompdf 使用例
PDF保存処理例
- エントリポイント
- 非同期処理に対応できるようlaravelのjob機能で実行
- PDF作成、保存
- ロケールを設定
- PDFインスタンスの作成
- PDFファイル保存
エントリポイント
public function store(EstimatesRequest $request)
{
$estimate = Estimate::createEstimate($request);
if ($request->has('estimateSend')) {
$estimate->send($request->title, $request->body);
}
GenerateEstimatePdfJob::dispatch($estimate);
return response()->json([
'estimate' => $estimate
]);
}
public function update(EstimatesRequest $request, Estimate $estimate)
{
$estimate = $estimate->updateEstimate($request);
GenerateEstimatePdfJob::dispatch($estimate, true);
return response()->json([
'estimate' => $estimate
]);
}
非同期処理に対応できるようlaravelのjob機能で実行
https://github.com/bytefury/crater/blob/master/app/Jobs/GenerateEstimatePdfJob.php
<?php
namespace Crater\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class GenerateEstimatePdfJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $estimate;
public $deleteExistingFile;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($estimate, $deleteExistingFile = false)
{
$this->estimate = $estimate;
$this->deleteExistingFile = $deleteExistingFile;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$this->estimate->generatePDF('estimate', $this->estimate->estimate_number, $this->deleteExistingFile);
return 0;
}
}
PDF作成、保存
https://github.com/bytefury/crater/blob/master/app/Traits/GeneratesPdfTrait.php
public function generatePDF($collection_name, $file_name, $deleteExistingFile = false)
{
$save_pdf_to_disk = CompanySetting::getSetting('save_pdf_to_disk', $this->company_id);
// コンフィグ設定で保存が必要なければ保存しない
if($save_pdf_to_disk == 'NO') {
return 0;
}
$locale = CompanySetting::getSetting('language', $this->company_id);
// ロケール設定
App::setLocale($locale);
// PDFインスタンス作成
// コードは下に記載
$pdf = $this->getPDFData();
// PDFファイル作成、保存
// 後に正となるPDFファイルを保存するので、あくまで一時用
\Storage::disk('local')->put('temp/'.$collection_name.'/'.$this->id.'/temp.pdf', $pdf->output());
if($deleteExistingFile) {
// 自分自身(Illuminate\Database\Eloquent\Model)に紐づくメディアファイルの削除
// Spatie\MediaLibrary\InteractsWithMediaトレイトをくっつけて、
// clearMediaCollectionを実行すれば削除してくれる
$this->clearMediaCollection($collection_name);
}
// Laravelのどのファイルシステムを利用するかを決定
$file_disk = FileDisk::whereSetAsDefault(true)->first();
if ($file_disk) {
// 決定したファイルシステムに設定
$file_disk->setConfig();
}
// 保存
$media = \Storage::disk('local')->path('temp/'.$collection_name.'/'.$this->id.'/temp.pdf');
try {
// https://github.com/spatie/laravel-medialibrary
// を利用して正となるPDFファイルを保存
// こんな形で保存される
/*
*************************** 3. row ***************************
id: 5
model_type: Crater\Models\Payment
model_id: 3
collection_name: payment
name: temp
file_name: PAY-000001.pdf
mime_type: application/pdf
disk: temp_local
size: 878396
manipulations: []
custom_properties: {"file_disk_id":2}
responsive_images: []
order_column: 3
created_at: 2021-05-09 09:39:26
updated_at: 2021-05-09 09:39:26
uuid: 76abc923-bb32-4418-9817-470057890716
conversions_disk: temp_local
*/
$this->addMedia($media)
->withCustomProperties(['file_disk_id' => $file_disk->id])
->usingFileName($file_name.'.pdf')
->toMediaCollection($collection_name, config('filesystems.default'));
// 一時用を削除
\Storage::disk('local')->deleteDirectory('temp/'.$collection_name.'/'.$this->id);
return true;
} catch (\Exception $e) {
return $e->getMessage();
}
}
app/Models/Estimate.php
public function getPDFData()
{
$taxTypes = [];
$taxes = [];
$labels = [];
...
// PDFのテンプレート情報を取得
// テンプレートのビューコード
// https://github.com/bytefury/crater/blob/master/resources/views/app/pdf/estimate/estimate1.blade.php
$estimateTemplate = EstimateTemplate::find($this->estimate_template_id);
$company = Company::find($this->company_id);
$locale = CompanySetting::getSetting('language', $company->id);
// ここでもロケール設定している
App::setLocale($locale);
$logo = $company->logo_path;
view()->share([
'estimate' => $this,
'logo' => $logo ?? null,
'company_address' => $this->getCompanyAddress(),
'shipping_address' => $this->getCustomerShippingAddress(),
'billing_address' => $this->getCustomerBillingAddress(),
'notes' => $this->getNotes(),
'labels' => $labels,
'taxes' => $taxes
]);
// ここでbarryvdh/laravel-dompdfを利用している
return PDF::loadView('app.pdf.estimate.' . $estimateTemplate->view);
// おそらくこんな書き方でもいいのではないか
// $var = [
// 'estimate' => $this,
// 'logo' => $logo ?? null,
// 'company_address' => $this->getCompanyAddress(),
// 'shipping_address' => $this->getCustomerShippingAddress(),
// ...
//];
// return PDF::loadView('app.pdf.estimate.' . $estimateTemplate->view, $var);
}
PDF出力処理例
エントリポイント
app/Http/Controllers/V1/Invoice/InvoicePdfController.php
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Invoice $invoice)
{
return $invoice->getGeneratedPDFOrStream('invoice');
}
PDF出力
app/Traits/GeneratesPdfTrait.php
<?php
namespace Crater\Traits;
use Carbon\Carbon;
use Crater\Models\Address;
use Crater\Models\FileDisk;
use Crater\Models\CompanySetting;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\App;
trait GeneratesPdfTrait
{
public function getGeneratedPDFOrStream($collection_name)
{
// 値があればこのよな値が$pdfに入る
// ["path" => "\/var\/www\/storage\/app\/Invoices\/INV-000001.pdf","file_name" => "INV-000001.pdf"]
$pdf = $this->getGeneratedPDF($collection_name);
if($pdf && file_exists($pdf['path'])) {
return response()->make(file_get_contents($pdf['path']), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$pdf['file_name'].'.pdf"'
]);
}
$locale = CompanySetting::getSetting('language', $this->company_id);
App::setLocale($locale);
$pdf = $this->getPDFData();
return response()->make($pdf->stream(), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$this[$collection_name.'_number'].'.pdf"'
]);
}
public function getGeneratedPDF($collection_name)
{
try {
// vendor/spatie/laravel-medialibrary/src/InteractsWithMedia.php
/* @var $media おそらく vendor/spatie/laravel-medialibrary/src/MediaCollections/Models/Media.php */
$media = $this->getMedia($collection_name)->first();
if ($media) {
// custom_propertiesに{"file_disk_id":2}このような値が入っている
// file_disk_idとはfilesystem.phpのdisksの設定を格納しているテーブルのid
$file_disk = FileDisk::find($media->custom_properties['file_disk_id']);
if (!$file_disk) {
return false;
}
$file_disk->setConfig();
$path = null;
if($file_disk->driver == 'local'){
$path = $media->getPath();
} else {
$path = $media->getTemporaryUrl(Carbon::now()->addMinutes(5));
}
return collect([
'path' => $path,
'file_name' => $media->file_name
]);
}
} catch(\Exception $e){
return false;
}
return false;
}
Discussion