Генерация PDF файлов на Laravel 10 в 2024 году
Был выпущен новый пакет под названием spatie/laravel-pdf , пакет для создания PDF-файлов в приложениях Laravel. Внутри он использует Chromium для создания PDF-файлов из представлений Blade. Вы можете использовать современные функции CSS, такие как grid, flexbox и даже такие ui-фрейморки, как Tailwind, для создания красивых PDF-файлов.
В этом посте я хотел бы представить и продемонстрировать пакет.
Создание PDF файла
После установки пакета вы можете использовать PDF
фасад для создания PDF-файлов. Основой для создания PDF-файлов является HTML, а самый простой способ создания HTML в приложении Laravel — использовать представление.
Вот пример создания PDF-файла из представления Blade.
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('pdf.invoice')->save('/some/directory/invoice.pdf');
Под капотом пакет через Browsershot запустит экземпляр Chrome, загрузит ваш HTML и позволит Chrome сохранить PDF-файл. Поскольку Chrome имеет современный механизм рендеринга, вы сможете использовать современные функции CSS для создания PDF-файла.
В качестве второго параметра вы можете передать массив данных, которые будут доступны в представлении. Вы можете использовать это для передачи модели Eloquent, например счета, в представление.
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('pdf.invoice', ['invoice' => $invoice])->save('/some/directory/invoice.pdf');
Помимо локального сохранения, вы можете сохранить PDF-файл на любом из настроенных вами дисков .
Вот пример сохранения PDF-файла на s3
диск.
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('invoice')->disk('s3')->save('invoice-april-2022.pdf');
Вместо использования представления Blade вы также можете создать PDF-файл из строки HTML.
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::html('<h1>Hello world!!</h1>')->save('/some/directory/invoice.pdf');
Ответ с помощью PDF файла в Laravel
В контроллере вы можете создать и вернуть PDF-файл, используя эту pdf()
функцию.
use function Spatie\LaravelPdf\Support\pdf;
class DownloadInvoiceController
{
public function __invoke(Invoice $invoice)
{
return pdf()->view('pdf.invoice', compact('invoice'))->name('invoice-2023-04-10.pdf');
}
}
По умолчанию PDF-файл будет встроен в браузер. Это означает, что PDF-файл будет отображаться в браузере, если браузер его поддерживает. Если пользователь попытается загрузить PDF-файл, он будет называться «invoice-2023-04-10.pdf». Мы рекомендуем всегда давать PDF-файлам имя.
Вы можете использовать этот download()
метод для принудительной загрузки PDF-файла.
use function Spatie\LaravelPdf\Support\pdf;
class DownloadInvoiceController
{
public function __invoke(Invoice $invoice)
{
return pdf()->view('pdf.invoice', compact('invoice'))->name('invoice-2023-04-10.pdf')->download();
}
}
Использование JavaScript в PDF файлах на Laravel
JavaScript в вашем HTML будет выполняться Chrome при создании PDF-файла. Вы можете использовать это, чтобы библиотека диаграмм JavaScript отображала диаграмму.
Вот простой пример. Если у вас есть этот вид Блэйда…
<div id="target"></div>
<script> document.getElementById('target').innerHTML = 'hello'; </script>
… и визуализируем его с помощью этого кода…
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('your-view')->save($pathToPdf);
… текст hello
будет виден в PDF.
Тестирование PDF файлов
Создание PDF-файла может быть медленным, поскольку необходимо запустить весь экземпляр Chrome. В ваших тестах эта медлительность может раздражать. Вот почему в комплект поставки входит подделка в формате PDF. При использовании этой подделки не будет генерироваться PDF-файл, и ваши тесты будут выполняться быстрее.
// in your test
use Spatie\LaravelPdf\Facades\Pdf;
beforeEach(function () { Pdf::fake(); });
Если генерация PDF-файла подделана, вы можете использовать некоторые мощные методы проверки.
Вы можете использовать этот assertSaved
метод, чтобы подтвердить, что PDF-файл был сохранен с определенными свойствами. Вы должны передать ему вызываемый объект, который получит экземпляр Spatie\LaravelPdf\PdfBuilder
. Если вызываемый объект возвращает true
, утверждение пройдет.
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\PdfBuilder;
Pdf::assertSaved(function (PdfBuilder $pdf) {
return $pdf->downloadName === 'invoice.pdf' && str_contains($pdf->html, 'Your total for April is $10.00'));
});
Этот assertRespondedWithPdf
метод можно использовать для подтверждения того, что PDF-файл был создан и возвращен в качестве ответа.
Представьте, что у вас есть этот маршрут:
use Spatie\LaravelPdf\Facades\Pdf;
Route::get('download-invoice', function () { return pdf('pdf.invoice')->download('invoice-for-april-2022.pdf'); });
В тесте для этого маршрута вы можете использовать , assertRespondedWithPdf
чтобы убедиться, что PDF-файл был создан и возвращен в качестве загрузки. Вы даже можете делать утверждения о содержании PDF-файла.
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\PdfBuilder;
it('can download an invoice', function () {
$this->get('download-invoice')->assertOk();
Pdf::assertRespondedWithPdf(function (PdfBuilder $pdf) {
return $pdf->downloadName === 'invoice-for-april-2022.pdf' && $pdf->isDownload() && str_contains($pdf->html, 'Your total for April is $10.00'));
});
});
Создание PDF файлов на AWS Lambda
Локальное создание PDF-файлов может оказаться ресурсоемким. Если вам необходимо создать много PDF-файлов или у вас возникли проблемы с установкой необходимых зависимостей на вашем сервере, вы можете рассмотреть возможность использования AWS Lambda для создания PDF-файлов.
Чтобы создавать PDF-файлы в AWS Lambda, вам необходимо установить эти два пакета в свое приложение.
- Hammerstone/sidecar : это позволяет вам выполнять функции AWS Lambda из вашего приложения Laravel.
- wnx/sidecar-browsershot : этот пакет содержит версию Browsershot, которую можно запустить на AWS Lambda через Sidecar.
Установив эти два пакета, вы можете создавать PDF-файлы на AWS Lambda следующим образом:
Pdf::view('pdf.invoice', $data)->generateOnLambda()->save('invoice.pdf');
Если вы хотите создавать все PDF-файлы в своем приложении на Lambda, вы можете установить его по умолчанию следующим образом:
// typically, in a service provider
Pdf::default()->generateOnLambda();