Heim  >  Artikel  >  Backend-Entwicklung  >  PHP在网页中动态生成PDF文件详细教程_PHP教程

PHP在网页中动态生成PDF文件详细教程_PHP教程

WBOY
WBOYOriginal
2016-07-13 10:26:411287Durchsuche

本文详细介绍使用 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 代码。

<&#63;php
function 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;
}
&#63;>

这段脚本实现了一个 getResults 函数,以便将 XML 文件读入 DOM 文档。然后使用 DOM 调用遍历所有 event 和 game 标记,以构建一个事件阵列。该数列内的每个元素都是一个散列表,包含事件名称和比赛项目的阵列。结构基本上是 XML 结构的内存版。

为了测试这个脚本的作用,将构建一个 HTML 导出页面,使用 getResults 函数读取文件,然后以一系列 HTML 表的形式输出数据。清单 3 显示了该测试所用的 PHP 代码。

清单 3. 结果 HTML 页面


<&#63;php
include_once('getresults.php');
$results = getResults();
foreach( $results as $event ) {
&#63;>
<h1><&#63;php echo( $event['name'] ) &#63;></h1>

<&#63;php
foreach( $event['games'] as $game ) {
 $s1 = (int)$game['score1'];
 $s2 = (int)$game['score2'];
&#63;>

<&#63;php
}
&#63;>
<table><tbody><tr>
 <td style="font-weight:<&#63;php echo( ( $s1 > $s2 ) &#63; 'bold' : 'normal') &#63;>">
  <&#63;php echo( $game['team1'] ) &#63;></td>
 <td><&#63;php echo( $s1 ) &#63;></td>
 <td style="font-weight:<&#63;php echo( ( $s2 > $s1 ) &#63; 'bold' : 'normal') &#63;>">
  <&#63;php echo( $game['team2'] ) &#63;></td>
 <td><&#63;php echo( $s2 ) &#63;></td>
</tr></tbody></table>
<&#63;php
}
&#63;>

通过代码 getresults.php,XML 数据文件被上传到 Web 服务器,您可以查看 HTML 结果,这与 图 1 类似。
图 1. HTML 格式的竞赛结果

在该结果中,对获胜队使用了粗体,以便查看哪支队赢得了哪场比赛。

构建 PDF

获得数据之后,应将重点放在构建 PDF 文件上。第一步是下载 FPDF 库,然后将其安装在与现有应用文件集相同的目录中。实际上,只要是在 PHP 库路径中,您可以将它安装在任何您喜欢的地方。追踪您放置字体目录的地方,因为您需要设置 ‘FPDF_FONTPATH',如 清单 4 所示。

清单 4. PDF Hello World

<&#63;php
define('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();
&#63;>

这段脚本实际上是一个 “Hello World”,但采用的是 PDF 格式而不是 HTML。这段脚本执行的第一个操作是使用 define 语句设置 FPDF 字体目录的位置。然后使用 require 语句引入 FPDF 库。这段脚本从该库创建了一个 FPDF 对象,设置字体,添加一个页面,然后使用 Cell 方法将一些文本放在该页面上,并输出 PDF。

图 2 展示了一切都正常情况下的结果。

图 2. PDF 格式的 Hello World

如果没有看到 PDF,那么您可能想在命令行运行这段脚本,查看是否丢失了 fpdf.php 文件或者存在其他问题。

既然 PDF 呈现正常,那么现在应该将其与旱滑结果文件合并,并查看可以动态生成哪些内容。清单 5 展示了该合并操作的第一个版本。

清单 5. 显示结果的首版 PDF

<&#63;php
define('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();
&#63;>

我们没有从外部扩展 FPDF 类别,而是使用我们自己的 PDF 子类来扩展 FPDF 类别。在这些子类内,我们创建了一个名为 EventTable 的新方法,为给定事件构建了一个结果表。在这种情况下,我们从小处着手,只输出了事件名称。该名称位于脚本底部,包装在 foreach 循环中,该脚本为每个事件添加一个页面,然后调用 EventTable 方法。

可在 图 3 中看到这段脚本的输出。

图 3. 动态 PDF 的第一个版本


向下滚动页面,以展示每个事件都在自己的页面上。此处的下一步操作是开始将结果添加到页面。

构建结果表

在构建 PDF 文件时,构建无表结构就像构建 HTML 一样简单。构建表的方法是构建许多宽度、字体、填充颜色、行颜色等各不相同的单元。

清单 6 展示了设置表的标题栏的添加代码。

清单 6. 添加结果表标题

<&#63;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();
&#63;>

此处的添加代码用于设置字体、颜色和行宽。然后它将呈现包含四个标题列的几个单元格。然后调用 Ln 方法(该方法与回车键等效)启用一个新行。

在浏览器中查看这段脚本时,可以看到类似 图 4 的内容。

图 4. 包含表的标题行的页面

在 图 4 中,标题以白色文本呈现在灰色背景上。这种格式有助于将其与呈现在标题下面的数据进行区分。要呈现比赛结果,请在 清单 7 中添加以下代码。

清单 7. 添加完整的结果表

<&#63;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'])&#63;'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'])&#63;'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();
&#63;>

除了标题行之外,在 EventTable 方法中还有一个 foreach 循环,它将在每个比赛上进行迭代。图 5 显示了用于此用途的代码。

图 5. 包含结果表的 PDF

$fill 变量可通过切换来改变表中每行的颜色。优胜队的名称和得分用加粗、斜体字体表示,这样可以清晰显示它们。还需注意的是,字体从标题的 Arial 字体更改成了显示比赛内容所用的 Times 字体。

要完成示例代码,则需要添加一些图形。

使用图形进行修饰

向 PDF 添加图像非常容易。首先需要从 Web 抓取一个图像。我抓取了一个旱滑参赛队的徽标,并将其存储为 PNG 格式的图像。 此后,我一直使用 清单 8 中的新代码。

清单 8. 添加徽标图像

<&#63;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'])&#63;'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'])&#63;'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();
&#63;>

清单 8中的关键方法是 Image 方法,它为图像、位置和宽度选取一个文件名称。所有其它参数都是可选的,因此您只指定您想要的信息便可。

到 SetXY 的一些新调用会将文本和表左右移动到适当的位置,防止其覆盖图像。

图 6 显示了这段脚本的输出结果。

图 6. 带有徽标图像的已完成的 PDF

该 PDF 库还提供了其他方法来呈现图形、添加流文本、添加超链接、管理页边距和方向等结构,您可以完全控制您的 PDF 文件。

结束语


使用合适的工具,通过 PHP 构建 PDF 文件是非常容易的。这种方法非常适用于打印发x票或票据,或填写表单,以及需要严格控制内容布局的任何项目。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/824611.htmlTechArticle本文详细介绍使用 PHP 动态构建 PDF 文件的整个过程。使用免费 PDF 库 (FPDF) 或 PDFLib-Lite 等开源工具进行实验,并使用 PHP 代码控制 PDF 内容格...
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn