本篇博客是在看完 php+mysql web书以后自己的测试代码,虽然是测试代码,但不是简单的粘贴复制,为了学习thinkPHP框架,自己就用这个来做的,而且这本书已经有年头了。原书的代码中的方法,在查阅手册的时候,很多都已经弃用了,所以分享给大家还是有必要的。php制作pdf文档的方法有很多,我写的只是其中一种,大家有时间可以多看看。好了,进入正题
准备工作:
1、php手册(在线php关于pdf地址: http://php.net/manual/zh/intro.pdf.php )
2、PDFlib(http://www.pdflib.com/download/pdflib-family/pdflib-9/ 下载)
开始安装PDFlib扩展
第一步,下载最新的pdflib扩展,
我下载下来后里面有很多东西
我的php版本是PHP Version 5.2.17所以我选的是php_520里面的文件,将里面的文件名称改成libpdf_php.dll =》php_pdf.dll
第二步安装
将php_pdf.dll文件放到php的ext目录
打开php.ini文件将里面extension=php_pdf.dll去掉分号(如果没有,就添加上这一行),如果没有找到添加即可。
第三步重启apache或IIS
建立项目pdfApp
这里我为了学习thinkPHP,所以使用的是thinkPHP框架,我们的目标是根据用户的答题情况->作出成绩判断->生成用户的pdf成绩证书
由于项目比较小,我们简单使用一个控制器就可以完成,代码就不分开贴了,最下面有完整的IndexController代码
首先,进入index方法显示信息搜集页面(就是controller中的index方法)
进入根据选择跳转到score方法
生成PDF证书
下面的一页就是代码中测试制作第二页的输出
怎么会有这么大的水印啊,影响美观。请不要相信那个大大的水印是我加的
由于PDFlib并不是开源免费的,所以、、、、、
完整代码:
需要注意的是:
PDFlib的使用也是有两种:面向对象和面向过程
区别是:对于手册中的所有方法都是面向过程的方法,在使用面向对象时,只需要把前面的前缀\'PDF_\'用对象调用替换即可,
同时忽略方法中的\'resource $pdfdoc\' 参数
1 <?php 2 namespace Home\Controller; 3 use Think\Controller; 4 class IndexController extends Controller { 5 public function index(){ 6 $this->display(); 7 } 8 public function score() { 9 $name = I(\'post.name\'); 10 $question_1 = I(\'post.q1\'); 11 $question_2 = I(\'post.q2\'); 12 $question_3 = I(\'post.q3\'); 13 14 if ( (\'\' == $question_1) || (\'\' == $question_2) || (\'\' == $question_3) || (\'\' == $name)) { 15 # code... 16 $err_url = U(\'Index/index\'); 17 $this->assign(\'url\',$err_url); 18 $this->display(\'nullError\'); 19 }else { 20 $score = 0; 21 1 == $question_1 && $score++; 22 1 == $question_2 && $score++; 23 1 == $question_3 && $score++; 24 25 //convert score to a percentage 26 $score = $score / 3 * 100; 27 28 if($score < 50) { 29 // this person failed 30 $this->display(\'notPass\'); 31 32 } else { 33 // create a string containing the score to one decimal place 34 $score = number_format($score, 1); 35 $this->assign(\'name\',$name); 36 $this->assign(\'score\',$score); 37 $this->display(\'isPass\'); 38 } 39 } 40 } 41 public function pdflib() { 42 $name = I(\'post.name\'); 43 $score = I(\'post.score\'); 44 if(!$name || !$score) { 45 echo \'name and score is null\'; 46 }else { 47 // 开始制作pdf文档 48 // 注意:PDFlib的使用也是有两种:面向对象和面向过程 49 // 区别是:对于手册中的所有方法都是面向过程的方法,在使用面向对象时,只需要把前面的前缀\'PDF_\'用对象调用替换即可, 50 // 同时忽略方法中的\'resource $pdfdoc\' 参数 51 // 例如我们可以创建一个pdf对象 $pdf = new \PDFlib(); 52 // 也可以使用 $pdf = pdf_new();创建一个pdf资源句柄 53 try { 54 $date = date(\'F d, Y\'); // 获取系统当前时间 55 // 实例化一个PDFlib对象,注意我们的PDFlib由于是在php的扩展库中,所以这里记得前面加上\'\\',thinkPHP此时就回去全区命名空间下 56 // 查找这个类问价 57 $pdf = new \PDFlib(); 58 // PDF_begin_document() 这个方法在内存中创建一个pdf文档 59 if(false == $pdf->begin_document(\'\',\'\')) { 60 die(\'Error: \'.$pdf->get_errmsg()); 61 } 62 63 $width = 792; 64 $height = 612; 65 // 向文档中添加新的页面 66 $pdf->begin_page_ext($width,$height,\'\'); 67 68 // 开始定义并画出边框(pdf中的长度和位置的单位均是:像素) 69 $inset = 20; // 边框和页面边缘的距离 70 $border = 10; // 边框宽度 71 $inner = 2; // 边框和两条边线的距离 72 // PDF_rect 方法是画出一个矩形,注意坐标原点是 左下角 73 $pdf->rect($inset-$inner,$inset-$inner,$width-2*($inset-$inner),$height-2*($inset-$inner)); 74 $pdf->stroke(); // PDF_stroke 描绘用当前颜色和路径宽度描绘出路径 75 76 $pdf->setlinewidth($border); // PDF_setlinewidth 设置线条宽度 77 $pdf->rect($inset+$border/2, 78 $inset+$border/2, 79 $width-2*($inset+$border/2), 80 $height-2*($inset+$border/2)); 81 $pdf->stroke(); 82 83 $pdf->setlinewidth(1.0); 84 $pdf->rect($inset+$border+$inner, 85 $inset+$border+$inner, 86 $width-2*($inset+$border+$inner), 87 $height-2*($inset+$border+$inner) 88 ); 89 $pdf->stroke(); 90 // 添加标题 91 $fontname = \'Times-Roman\'; 92 // PDF_load_font 方法是:搜索和准备字体 93 $font = $pdf->load_font($fontname,\'winansi\',\'\'); 94 $pdf->setcolor(\'fill\', \'rgb\', 1, 0, 0, 0); // PDF_setcolor 设置 填充颜色和描绘路径颜色 95 $pdf->setfont($font,20); 96 $pdf->show_xy($date,50,490); // PDF_show_xy 在给的的位置输出文本内容 97 $pdf->setcolor(\'fill\', \'rgb\', 0, 0, 0, 0); // red 98 $pdf->setfont($font,48); 99 $start_x = ($width-$pdf->stringwidth(\'PHP Certification\',$font,\'12\'))/2; 100 $pdf->show_xy(\'PHP Certification\',$start_x,490); 101 102 // 添加内容 103 $font = $pdf->load_font($fontname,\'iso8859-1\',\'\'); 104 $pdf->setfont($font,26); 105 $start_x = 70; 106 $pdf->show_xy(\'This is to certify that:\',$start_x,430); 107 $pdf->show_xy(strtoupper($name),$start_x+90,391); 108 109 $font = $pdf->load_font($fontname,\'iso8859-1\',\'\'); 110 $pdf->setfont($font,20); 111 $pdf->show_xy(\'has demonstrated that they are certifiable by passing a rigorous exam\', $start_x, 340); 112 $pdf->show_xy(\'consisting of three multiple choice questions.\',$start_x, 310); 113 114 $pdf->show_xy("$name obtained a score of $score".\'%.\', $start_x, 260); 115 116 $pdf->show_xy(\'The test was set and overseen by the \', $start_x, 210); 117 $pdf->show_xy(\'Fictional Institute of PHP Certification\', $start_x, 180); 118 $pdf->show_xy("on $date.", $start_x, 150); 119 $pdf->show_xy(\'Authorised by:\', $start_x, 100); 120 121 // 添加签名 122 // PDF_load_image 打开图像文件 123 $signature = $pdf->load_image(\'png\',WEB_ROOT."/Public/images/signature.png",\'\'); 124 $pdf->fit_image($signature,200, 75, \'\'); // PDF_fit_image 将图片放到指定位置 125 $pdf->close_image($signature); // 关闭文件 126 127 // 开始画出星型图章 128 $pdf->setcolor(\'fill\', \'rgb\', 0, 0, .4, 0); // 设置PDF_fill方法用的颜色 129 $pdf->setcolor(\'stroke\', \'rgb\', 0, 0, 0, 0); // 设置PDF_stroke方法用的颜色 130 // 画出左侧飘带 131 $pdf->moveto(630, 150); // PDF_moveto 将画图点移动到指定位置 132 $pdf->lineto(610, 55); // PDF_lineto 从当前点画出一条线到指定位置 133 $pdf->lineto(632, 69); 134 $pdf->lineto(646, 49); 135 $pdf->lineto(666, 150); 136 $pdf->closepath(); // PDF_closepath 关闭当前路径 137 $pdf->fill(); // PDF_fill 用指定颜色填充到路径内 138 139 // outline ribbon 1 140 $pdf->moveto(630, 150); 141 $pdf->lineto(610, 55); 142 $pdf->lineto(632, 69); 143 $pdf->lineto(646, 49); 144 $pdf->lineto(666, 150); 145 $pdf->closepath(); 146 $pdf->stroke(); 147 148 // draw ribbon 2 149 $pdf->moveto(660, 150); 150 $pdf->lineto(680, 49); 151 $pdf->lineto(695, 69); 152 $pdf->lineto(716, 55); 153 $pdf->lineto(696, 150); 154 $pdf->closepath(); 155 $pdf->fill(); 156 157 // -> outline ribbon 2 158 $pdf->moveto(660, 150); 159 $pdf->lineto(680, 49); 160 $pdf->lineto(695, 69); 161 $pdf->lineto(716, 55); 162 $pdf->lineto(696, 150); 163 $pdf->closepath(); 164 $pdf->stroke(); 165 166 167 $pdf->setcolor(\'fill\', \'rgb\', 1, 0, 0, 0); // red 168 169 //调用自定义方法,画出图章礼花 170 $this->draw_star(665, 175, 32, 57, 10, $pdf, true); 171 172 //outline rosette 173 $this->draw_star(665, 175, 32, 57, 10, $pdf, false); 174 175 // PDF_end_page 结束当前页 176 177 // 这里如果需要继续制作第二页,第三页。。。。 178 $pdf->end_page_ext(""); 179 180 $pdf->set_info("Creator", "hello.php"); 181 $pdf->set_info("Author", "Rainer Schaaf"); 182 $pdf->set_info("Title", "Hello world (PHP)!"); 183 184 $pdf->begin_page_ext(595, 842, ""); 185 186 $font = $pdf->load_font("Helvetica-Bold", "winansi", ""); 187 188 $pdf->setfont($font, 24.0); 189 $pdf->set_text_pos(50, 700); 190 $pdf->show("Hello world!"); 191 $pdf->continue_text("(says PHP)"); 192 $pdf->end_page_ext(""); 193 // 第二页结束,看明白了吗? 194 195 // PDF_end_document 结束文档 196 $pdf->end_document(""); 197 // PDF_get_buffer 得到PDF输出缓存 198 $data = $pdf->get_buffer(); 199 200 // 设置浏览器头信息 201 header(\'Content-type: application/pdf\'); 202 header(\'Content-disposition: inline; filename=test.pdf\'); 203 header(\'Content-length: \' . strlen($data)); 204 205 // 输出PDF 206 echo $data; 207 } 208 catch (PDFlibException $e) { 209 die("PDFlib exception occurred in hello sample:\n" . 210 "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " . 211 $e->get_errmsg() . "\n"); 212 } 213 catch (Exception $e) { 214 die($e); 215 } 216 217 } 218 } 219 // 画礼花图章方法 220 // 具体算法自行理解,所用方法上面都有所说明, 221 function draw_star($centerx, $centery, $points, $radius, $point_size, $pdf, $filled) { 222 $inner_radius = $radius-$point_size; 223 224 for ($i = 0; $i<=$points*2; $i++) { 225 $angle= ($i*2*pi())/($points*2); 226 227 if($i%2) { 228 $x = $radius*cos($angle) + $centerx; 229 $y = $radius*sin($angle) + $centery; 230 } else { 231 $x = $inner_radius*cos($angle) + $centerx; 232 $y = $inner_radius*sin($angle) + $centery; 233 } 234 235 if($i==0) { 236 $pdf->moveto($x, $y); 237 } else if ($i==$points*2) { 238 $pdf->closepath(); 239 } else { 240 $pdf->lineto($x, $y); 241 } 242 } 243 if($filled) { 244 $pdf->fill_stroke(); 245 } else { 246 $pdf->stroke(); 247 } 248 } 249 250 public function pdf() { 251 try { 252 $p = new \PDFlib(); 253 254 /* open new PDF file; insert a file name to create the PDF on disk */ 255 if ($p->begin_document("", "") == 0) { 256 die("Error: " . $p->get_errmsg()); 257 } 258 259 $p->set_info("Creator", "hello.php"); 260 $p->set_info("Author", "Rainer Schaaf"); 261 $p->set_info("Title", "Hello world (PHP)!"); 262 263 $p->begin_page_ext(595, 842, ""); 264 265 $font = $p->load_font("Helvetica-Bold", "winansi", ""); 266 267 $p->setfont($font, 24.0); 268 $p->set_text_pos(50, 700); 269 $p->show("Hello world!"); 270 $p->continue_text("(says PHP)"); 271 $p->end_page_ext(""); 272 273 $p->end_document(""); 274 275 $buf = $p->get_buffer(); 276 $len = strlen($buf); 277 278 header("Content-type: application/pdf"); 279 header("Content-Length: $len"); 280 header("Content-Disposition: inline; filename=hello.pdf"); 281 print $buf; 282 $p->open_file(\'1.pdf\'); 283 } 284 catch (PDFlibException $e) { 285 die("PDFlib exception occurred in hello sample:\n" . 286 "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " . 287 $e->get_errmsg() . "\n"); 288 } 289 catch (Exception $e) { 290 die($e); 291 } 292 $p = 0; 293 } 294 }
代码中用到的方法:
PDF_begin_document() 这个方法在内存中创建一个pdf文档
PDF_begin_page_ext() 向文档中添加新的页面
PDF_rect 方法是画出一个矩形,注意坐标原点是 左下角
PDF_stroke 描绘用当前颜色和路径宽度描绘出路径
PDF_setlinewidth 设置线条宽度
PDF_load_font 搜索和准备字体.
PDF_setcolor 设置 填充颜色和描绘路径颜色
PDF_show_xy 在给的的位置输出文本内容
PDF_load_image 打开图像文件
PDF_fit_image 将图片放到指定位置
PDF_close_image 关闭文件
PDF_moveto 将画图点移动到指定位置
PDF_lineto 从当前点画出一条线到指定位置
PDF_closepath 关闭当前路径
PDF_fill 用指定颜色填充到路径内
PDF_end_document 结束文档
PDF_get_buffer 得到PDF输出缓存
好了,方法有很多,常用的也就是这么多,如果有兴趣,愿意的话可以去看看php手册:http://php.net/manual/zh/ref.pdf.php
以上就是今天一天的学习成果,哎时间真快,都天黑了,完了,吃饭走。
欢迎大家转载,收藏,吐槽,哈哈、、、、