首頁  >  文章  >  php框架  >  如何使用Laravel snappy產生PDF並整合到Laravel-admin

如何使用Laravel snappy產生PDF並整合到Laravel-admin

藏色散人
藏色散人轉載
2020-08-15 13:54:283779瀏覽

Laravel snappy如何使用Laravel snappy產生PDF並整合到Laravel-admin

之前使用過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' => Barryvdh\Snappy\Facades\SnappyPdf::class,
'SnappyImage' => Barryvdh\Snappy\Facades\SnappyImage::class,

最後發布資源檔案:<pre class="brush:php;toolbar:false">php artisan vendor:publish --provider=&quot;Barryvdh\Snappy\ServiceProvider&quot;</pre>.env 檔案中新增:

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

然後在

snappy.php

設定檔中做以下設定:<pre class="brush:php;toolbar:false"> &amp;#39;pdf&amp;#39; =&gt; [ &amp;#39;enabled&amp;#39; =&gt; true, &amp;#39;binary&amp;#39; =&gt; env(&amp;#39;WKHTML_PDF_BINARY&amp;#39;, &amp;#39;vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64&amp;#39;), &amp;#39;timeout&amp;#39; =&gt; 3600, &amp;#39;options&amp;#39; =&gt; [], &amp;#39;env&amp;#39; =&gt; [], ], &amp;#39;image&amp;#39; =&gt; [ &amp;#39;enabled&amp;#39; =&gt; true, &amp;#39;binary&amp;#39; =&gt; env(&amp;#39;WKHTML_IMG_BINARY&amp;#39;, &amp;#39;vendor/h4cc/wkhtmltoimage-amd64/bin/wkhtmltoimage-amd64&amp;#39;), &amp;#39;timeout&amp;#39; =&gt; 3600, &amp;#39;options&amp;#39; =&gt; [], &amp;#39;env&amp;#39; =&gt; [], ],</pre>

使用

透過載入渲染blade模板生成PDF:

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

透過外部連結生成:

return PDF::loadFile(&#39;http://www.github.com&#39;)->inline(&#39;github.pdf&#39;);
透過html生成,並做各種設置,並保存之:

PDF::loadHTML($html)->setPaper(&#39;a4&#39;)->setOrientation(&#39;landscape&#39;)->setOption(&#39;margin-bottom&#39;, 0)->save(&#39;myfile.pdf&#39;)
// 更多选项可查看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);這裡面的程式碼:<pre class="brush:php;toolbar:false;">protected function handleExportRequest($forceExport = false){ if (!$scope = request(Exporter::$queryName)) { return; } // clear output buffer. if (ob_get_length()) { ob_end_clean(); } $this-&gt;disablePagination(); if ($forceExport) { $this-&gt;getExporter($scope)-&gt;export(); // 这里将调用某个类的export方法 }}</pre>最關鍵的是

export

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

getExporter

方法:<pre class="brush:php;toolbar:false;">protected function getExporter($scope){ return (new Exporter($this))-&gt;resolve($this-&gt;exporter)-&gt;withScope($scope);}</pre>我們也可以在子類別中改寫withScope進行一些參數設定、攔截。

開始改造導出功能

了解了基本的原理,再參考下Laravel-admin的文檔,我們就可以著手改下導出功能了。 首先,建立一個擴展,如app/Admin/Extensions/PdfExporter.php,程式碼實作如下:

<?php

namespace App\Admin\Extensions;

use Encore\Admin\Grid\Exporters\AbstractExporter;
use Encore\Admin\Grid\Exporter;
use PDF;

class PdfExporter extends AbstractExporter
{
    protected $lackOfUserId = false;

    public function withScope($scope){
        // 你自己的一些处理逻辑,比如:
        /*if ($scope == Exporter::SCOPE_ALL) {
            if(request()->has(&#39;user_id&#39;)) {
                $this->grid->model()->where(&#39;user_id&#39;, request()->user_id);
            } else {
                $this->lackOfUserId = true;
            }
            return $this;
        }*/
        return parent::withScope($scope);
    }

    public function export()
    {
        // 具体的导出逻辑,比如:
        if($this->lackOfUserId) {
            $headers = [
                &#39;Content-Encoding&#39;    => &#39;UTF-8&#39;,
                &#39;Content-Type&#39;        => &#39;text/html;charset=UTF-8&#39;,
            ];
            response(&#39;请先筛选出用户&#39;, 200, $headers)->send();
            exit();
        }
        $author = $this->grid->model()->getOriginalModel()->first()->user->user_name;

        $this->grid->model()->orderBy(&#39;add_time&#39;, &#39;desc&#39;);

        // 按年-月分组数据
        $data = collect($this->getData())->groupBy(function ($post) {
            return Carbon::parse(date(&#39;Y-m-d&#39;,$post[&#39;add_time&#39;]))->format(&#39;Y-m&#39;);
        })->toArray();
        // 渲染数据到blade模板
        $output = PDF::loadView(&#39;pdf.weibo&#39;, compact(&#39;data&#39;))->setOption(&#39;footer-center&#39;, &#39;[page]&#39;)->output();

        $headers = [
            &#39;Content-Type&#39;        => &#39;application/pdf&#39;,
            &#39;Content-Disposition&#39; => "attachment; filename=$author.pdf",
        ];

        // 导出文件,
        response(rtrim($output, "\n"), 200, $headers)->send();

        exit;
    }
}

接著,在

app/Admin/ bootstrap.php

中註冊擴充功能:<pre class="brush:php;toolbar:false;">Exporter::extend(&amp;#39;pdf-exporter&amp;#39;, PdfExporter::class);</pre>最後,對應的在

Grid

方法中使用:<pre class="brush:php;toolbar:false;">protected function grid(){ // 其他逻辑... // 添加导出PDF的扩展 $grid-&gt;exporter(&amp;#39;pdf-exporter&amp;#39;); return $grid;}</pre>這樣,點擊匯出按鈕的時候,就可以下載PDF了。

注意事項

blade範本中的css、js位址必須是完整的url位址,所以mix( 'css/app.css')應該改為asset('css/app.css')

  • 圖片位址最好使用http協定取代https,比較不容易出錯最後,請貼個效果圖:
                           

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

###

以上是如何使用Laravel snappy產生PDF並整合到Laravel-admin的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除