PHP在网页中动态生成PDF文件详细教程
本文详细介绍使用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> <eventname="BeastoftheEast2011"> <gamescore1="88"team1="TorontoGore-GoreRollergirls"team2="MontrealLaRacaille"score2="11"> <gamescore1="58"team1="TorontoDeathTrackDolls"team2="MontrealLesContrabanditas"score2="49"> ... </game></game></event> <eventname="DustbowlInvitational2011"> ... </event> <eventname="TheGreatYorkshireShowdown2011"> ... </event> </events>
XML的根元素是一个events标记。按事件对数据进行分组,每个事件都包含多个比赛。在events标记内,是一系列的event标记,在这些标记中有多个game标记。这些game标记中包含参加比赛的两个队的名称以及他们在比赛中的得分。
清单2展示了用来读取XML的PHP代码。
<?php functiongetResults(){ $xml=newDOMDocument(); $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页面
<?php include_once("getresults.php"); $results=getResults(); foreach($resultsas$event){ ?> <h1><?phpecho($event["name"])?></h1> <?php foreach($event["games"]as$game){ $s1=(int)$game["score1"]; $s2=(int)$game["score2"]; ?> <?php } ?> <table><tbody><tr> <tdstyle="font-weight:<?phpecho(($s1>$s2)?"bold":"normal")?>"> <?phpecho($game["team1"])?></td> <td><?phpecho($s1)?></td> <tdstyle="font-weight:<?phpecho(($s2>$s1)?"bold":"normal")?>"> <?phpecho($game["team2"])?></td> <td><?phpecho($s2)?></td> </tr></tbody></table> <?php } ?>
通过代码getresults.php,XML数据文件被上传到Web服务器,您可以查看HTML结果,这与图1类似。
图1.HTML格式的竞赛结果
在该结果中,对获胜队使用了粗体,以便查看哪支队赢得了哪场比赛。
构建PDF
获得数据之后,应将重点放在构建PDF文件上。第一步是下载FPDF库,然后将其安装在与现有应用文件集相同的目录中。实际上,只要是在PHP库路径中,您可以将它安装在任何您喜欢的地方。追踪您放置字体目录的地方,因为您需要设置‘FPDF_FONTPATH",如清单4所示。
清单4.PDFHelloWorld
<?php define("FPDF_FONTPATH","/Library/WebServer/Documents/derby/font/"); require("fpdf.php"); $pdf=newFPDF(); $pdf->SetFont("Arial","",72); $pdf->AddPage(); $pdf->Cell(40,10,"HelloWorld!",15); $pdf->Output(); ?>
这段脚本实际上是一个“HelloWorld”,但采用的是PDF格式而不是HTML。这段脚本执行的第一个操作是使用define语句设置FPDF字体目录的位置。然后使用require语句引入FPDF库。这段脚本从该库创建了一个FPDF对象,设置字体,添加一个页面,然后使用Cell方法将一些文本放在该页面上,并输出PDF。
图2展示了一切都正常情况下的结果。
图2.PDF格式的HelloWorld
如果没有看到PDF,那么您可能想在命令行运行这段脚本,查看是否丢失了fpdf.php文件或者存在其他问题。
既然PDF呈现正常,那么现在应该将其与旱滑结果文件合并,并查看可以动态生成哪些内容。清单5展示了该合并操作的第一个版本。
清单5.显示结果的首版PDF
<?php define("FPDF_FONTPATH","/Library/WebServer/Documents/derby/font/"); require("fpdf.php"); require("getresults.php"); classPDFextendsFPDF { functionEventTable($event) { $this->Cell(40,10,$event["name"],15); $this->Ln(); } } $pdf=newPDF(); $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.添加结果表标题
<?php define("FPDF_FONTPATH","/Library/WebServer/Documents/derby/font/"); require("fpdf.php"); require("getresults.php"); classPDFextendsFPDF { functionEventTable($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,"Team1",1,0,"C",true); $this->Cell(20,7,"Score1",1,0,"C",true); $this->Cell(70,7,"Team2",1,0,"C",true); $this->Cell(20,7,"Score2",1,0,"C",true); $this->Ln(); } } $pdf=newPDF(); $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"); classPDFextendsFPDF { functionEventTable($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,"Team1",1,0,"C",true); $this->Cell(20,7,"Score1",1,0,"C",true); $this->Cell(70,7,"Team2",1,0,"C",true); $this->Cell(20,7,"Score2",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=newPDF(); $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"); classPDFextendsFPDF { functionEventTable($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,"Team1",1,0,"C",true); $this->Cell(20,7,"Score1",1,0,"C",true); $this->Cell(70,7,"Team2",1,0,"C",true); $this->Cell(20,7,"Score2",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=newPDF(); $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票或票据,或填写表单,以及需要严格控制内容布局的任何项目。
相关文章
- php格式怎么转换为pdf,PHP如何将将word文件转为pdf
- 4种方式优化服务器,可以提高PHP性能
- php读取pdf文件_php怎么转换成pdf
- php-文件上传
- 如何保护Wp-Config.Php文件
- PHP遍历文件夹下所有文件和文件夹
- PHP异步MySQL:提升网站性能的新方案(php异步mysql)
- Linux切换PHP版本:快速而安全的方法(linux切换php版本)
- Linux新建PHP文件的操作指南(linux新建php文件)
- Linux下打开PHP文件的实用技巧(linux打开php文件)
- 初探Linux中的PHP文件之旅(linux创建php文件)
- PHP和MySQL联动教程:如何取值?(phpmysql取值)
- PHP配置指南:MySQL编码设置详解(php设置mysql编码)
- 检测PHP对MSSQL数据库操作的能力(检测php_mssql)
- Linux平台如何高效搜索PHP文件(linux搜索php)
- PHP脚本管理MSSQL数据库:优化时间精度(php mssql 时间)
- PHP如何实现与MSSQL的连接(要php链接mssql)
- PHP实现稳定支持Redis的精彩瞬间(让php支持redis)
- php数据库连接
- 修改php.ini实现Mysql导入数据库文件最大限制的修改方法
- php无限分类的树类代码
- PHP和Mysqlweb应用开发核心技术第1部分Php基础-1开始了解php
- PHP中strtotime函数使用方法详解
- php读取文件内容的几种方法详解
- PHP二维数组排序的3种方法和自定义函数分享
- 自己写了一个php检测文件编码的函数
- 配置php.ini实现PHP文件上传功能
- php批量添加数据与批量更新数据的实现方法
- php实现的zip文件内容比较类