如何使用Laravel snappy生成PDF并集成到Laravel-admin

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

下面由laravel教程欄目給大家介紹使用Laravel snappy生成PDF并集成到Laravel-admin的方法,希望對需要的朋友有所幫助!

如何使用Laravel snappy生成PDF并集成到Laravel-admin

laravel snappy

之前使用過python+wkhtmltopdf來導出PDF,wkhtmltopdf確實是很強大的工具,有很多的頁面定制選項,而且會自動幫你把網上的圖片抓取下來,渲染到PDF上。這次想在Laravel-admin中實現導出PDF的功能,于是找到了Laravel snappy這個擴展包,它是對https://github.com/KnpLabs/snappy這個項目的封裝,好巧的是,它也是通過調用wkhtmltopdf程序來生成PDF的。

安裝與配置

//?安裝擴展包 composer?require?barryvdh/laravel-snappy  //?將wkhtmltopdf作為composer依賴 //?對于64位系統,使用: composer?require?h4cc/wkhtmltopdf-amd64?0.12.x composer?require?h4cc/wkhtmltoimage-amd64?0.12.x

對于homestead開發環境,還要執行:

cp?vendor/h4cc/wkhtmltoimage-amd64/bin/wkhtmltoimage-amd64?/usr/local/bin/ cp?vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64?/usr/local/bin/  chmod?+x?/usr/local/bin/wkhtmltoimage-amd64? chmod?+x?/usr/local/bin/wkhtmltopdf-amd64

安裝完后,在app.config中alias鍵設置facade別名(可選):

'PDF'?=>?BarryvdhSnappyFacadesSnappyPdf::class, 'SnappyImage'?=>?BarryvdhSnappyFacadesSnappyImage::class,

最后發布資源文件:

php?artisan?vendor:publish?--provider="BarryvdhSnappyServiceProvider"

在.env文件中添加:

WKHTML_PDF_BINARY=/usr/local/bin/wkhtmltopdf-amd64 WKHTML_IMG_BINARY=/usr/local/bin/wkhtmltoimage-amd64

然后在snappy.php配置文件中做如下配置:

????'pdf'?=>?[ ????????'enabled'?=>?true, ????????'binary'??=>?env('WKHTML_PDF_BINARY',?'vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64'), ????????'timeout'?=>?3600, ????????'options'?=>?[], ????????'env'?????=>?[], ????],  ????'image'?=>?[ ????????'enabled'?=>?true, ????????'binary'??=>?env('WKHTML_IMG_BINARY',?'vendor/h4cc/wkhtmltoimage-amd64/bin/wkhtmltoimage-amd64'), ????????'timeout'?=>?3600, ????????'options'?=>?[], ????????'env'?????=>?[], ????],

使用

通過加載渲染blade模板生成PDF:

$pdf?=?PDF::loadView('pdf.invoice',?$data);?//pdf.invoice是你的blade模板 return?$pdf->download('invoice.pdf');

通過外部鏈接生成:

return?PDF::loadFile('http://www.github.com')->inline('github.pdf');

通過html生成,并做各種設置,并保存之:

PDF::loadHTML($html)->setPaper('a4')->setOrientation('landscape')->setOption('margin-bottom',?0)->save('myfile.pdf') //?更多選項可查看wkhtmltopdf的手冊:https://wkhtmltopdf.org/usage/wkhtmltopdf.txt

Laravel-admin導出功能改造

Laravel-admin默認的導出格式是csv,這里將把它改造成想要的PDF格式。

Laravel-admin導出原理簡單分析

查看導出按鈕,可得到這三個導出入口格式大概如下:

http://hostname/posts?_export_=all??//?導出全部 http://hostname/posts?_export_=page%3A1?//?導出當前頁 http://hostname/posts?_export_=selected%3A1?//?導出選定的行

其有對應的控制器方法應該是index,從這里追查開去,可以找到/vendor/encore/laravel-admin/src/Grid.php中有:

public?function?render(){ ????$this->handleExportRequest(true);?? ????try?{ ????????$this->build(); ????}?catch?(Exception?$e)?{ ????????return?Handler::renderException($e); ????} ????$this->callRenderingCallback(); ????return?view($this->view,?$this->variables())->render();}

如果url中有帶_export=…參數,將會執行$this->handleExportRequest(true);這里面的代碼:

protected?function?handleExportRequest($forceExport?=?false){ ????if?(!$scope?=?request(Exporter::$queryName))?{ ????????return; ????}  ????//?clear?output?buffer. ????if?(ob_get_length())?{ ????????ob_end_clean(); ????}  ????$this->disablePagination();  ????if?($forceExport)?{ ????????$this->getExporter($scope)->export();??//?這里將調用某個類的export方法 ????}}

最關鍵的是export方法,我們將新建一個繼承AbstractExporter類的類,實現我們自己想要的導出邏輯。另外,看getExporter方法:

protected?function?getExporter($scope){ ????return?(new?Exporter($this))->resolve($this->exporter)->withScope($scope);}

我們還可以在子類中改寫withScope進行一些參數設置、攔截。

開始改造導出功能

了解了基本的原理,再參考下Laravel-admin的文檔,我們就可以著手改下導出功能了。

首先,創建一個擴展,如app/Admin/Extensions/PdfExporter.php,代碼實現如下:

<?php namespace AppAdminExtensions;  use EncoreAdminGridExportersAbstractExporter; use EncoreAdminGridExporter; use PDF;  class PdfExporter extends AbstractExporter {     protected $lackOfUserId = false;      public function withScope($scope){         // 你自己的一些處理邏輯,比如:         /*if ($scope == Exporter::SCOPE_ALL) {             if(request()->has('user_id'))?{ ????????????????$this-&gt;grid-&gt;model()-&gt;where('user_id',?request()-&gt;user_id); ????????????}?else?{ ????????????????$this-&gt;lackOfUserId?=?true; ????????????} ????????????return?$this; ????????}*/ ????????return?parent::withScope($scope); ????}  ????public?function?export() ????{ ????????//?具體的導出邏輯,比如: ????????if($this-&gt;lackOfUserId)?{ ????????????$headers?=?[ ????????????????'Content-Encoding'????=&gt;?'UTF-8', ????????????????'Content-Type'????????=&gt;?'text/html;charset=UTF-8', ????????????]; ????????????response('請先篩選出用戶',?200,?$headers)-&gt;send(); ????????????exit(); ????????} ????????$author?=?$this-&gt;grid-&gt;model()-&gt;getOriginalModel()-&gt;first()-&gt;user-&gt;user_name;  ????????$this-&gt;grid-&gt;model()-&gt;orderBy('add_time',?'desc');  ????????//?按年-月分組數據 ????????$data?=?collect($this-&gt;getData())-&gt;groupBy(function?($post)?{ ????????????return?Carbon::parse(date('Y-m-d',$post['add_time']))-&gt;format('Y-m'); ????????})-&gt;toArray(); ????????//?渲染數據到blade模板 ????????$output?=?PDF::loadView('pdf.weibo',?compact('data'))-&gt;setOption('footer-center',?'[page]')-&gt;output();  ????????$headers?=?[ ????????????'Content-Type'????????=&gt;?'application/pdf', ????????????'Content-Disposition'?=&gt;?"attachment;?filename=$author.pdf", ????????];  ????????//?導出文件, ????????response(rtrim($output,?"n"),?200,?$headers)-&gt;send();  ????????exit; ????} }

接著,在app/Admin/bootstrap.php中注冊擴展:

Exporter::extend('pdf-exporter',?PdfExporter::class);

最后,對應的在Grid方法中使用:

protected?function?grid(){ ????//?其他邏輯...  ????//?添加導出PDF的擴展 ????$grid-&gt;exporter('pdf-exporter'); ????return?$grid;}

這樣,點擊導出按鈕的時候,就可以下載PDF了。

注意事項

  • blade模板中的cssJS地址必須是完整的url地址,所以mix(‘css/app.css’)應該改為asset(‘css/app.css’)
  • 圖片地址最好使用http協議代替https,比較不容易出錯

最后,貼個效果圖吧:

如何使用Laravel snappy生成PDF并集成到Laravel-admin

? ? ? ? ? ? ? ? ? ? ? ? ? ?

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享