در برخی مواقع مانند زمانی که میخواهید فاکتور فروش محصول یا مواردی مشابه این را ایجاد کنید، ممکن است نیاز به تولید یک فایل PDF داشته باشید. برای این منظور پکیجهای متنوعی در لاراول توسعه داده شده است. اما ایراد عمدهی این پکیجها این است که از زبان فارسی به درستی پشتیبانی نمیکنند. در نتیجه انتخابهای ما محدودتر هستند. نکته دیگر این است که معمولا این پکیجها یک فایل HTML را به فایل PDF با همان ساختار تبدیل میکنند. محدودیتی که در این روش وجود دارد این است که تمام قابلیتهایی که به کمک CSS بر روی یک فایل HTML میتوان اعمال نمود در این روش پشتیبانی نمیشوند. مثلا برخی از پکیج ها از فونتهای پیشفرض استفاده میکنند و امکان تعیین فونت دلخواه در آنها وجود ندارد و یا اینکه امکان تعریف Style ها در فایل مجزا را ندارند. برای این منظور، در این آموزش سعی میکنیم تا حد امکان، تبدیل HTML به PDF در لاراول را با هدف ساخت فایلهای PDF فارسی با فونت دلخواه و Style دهی مناسب دنبال کنیم.
پکیج تبدیل HTML به PDF در لارول
با توجه به محدودیتهایی که پیشتر مطرح شد، پکیجی که به درستی از زبان فارسی پشتیبانی کند،/ laravel-pdf اس که بر پایه کتابخانه mpdf توسعه یافته است. این کتابخانه پایه امکانات لازم برای ساخت فایلهای PDF بر پایه استاندارد کاراکترهای UTF-8 را فراهم میکند. برای نصب پکیج ابتدا باید دستور زیر را در مسیر پروژه لاراول خود اجرا کنید:
composer require niklasravnsborg/laravel-pdf
در گام بعد باید سراغ فایل app.php در پوشهی config پروژه خود بروید و در بخش providers مسیر پکیج جدید را اضافه کنید.
'providers' => [
//
niklasravnsborg\LaravelPdf\PdfServiceProvider::class,
],
همچنین در همین فایل و در قسمت aliases باید مقدار مربوط به این پکیج را وارد نمایید.
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
'PDF' => niklasravnsborg\LaravelPdf\Facades\Pdf::class
])->toArray(),
پس از انجام مراحل بالا، باید دستور زیر را وارد کنید تا فایل تنظیمات پکیج در پوشهی config پروژه ایجاد شود.
php artisan vendor:publish
با اجرای دستور بالا فایل pdf.php در مسیر config پروژه ایجاد میگردد. برای پشتیبانی از فونت دلخواه و نمایش درست کاراکترهای فارسی، تنظیمات زیر را در این فایل قرار دهید.
return [
'mode' => 'utf-8',
'format' => 'A4',
'author' => '',
'subject' => '',
'keywords' => '',
'creator' => 'Laravel Pdf',
'display_mode' => 'fullpage',
'tempDir' => base_path('storage/temp'),
'font_path' => base_path('storage/fonts/'),
'font_data' => [
'vazir' => [
'R' => 'Vazir.ttf', // regular font
'B' => 'Vazir.ttf', // optional: bold font
'I' => 'Vazir.ttf', // optional: italic font
'BI' => 'Vazir.ttf', // optional: bold-italic font
'useOTL' => 0xFF, // required for complicated langs like Persian, Arabic and Chinese
'useKashida' => 75, // required for complicated langs like Persian, Arabic and Chinese
] // ...add as many as you want.
]
];
با توجه به تنظیمات بالا، در پوشهی storage باید پوشههای زیر را ایجاد کنید.
- temp
- fonts
همچنین در داخل پوشهی fonts فایل مربوط به فونت دلخواه را قرار دهید به نحوی که نام آن در تنظیمات صحیح باشد. در مثال این پست فرض بر این است که نام فونت Vazir.ttf است.
پس از انجام مراحل بالا باید صفحه مورد نظر برای تولید فایل pdf که در اصل یکی از view ها است را ایجاد کنیم. در نتیجه به پوشه resourrces/views بروید و پوشهی reports را ایجاد کنید و سپس فایلی مثلا با نام invoice.blade.php بسازید. کد زیر را درون این فایل قرار دهید:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Title</title>
<style>
body {
font-family: 'vazir';
direction: rtl;
}
</style>
</head>
<body>
<h1>{{ $data['title'] }}</h1>
</body>
</html>
حال برای اینکه فایل pdf تولید شود، کافیست یک کنترولر بسازیم. برای اینکار میتوان از این دستور استفاده کرد:
php artisan make:controller Web/InvoiceController
حالا کدهای زیر را در کنترلر ایجاد شده کپی میکنیم:
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use niklasravnsborg\LaravelPdf\Facades\Pdf;
class InvoiceController extends Controller
{
public function generatePDF()
{
$data = [
'title' => 'این یک فایل PDF تولید شده با لاراول است.'
];
$pdf = Pdf::loadView('reports.invoice', compact('data'));
return $pdf->stream('report.pdf');
}
}
در آخر کافیست تا یک مسیر برای این متد کنترلر بنویسیم تا با مراجعه به آن، فایل PDF خروجی را مشاهده کنیم. برای این کار در پوشهی routes و فایل web.php یک مسیر مانند کد زیر تعریف میکنیم:
use App\Http\Controllers\Web\InvoiceController;
...
Route::get('invoice', [InvoiceController::class, 'generatePDF']);
حالا، کافیست تا با دستور زیر، پروژه را در سیستم خود به صورت local اجرا کنیم:
php artisan serv
پس از اجرای پروژه، برای مشاهده خروجی کار باید با مرورگر سیستم خود به آدرس http://localhost:8000/invoice مراجعه کنیم. فایل نهایی بصورت تصویر زیر نمایان خواهد شد.
تغییر تنظیمات تولید PDF
اگر در یک گزارش/فاکتور خاص، خواستید تنظیمات پیش فرض را بازنویسی کرده و تغییر دهید، مثلا به جای تولید گزارش در سایز برگهی A4 ابعاد را به A5 و حالت Landscape تغییر دهید، میتوانید از نمونه کد زیر استفاده کنید:
$pdf = Pdf::loadView('reports.invoice', compact('data'),[], [
'format' => 'A5-L', // size: A5 Landscape
]);
نتیجهی این تغییر تنظیمات، خروجی را به صورت زیر تغییر خواهد داد:
قرار دادن Header و Footer در فایل PDF
برای اینکار باید تغییراتی را در فایل view مربوط به گزارش اعمال کنیم. برای این منظور، فایل view را بصورت زیر تغییر دهید:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Title</title>
<style>
body {
font-family: 'vazir';
direction: rtl;
}
@page {
header: page-header;
footer: page-footer;
}
</style>
</head>
<body>
<htmlpageheader name="page-header">
<p style="text-align:center">
محل قرارگیری محتوای Header
</p>
</htmlpageheader>
<htmlpagefooter name="page-footer">
<p style="text-align:center">
محل قرارگیری محتوای Footer
</p>
</htmlpagefooter>
<h1 style="text-align:center">{{ $data['title'] }}</h1>
</body>
</html>
نتیجهی تغییرات بالا، خروجی زیر را ایجاد خواهد کرد:
ساخت نامهی مرخصی روزانه در قالب PDF با لاراول
برای اینکار باید نحوهی قرار دادن تصاویر، شماره صفحه و قرار دادن محلی ثابت برای امضادر پایین برگه را در نظر بگیریم. به نمونه قالب HTML زیر دقت کنید:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Title</title>
<style>
body {
font-family: 'vazir';
direction: rtl;
}
strong{
font-weight: bold;
}
@page {
header: page-header;
footer: page-footer;
size: 8.5in 11in;
/* <length>{1,2} | auto | portrait | landscape */
/* 'em' 'ex' and % are not allowed; length values are width height */
margin: 15% 10% 10% 10%;
/* <any of the usual CSS values for margins> */
/*(% of page-box width for LR, of height for TB) */
margin-header: 5mm;
/* <any of the usual CSS values for margins> */
margin-footer: 5mm;
/* <any of the usual CSS values for margins> */
}
.logo {
width: 2cm;
height: 2cm;
}
.emza {
width: 4cm;
height: 4cm;
}
</style>
</head>
<body>
<htmlpageheader name="page-header">
<p style="text-align:center">
<img class="logo" src="https://www.graphiciran.net/wp-content/uploads/2015/12/iran-logo-download.jpg" alt="">
</p>
</htmlpageheader>
<htmlpagefooter name="page-footer">
<p style="text-align:center">
{PAGENO} از {nbpg}
</p>
</htmlpagefooter>
<h4>جناب آقای {{ $data['hr_name'] }}</h4>
<h4>رییس محترم امور کارکنان</h4>
<h4>موضوع : درخواست مرخصی بدون حقوق</h4>
<h4>با سلام و احترام</h4>
<p style="text-align: justify;">
بدینوسیله به استحضار می رساند اینجانب آقای/خانم <strong>{{ $data['full_name'] }}</strong> با توجه بروز برخی مشکلات خانوادگی / تحصیلی / شخصی متقاضی استفاده از مرخصی بدون حقوق به مدت <strong>{{ $data['duration'] }}</strong> ماه از تاریخ <strong>{{ $data['from_date'] }}</strong> میباشم. خواهشمند است درصورت صلاحدید با توجه به نیاز مبرم و ضرورت موضوع برای اینجانب با تقاضای اینجانب موافقت و دستورات لازم را در این خصوص صادر فرمایید.
پیشاپیش از مساعدت و حسن اعتماد جنابعالی کمال تشکر را دارم.
</p>
<div style="position: fixed; left: 0mm; bottom: 0mm;">
<p>با تشکر، {{ $data['full_name'] }}</p>
<img class="emza" src="https://setare.com/files/1397/11/09/%D9%86%D9%85%D9%88%D9%86%D9%87-%D8%A7%D9%85%D8%B6%D8%A7-%D8%B3%D8%A7%D8%AF%D9%87.svg" />
</div>
</body>
</html>
برای رندر قالب بالا در لاراول لازم است تا دادههای مورد نیاز به صورت کد زیر در اختیار view قرار گیرد:
public function generatePDF()
{
$data = [
'title' => 'این یک فایل PDF تولید شده با لاراول است.',
'hr_name' => 'مهندس تستیان',
'full_name' => 'مهندس فردین رستمی',
'duration' => 2,
'from_date' => '1401/05/25'
];
$pdf = Pdf::loadView('reports.invoice', compact('data'),[], [
'format' => 'A5',
]);
return $pdf->stream('report.pdf');
}
خروجی کد بالا بصورت زیر خواهد بود:
موفق و پیروز باشید.
سلام من مراحل شمارو رفتم ولی فونت رو فارسی نمیکنه
سلام
برنامه خوب بود اما چگونه میتوان بجای دانلود تو مرورگر نمایش داد