PHP在網頁中動態產生PDF檔案詳細教程_php執行個體

來源:互聯網
上載者:User

本文詳細介紹使用 PHP 動態構建 PDF 檔案的整個過程。使用免費 PDF 庫 (FPDF) 或 PDFLib-Lite 等開源工具進行實驗,並使用 PHP 代碼控制 PDF 內容格式。

有時您需要準確控制要列印的頁面的呈現方式。在這種情況下,HTML 就不再是最佳選擇了。PDF 檔案使您能夠完全控制頁面的呈現方式,以及文本、圖形和映像在頁面上的呈現方式。遺憾的是,用來構建 PDF 檔案的 API 不屬於 PHP 工具包的標準組件。現在您需要提供一點協助。

當您在網路上搜尋,尋找對 PHP 的 PDF 支援時,您首先發現的可能是商業 PDFLib 庫及其開源版本 PDFLib-Lite。 這些都是很好的庫,但是商業版本相當昂貴。PDFLib 庫的精簡版本庫僅作為原始版本分發,當您嘗試在託管環境下安裝精簡版本時,就會出現這個限制問題。

另一種選擇是免費 PDF 庫 (FPDF),它是本機 PHP,無需要進行任何編譯,是完全免費的,因此,您不會像在未許可版本的 PDFLib 中那樣看到浮水印。這個免費的 PDF 庫正是我在本文中會用到的庫。

我們將使用女子旱滑比賽的得分來示範動態構建 PDF 檔案的過程。這些得分是從 Web 中獲得並被轉換成 XML。清單 1 顯示了一個樣本 XML 資料檔案。

清單 1. XML 資料

<events>  <event name="Beast of the East 2011">  <game score1="88" team1="Toronto Gore-Gore Rollergirls" team2="Montreal La Racaille" score2="11">  <game score1="58" team1="Toronto Death Track Dolls" team2="Montreal Les Contrabanditas" score2="49">   ... </game></game></event> <event name="Dustbowl Invitational 2011">   ... </event> <event name="The Great Yorkshire Showdown 2011">   ... </event></events>

XML 的根項目是一個 events 標記。按事件對資料進行分組,每個事件都包含多個比賽。在 events 標記內,是一系列的 event 標記,在這些標記中有多個 game 標記。 這些 game 標記中包含參加比賽的兩個隊的名稱以及他們在比賽中的得分。

清單 2 展示了用來讀取 XML 的 PHP 代碼。

<?phpfunction getResults() { $xml = new DOMDocument();  $xml->load('events.xml');  $events = array(); foreach($xml->getElementsByTagName('event') as $event) {   $games = array();  foreach($event->getElementsByTagName('game') as $game) {   $games []= array( 'team1' => $game->getAttribute('team1'),    'score1' => $game->getAttribute('score1'),    'team2' => $game->getAttribute('team2'),    'score2' => $game->getAttribute('score2') );  }  $events []= array( 'name' => $event->getAttribute('name'),   'games' => $games ); } return $events;}?>

這段指令碼實現了一個 getResults 函數,以便將 XML 檔案讀入 DOM 文檔。然後使用 DOM 調用遍曆所有 event 和 game 標記,以構建一個事件陣列。該數列內的每個元素都是一個散列表,包含事件名稱和比賽項目的陣列。結構基本上是 XML 結構的記憶體版。

為了測試這個指令碼的作用,將構建一個 HTML 匯出頁面,使用 getResults 函數讀取檔案,然後以一系列 HTML 表的形式輸出資料。清單 3 顯示了該測試所用的 PHP 代碼。

清單 3. 結果 HTML 頁面

<?phpinclude_once('getresults.php');$results = getResults();foreach( $results as $event ) {?><h1><?php echo( $event['name'] ) ?></h1><?phpforeach( $event['games'] as $game ) { $s1 = (int)$game['score1']; $s2 = (int)$game['score2'];?><?php}?><table><tbody><tr> <td style="font-weight:<?php echo( ( $s1 > $s2 ) ? 'bold' : 'normal') ?>">  <?php echo( $game['team1'] ) ?></td> <td><?php echo( $s1 ) ?></td> <td style="font-weight:<?php echo( ( $s2 > $s1 ) ? 'bold' : 'normal') ?>">  <?php echo( $game['team2'] ) ?></td> <td><?php echo( $s2 ) ?></td></tr></tbody></table><?php}?>

通過代碼 getresults.php,XML 資料檔案被上傳到 Web 服務器,您可以查看 HTML 結果,這與 圖 1 類似。
圖 1. HTML 格式的競賽結果

在該結果中,對獲勝隊使用了粗體,以便查看哪支隊贏得了哪場比賽。

構建 PDF

獲得資料之後,應將重點放在構建 PDF 檔案上。第一步是下載 FPDF 庫,然後將其安裝在與現有應用檔案集相同的目錄中。實際上,只要是在 PHP 庫路徑中,您可以將它安裝在任何您喜歡的地方。追蹤您放置字型目錄的地方,因為您需要設定 ‘FPDF_FONTPATH',如 清單 4 所示。

清單 4. PDF Hello World

<?phpdefine('FPDF_FONTPATH','/Library/WebServer/Documents/derby/font/');require( 'fpdf.php' );$pdf = new FPDF();$pdf->SetFont('Arial','',72);$pdf->AddPage();$pdf->Cell(40,10,"Hello World!",15);$pdf->Output();?>

這段指令碼實際上是一個 “Hello World”,但採用的是 PDF 格式而不是 HTML。這段指令碼執行的第一個操作是使用 define 語句設定 FPDF 字型目錄的位置。然後使用 require 語句引入 FPDF 庫。這段指令碼從該庫建立了一個 FPDF 對象,設定字型,添加一個頁面,然後使用 Cell 方法將一些文本放在該頁面上,並輸出 PDF。

圖 2 展示了一切都正常情況下的結果。

圖 2. PDF 格式的 Hello World

如果沒有看到 PDF,那麼您可能想在命令列運行這段指令碼,查看是否丟失了 fpdf.php 檔案或者存在其他問題。

既然 PDF 呈現正常,那麼現在應該將其與旱滑結果檔案合并,並查看可以動態產生哪些內容。清單 5 展示了該合併作業的第一個版本。

清單 5. 顯示結果的首版 PDF

<?phpdefine('FPDF_FONTPATH','/Library/WebServer/Documents/derby/font/');require( 'fpdf.php' );require( 'getresults.php' );class PDF extends FPDF{function EventTable($event){  $this->Cell(40,10,$event['name'],15);  $this->Ln();}}$pdf = new PDF();$pdf->SetFont('Arial','',48);foreach( getResults() as $event ) { $pdf->AddPage(); $pdf->EventTable($event); }$pdf->Output();?>

我們沒有從外部擴充 FPDF 類別,而是使用我們自己的 PDF 子類來擴充 FPDF 類別。在這些子類內,我們建立了一個名為 EventTable 的新方法,為給定事件構建了一個結果表。在這種情況下,我們從小處著手,只輸出了事件名稱。該名稱位於指令碼底部,封裝在 foreach 迴圈中,該指令碼為每個事件添加一個頁面,然後調用 EventTable 方法。

可在 圖 3 中看到這段指令碼的輸出。

圖 3. 動態 PDF 的第一個版本


向下滾動頁面,以展示每個事件都在自己的頁面上。此處的下一步操作是開始將結果添加到頁面。

構建結果表

在構建 PDF 檔案時,構建無表結構就像構建 HTML 一樣簡單。構建表的方法是構建許多寬度、字型、填充顏色、行顏色等各不相同的單元。

清單 6 展示了設定表的標題列的添加代碼。

清單 6. 添加結果表標題

<?phpdefine('FPDF_FONTPATH','/Library/WebServer/Documents/derby/font/');require( 'fpdf.php' );require( 'getresults.php' );class PDF extends FPDF{function EventTable($event){  $this->SetFont('','B','24');  $this->Cell(40,10,$event['name'],15);  $this->Ln();  $this->SetXY( 10, 45 );  $this->SetFont('','B','10');  $this->SetFillColor(128,128,128);  $this->SetTextColor(255);  $this->SetDrawColor(92,92,92);  $this->SetLineWidth(.3);  $this->Cell(70,7,"Team 1",1,0,'C',true);  $this->Cell(20,7,"Score 1",1,0,'C',true);  $this->Cell(70,7,"Team 2",1,0,'C',true);  $this->Cell(20,7,"Score 2",1,0,'C',true);  $this->Ln();}}$pdf = new PDF();$pdf->SetFont('Arial','',10);foreach( getResults() as $event ) { $pdf->AddPage(); $pdf->EventTable($event); }$pdf->Output();?>

此處的添加代碼用於設定字型、顏色和行寬。然後它將呈現包含四個標題列的幾個儲存格。然後調用 Ln 方法(該方法與斷行符號鍵等效)啟用一個新行。

在瀏覽器中查看這段指令碼時,可以看到類似 圖 4 的內容。

圖 4. 包含表的標題列的頁面

在 圖 4 中,標題以白色文本呈現在灰色背景上。這種格式有助於將其與呈現在標題下面的資料進行區分。要呈現比賽結果,請在 清單 7 中添加以下代碼。

清單 7. 添加完整的結果表

<?phpdefine('FPDF_FONTPATH','/Library/WebServer/Documents/derby/font/');require( 'fpdf.php' );require( 'getresults.php' );class PDF extends FPDF{function EventTable($event){  $this->SetFont('','B','24');  $this->Cell(40,10,$event['name'],15);  $this->Ln();  $this->SetFont('','B','10');  $this->SetFillColor(128,128,128);  $this->SetTextColor(255);  $this->SetDrawColor(92,92,92);  $this->SetLineWidth(.3);  $this->Cell(70,7,"Team 1",1,0,'C',true);  $this->Cell(20,7,"Score 1",1,0,'C',true);  $this->Cell(70,7,"Team 2",1,0,'C',true);  $this->Cell(20,7,"Score 2",1,0,'C',true);  $this->Ln();  $this->SetFillColor(224,235,255);  $this->SetTextColor(0);  $this->SetFont('');  $fill = false;  foreach($event['games'] as $game)  {    $this->SetFont('Times',((int)$game['score1']>(int)$game['score2'])?'BI':'');    $this->Cell(70,6,$game['team1'],'LR',0,'L',$fill);    $this->Cell(20,6,$game['score1'],'LR',0,'R',$fill);    $this->SetFont('Times',((int)$game['score1']<(int)$game['score2'])?'BI':'');    $this->Cell(70,6,$game['team2'],'LR',0,'L',$fill);    $this->Cell(20,6,$game['score2'],'LR',0,'R',$fill);    $this->Ln();    $fill =! $fill;  }  $this->Cell(180,0,'','T');}}$pdf = new PDF();$pdf->SetFont('Arial','',10);foreach( getResults() as $event ) { $pdf->AddPage(); $pdf->EventTable($event); }$pdf->Output();?>

除了標題列之外,在 EventTable 方法中還有一個 foreach 迴圈,它將在每個比賽上進行迭代。圖 5 顯示了用於此用途的代碼。

圖 5. 包含結果表的 PDF

$fill 變數可通過切換來改變表中每行的顏色。優勝隊的名稱和得分用加粗、斜體字型表示,這樣可以清晰顯示它們。還需注意的是,字型從標題的 Arial 字型更改成了顯示比賽內容所用的 Times 字型。

要完成範例程式碼,則需要添加一些圖形。

使用圖形進行修飾

向 PDF 添加映像非常容易。首先需要從 Web 抓取一個映像。我抓取了一個旱滑參賽隊的徽標,並將其儲存為 PNG 格式的映像。 此後,我一直使用 清單 8 中的新代碼。

清單 8. 添加徽標映像

<?phpdefine('FPDF_FONTPATH','/Library/WebServer/Documents/derby/font/');require( 'fpdf.php' );require( 'getresults.php' );class PDF extends FPDF{function EventTable($event){  $this->Image('logo.png',5,5,33);  $this->SetXY( 40, 15 );  $this->SetFont('','B','24');  $this->Cell(40,10,$event['name'],15);  $this->Ln();  $this->SetXY( 10, 45 );  $this->SetFont('','B','10');  $this->SetFillColor(128,128,128);  $this->SetTextColor(255);  $this->SetDrawColor(92,92,92);  $this->SetLineWidth(.3);  $this->Cell(70,7,"Team 1",1,0,'C',true);  $this->Cell(20,7,"Score 1",1,0,'C',true);  $this->Cell(70,7,"Team 2",1,0,'C',true);  $this->Cell(20,7,"Score 2",1,0,'C',true);  $this->Ln();  $this->SetFillColor(224,235,255);  $this->SetTextColor(0);  $this->SetFont('');  $fill = false;  foreach($event['games'] as $game)  {   $this->SetFont('Times',((int)$game['score1']>(int)$game['score2'])?'BI':'');   $this->Cell(70,6,$game['team1'],'LR',0,'L',$fill);   $this->Cell(20,6,$game['score1'],'LR',0,'R',$fill);   $this->SetFont('Times',((int)$game['score1']<(int)$game['score2'])?'BI':'');   $this->Cell(70,6,$game['team2'],'LR',0,'L',$fill);   $this->Cell(20,6,$game['score2'],'LR',0,'R',$fill);   $this->Ln();   $fill =! $fill;  }  $this->Cell(180,0,'','T');}}$pdf = new PDF();$pdf->SetFont('Arial','',10);foreach( getResults() as $event ) { $pdf->AddPage(); $pdf->EventTable($event); }$pdf->Output();?>

清單 8中的關鍵方法是 Image 方法,它為映像、位置和寬度選取一個檔案名稱。所有其它參數都是可選的,因此您只指定您想要的資訊便可。

到 SetXY 的一些新調用會將文本和表左右移動到適當的位置,防止其覆蓋映像。

圖 6 顯示了這段指令碼的輸出結果。

圖 6. 帶有徽標映像的已完成的 PDF

該 PDF 庫還提供了其他方法來呈現圖形、添加流文本、添加超連結、管理頁面邊界和方向等結構,您可以完全控制您的 PDF 檔案。

結束語


使用合適的工具,通過 PHP 構建 PDF 檔案是非常容易的。這種方法非常適用於列印發x票或票據,或填寫表單,以及需要嚴格控制內容布局的任何項目。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.