ホームページ >バックエンド開発 >PHPチュートリアル >PHP_PHP チュートリアルを使用して Web ページで PDF ファイルを動的に生成する詳細なチュートリアル
この記事では、PHP を使用して PDF ファイルを動的に構築するプロセス全体について詳しく説明します。 Free PDF Library (FPDF) や PDFLib-Lite などのオープン ソース ツールを試し、PHP コードで PDF コンテンツの書式設定を制御します。
場合によっては、印刷するページのレンダリング方法を正確に制御する必要があります。この場合、HTML は最適な選択ではなくなります。 PDF ファイルを使用すると、ページのレンダリング方法やページ上でのテキスト、グラフィック、画像の表示方法を完全に制御できます。残念ながら、PDF ファイルの構築に使用される API は、PHP ツールキットの標準部分ではありません。ここで、少し手助けをする必要があります。
PHP の PDF サポートを Web で検索すると、最初に商用の PDFLib ライブラリとそのオープン ソース バージョンである PDFLib-Lite が見つかるかもしれません。 これらは素晴らしいライブラリですが、商用バージョンは非常に高価です。 PDFLib ライブラリのライト バージョンはオリジナル バージョンとしてのみ配布されており、ホスト環境にライト バージョンをインストールしようとするとこの制限が発生します。
もう 1 つのオプションは、Free PDF Library (FPDF) です。これはネイティブ PHP であり、コンパイルを必要とせず、完全に無料であるため、ライセンスのないバージョンの PDFLib のようにウォーターマークは表示されません。この無料の PDF ライブラリは、まさにこの記事で使用するものです。
女子ローラーダービー競技のスコアを使用して、PDF ファイルを動的に構築するプロセスを示します。これらのスコアは Web から取得され、XML に変換されます。リスト 1 は、サンプル XML データ ファイルを示しています。
リスト 1. XML データ
XML のルート要素は events タグです。データはイベントごとにグループ化されており、各イベントには複数の一致が含まれています。 events タグ内には一連のイベント タグがあり、これらのタグ内には複数のゲーム タグがあります。 これらのゲームタグには、ゲームに参加する 2 チームの名前とゲーム中のスコアが含まれています。
リスト 2 は、XML の読み取りに使用される PHP コードを示しています。
このスクリプトは、XML ファイルを DOM ドキュメントに読み取るための getResults 関数を実装します。次に、DOM 呼び出しを使用してすべてのイベント タグとゲーム タグを反復処理し、イベント配列を構築します。この配列の各要素は、イベント名と競技アイテムの配列を含むハッシュ テーブルです。構造は基本的に、XML 構造のメモリ内バージョンです。
このスクリプトの有効性をテストするために、HTML エクスポート ページを構築し、getResults 関数を使用してファイルを読み取り、一連の HTML テーブルの形式でデータを出力します。リスト 3 は、このテストに使用された PHP コードを示しています。
リスト 3. 結果の HTML ページ
コード getresults.php を使用すると、XML データ ファイルが Web サーバーにアップロードされ、図 1 と同様の HTML 結果を表示できます。
図 1. HTML 形式のコンテスト結果
この結果では、どのチームがどの試合に勝ったのかがわかるように、勝利チームが太字で表示されています。
PDFを構築
データを取得したら、PDF ファイルの構築に集中する必要があります。最初のステップは、FPDF ライブラリをダウンロードし、既存のアプリケーション ファイルセットと同じディレクトリにインストールすることです。実際、PHP ライブラリ パス内にあれば、どこにでもインストールできます。リスト 4 に示すように、「FPDF_FONTPATH」を設定する必要があるため、フォント ディレクトリをどこに置いたかを記録しておいてください。
リスト 4. PDF Hello World
このスクリプトは実際には「Hello World」ですが、HTML ではなく PDF 形式です。このスクリプトは最初に、define ステートメントを使用して FPDF フォント ディレクトリの場所を設定します。次に、require ステートメントを使用して FPDF ライブラリを導入します。このスクリプトは、ライブラリから FPDF オブジェクトを作成し、フォントを設定し、ページを追加してから、Cell メソッドを使用してページにテキストを配置し、PDF を出力します。
図 2 は、すべてが正常な場合の結果を示しています。
図 2. PDF 形式の Hello World
PDF が表示されない場合は、コマンドラインからこのスクリプトを実行して、fpdf.php ファイルが見つからないか、または他の問題があるかどうかを確認してください。
PDF が適切にレンダリングされたので、次にそれをスケート結果ファイルとマージし、何が動的に生成されるかを確認します。リスト 5 は、このマージ操作の最初のバージョンを示しています。
リスト 5. 結果を示す最初の PDF
我们没有从外部扩展 FPDF 类别,而是使用我们自己的 PDF 子类来扩展 FPDF 类别。在这些子类内,我们创建了一个名为 EventTable 的新方法,为给定事件构建了一个结果表。在这种情况下,我们从小处着手,只输出了事件名称。该名称位于脚本底部,包装在 foreach 循环中,该脚本为每个事件添加一个页面,然后调用 EventTable 方法。
可在 图 3 中看到这段脚本的输出。
图 3. 动态 PDF 的第一个版本
向下滚动页面,以展示每个事件都在自己的页面上。此处的下一步操作是开始将结果添加到页面。
构建结果表
在构建 PDF 文件时,构建无表结构就像构建 HTML 一样简单。构建表的方法是构建许多宽度、字体、填充颜色、行颜色等各不相同的单元。
清单 6 展示了设置表的标题栏的添加代码。
清单 6. 添加结果表标题
<?php define('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. 添加完整的结果表
<?php define('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. 添加徽标图像
<?php define('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票或票据,或填写表单,以及需要严格控制内容布局的任何项目。