برای وبسایتها یا وب اپلیکیشنهای که حاوی برگههای فاکتور، سندهای بزرگ، یک مقولهی نیاز به چاپ و یا خیلی موارد دیگر هستند وجود قسمتی برای تولید PDF بسیار ضروری است و این مورد یکی از نیازها و ویژگیهای اصلی این نوع اپلیکیشنها میتوانید باشد. بنابراین اگر ما در اپلیکیشن خود نیاز داشته باشیم که یک سند چند صفحهای را ارائه دهیم چه کاری باید انجام دهیم؟
در این صورت شما میتوانید از WKHTML استفاده کنید و آن را با لاراول ادغام کنید.
توجه
اول از همه، اگر شما برای این مشکل یک راه حل سریع و آماده میخواهید، میتوانید از این پکیج استفاده کنید، اما در اینجا شما از همه توابعی که این پکیج ارائه میدهد استفاده نخواهید کرد همچنین شما به برخی از وابستگیها که باعث ایجاد وابستگی دیگر میشوند نیاز نخواهید داشت.
در این مقاله روش ما خیلی ساده است. به طور خلاصه، ایجاد سرویس و ارائه جایی برای اتصال سرویس به کانتینر، پس از آن پیکربندی اصلی سرویس را انجام میدهیم و کنترلر را آماده میکنیم تا در آن PDF برای مشاهده یا بارگیری آماده شود.
سرویس PDF
اولین کاری که باید انجام بدهیم نصب دو پکیج WKHTML و Snappy است. ما میتوانیم این دو پکیج را از طریق کامپوز نصب کنیم، بسته به نوع سیستم خود میتوانید پکیج متناسب با آن را نصب کنید. برای من با استفاده از کد زیر در ترمینال پکیج نصب می شود:
composer require h4cc/wkhtmltopdf-amd64
پس از آن ما نیاز به نصب پکیج Snappy داریم برای این کار کد
composer require knplabs/knp-snappy
در ترمینال وارد می کنیم.
حالا تمام نیازمندیها فراهم شدهاند و پس از آن ما میتوانیم سرویس PDF خود را آماده کنیم.
namespace App\Services;
use App\Invoice;
use Knp\Snappy\Pdf as Snappy;
use Illuminate\Support\Facades\View;
class Pdf extends Snappy
{
/**
* Initialize a new pdf instance.
*
* @param array $config
* @return void
*/
public function __construct(array $config = [])
{
parent::__construct($config['binary'], $config['generator']);
}
/**
* Render the PDF preview.
*
* @param \App\Invoice $invoice
* @return string
*/
public function render(Invoice $invoice)
{
return $this->getOutputFromHtml(
View::make('your.blade.template', compact('invoice'))->render()
);
}
}
همانطور که در کد بالا میبینید ما یک فاکتور(Invoic) برای اجرا کردن قرار دادیم البته شما میتوانید هر چیز دیگری که نیاز دارید را در اینجا قرار دهید.
ریجستر کردن سرویس در provider
با استفاده از کد زیر در ترمینال ما میتوانیم یک provider جدید ایجاد کنیم:
namespace App\Providers;
use App\Services\Pdf;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Support\DeferrableProvider;
class PdfServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->bind(Pdf::class, function ($app) {
return new Pdf($app['config']['pdf']);
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [Pdf::class];
}
}
نکته: توجه کنید، از لاراول ورژن 5.8 ، ویژگی $defer منسوخ شده است. Providerهای معوق(Deferred) باید به صورت DeferrableProvider پیاده سازی شوند، مانند مثال بالا.
بنابراین هیچ چیز جدیدی در اینجا وجود ندارد. ما سرویس خود را به کانتینر متصل کردیم و پس از آن به طور خودکار پیکربندی(config) به عنوان یک نمونه(instance) به آن منتقل میشود، بدین معنا که هر زمانی که نیاز به استفاده از سرویس داریم پیکربندی به صورت خودکار تزریق میشود و ما نیاز نداریم که کاری را به صورت دستی انجام دهیم.
صحبت از پیکربندی شد در ادامه اجازه دهید به بررسی فایل پیکربندی بپردازیم.
پیکربندی اصلی
پیکربندی اصلی باید چیزی شبیه به زیر باشد. ما مسیر binary را مشخص کردیم و همچنین ممکن است شما بخواهید مسیر را از فایل .env دریافت کنید.
// config/pdf.php
<?php
return [
'binary' => env('WKHTML_PATH', realpath(h4cc\WKHTMLToPDF\WKHTMLToPDF::PATH)),
'generator' => [
'images' => true,
'no-images' => false,
'encoding' => 'utf-8',
'disable-smart-shrinking' => true,
'page-size' => 'A4',
'margin-top' => 0,
'margin-left' => 0,
'margin-right' => 0,
'margin-bottom' => 0,
],
];
کنترلر PDF
در ابتدا بیایید با استفاده از دستور زیر در ترمینال
php artisan make:controller PdfController
کنترلر خود را ایجاد کنیم و پس از آن روت مربوط به کنترلر را در فایل روتهای web تعریف کنیم:
Route::get('invoice/{invoice}', 'PdfController');
حالا به کنترلر زیر نگاه کنید:
namespace App\Http\Controllers;
use App\Invoice;
use App\Services\Pdf;
use Illuminate\Http\Request;
class PdfController extends Controller
{
/**
* The pdf instance.
*
* @var \App\Services\Pdf
*/
protected $pdf;
/**
* Create a new controller instance.
*
* @param \App\Services\Pdf $pdf
* @return void
*/
public function __construct(Pdf $pdf)
{
$this->middleware('auth');
$this->pdf = $pdf;
}
/**
* Generate the PDF to inspect or download.
*
* @param \Illuminate\Http\Request $request
* @param \App\Invoice $invoice
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request, Invoice $invoice)
{
return response($this->pdf->render($invoice), 200)->withHeaders([
'Content-Type' => 'application/pdf',
'Content-Disposition' => ($request->has('download') ? 'attachment' : 'inline') . "; filename='invoice-{$invoice->id}.pdf'",
]);
}
}
همانطور که می بینید، هنگامی که کاربر روت invoice را مشاهده میکند، PDF رندر میشود؛ همچنین اگر کوئری حاوی کلید download باشد، فایل pdf دانلود میشود در غیر این صورت از طریق مرورگر به صورت آنلاین قابل مشاهده و خواندن خواهد بود.
نتیجهگیری
این روش در صورتی پیشنهاد میشود که شما یک سند بزرگ(بیشتر از 10 صفحه) داشته باشید همچنین اگر هنگام نصب و راه اندازی آن دچار اشتباه شوید و به خطایی بربخورید، خطایابی آن چندان آسان نخواهد بود. بنابراین حتماً مطمئن شوید که یک libssl در سیستم شما نصب شده باشد، همچنین مطمئن شوید که binaries قابل اجرا شدن هستند.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید