用PHP处理中文PDF

Posted on 十二月 20th, 2008 in Program | No Comments »

因项目需要,现在想在服务器端动态生成PDF文件,已一个PDF为模板,然后把所需的数据动态填入。
本来在使用zend framework,因此很直接的就使用zend_pdf类来进行测试,代码实现如下:

$pdf = Zend_Pdf::load($this->view->config->offline->template);
$pdf->pages = array_reverse($pdf->pages);
$style = new Zend_Pdf_Style();
$font = Zend_Pdf_Font::fontWithPath($this->view->config->offline->font, ( Zend_Pdf_Font::EMBED_DONT_SUBSET));
$pdf->pages[0]->setFont($font, 10);
$pdf->pages[0]->saveGS();
//datalist
$pdf->pages[0]->drawText(str_replace(";","\n",$datalist), 100, 570,"UTF-8");
//project
$pdf->pages[0]->drawText($formData['project'], 100, 430,"UTF-8");
$pdf->pages[0]->drawText($formData['realname'], 100, 78,"UTF-8");
$pdf->pages[0]->drawText($formData['realname'], 130, 590,"UTF-8");
$pdf->pages[0]->drawText($formData['unit'], 95, 58,"UTF-8");
$pdf->pages[0]->drawText($formData['address'], 285, 58,"UTF-8");
$pdf->pages[0]->drawText($formData['postcode'], 470, 58,"UTF-8");
$pdf->pages[0]->drawText($formData['email'], 95, 40,"UTF-8");
$pdf->pages[0]->drawText($formData['phone'], 295, 40,"UTF-8");
$t=getdate();
$pdf->pages[0]->drawText($t['year'], 465, 40,"UTF-8");
$pdf->pages[0]->drawText($t['mon'], 500, 40,"UTF-8");
$pdf->pages[0]->drawText($t['mday'], 525, 40,"UTF-8");
$pdf->pages[0]->restoreGS();
$fn=$formData['realname'].date('YmdHis').".pdf";
$pdf->save($this->view->config->offline->savepath."/".$fn);

这样,的确能完成要求,但是令人恼火的是,其把中文字体内嵌到PDF文件中去,因此导致PDF文件过大,而且导致PHP所需内存也增大(64M)。
因此,就开始尝试别的办法,开始锁定fpdf,PHP能完美支持,而且也能支持中文(所要单独下载chinese.php和chinese-unicode.php)。
但是,FPDF不支持打开已有的PDF文件作为模板,因此还需要使用fpdi进行模板的支持,还要修改fpdi,使其父类为PDF-UNICODE。

然后就可以这样使用:

$pagecount = $this->setSourceFile($this->template);
$tplidx = $this->importPage(1, '/MediaBox');
$this->addPage();
$this->useTemplate($tplidx);
$this->AddUniGBhwFont('ugb','AdobeSongStd-Light-Acro');

$this->SetFont('ugb','',$this->fontsize);
$this->setXY(45,65);
$this->Write($this->fontsize,$this->data['realname']);

其中,字形由默认的AdobeSongStd-Light改成AdobeSongStd-Light-Acro,是为了防止英文字体变宽和变窄,格式才会整齐,英文字不会挤在一起。(参考: http://bbs.erp100.com/thread-18424-1-1.html)

ubuntu hardy下使用zend framework

Posted on 七月 22nd, 2008 in Linux | No Comments »

安装:

sudo aptitude install zend-framework

补充操作:
1 添加Zend符号连接
sudo ln -s /usr/share/php/libzend-framework-php/Zend /usr/share/php/Zend
2 修补中文EMAIL的subject乱码
参考http://framework.zend.com/issues/browse/ZF-2532

use bcspamblock in zend form

Posted on 七月 2nd, 2008 in Computer | No Comments »

I want to integrate the bcspamblock and zend form, so first to do:
为了能自动防止机器人攻击,打算把bcspamblock整合到zend_form中。
1 创建element_bcSpamBlock.php文件,

<?php
class element_bcSpamBlock extends Zend_Form_Element_Xhtml{
/**
* Default form view helper to use for rendering
* @var string
*/
public $helper = 'bcSpamBlock';
}

2 创建helper文件:BcSpamBlock.php

<?php
include_once("bcspamblock.php");
class Zend_View_Helper_BcSpamBlock extends Zend_View_Helper_FormElement{

public function bcSpamBlock($name, $value='', $attribs = null){

$xhtml = bcspamblock_generate(true);
return $xhtml;
}
}

3 创建validator,但奇怪的是,这一步经测试,没发生实际作用,不知道是什么原因。

<?php
include_once("bcspamblock.php");
class Validator_SpamBlock extends Zend_Validate_Abstract {
const NOT_MATCH = '机器人阻止';//'spam blocked!';

protected $_messageTemplates = array(
self::NOT_MATCH => '机器人阻止'
);

public function isValid($value) {
$result=bcspamblock_verify();
return $result;
}
}

4 创建自定义的form

<?php

class ContactForm extends Zend_Form
{
public function __construct($options = null)
{
parent::__construct($options);
$this->setName('Contact');

$username = new Zend_Form_Element_Text('username');
$username->setLabel('用户名')->setRequired(true)
->addFilter('StripTags') ->addFilter('StringTrim')
->addValidator('StringLength',false,array(3,50));

$email=new Zend_Form_Element_Text('email');
$email->setLabel('E-Mail')
->setRequired(true)
->addFilter('StringTrim')
->addValidator('NotEmpty')
->addValidator('EmailAddress');

$subject=new Zend_Form_Element_Text('subject');
$subject->setLabel('主题')->setRequired(true);

$body=new Zend_Form_Element_Textarea('body');
$body->setLabel('内容')->setRequired(true)->setAttrib('rows',4);

$id = new Zend_Form_Element_Hidden('id');

$submit = new Zend_Form_Element_Submit('submit');
$submit->setAttrib('id', 'submitbutton')->setLabel('发送');

$spam=new element_bcSpamBlock('spam');
$spam->addPrefixPath('Validator','validator/','validate')
->addValidator('SpamBlock');

$this->addElements(array($id, $spam,$username,$email,$subject,$body,$submit));
}
}

5 在action中调用此form

function contactAction()
{
$form=new ContactForm();
$this->view->form=$form;
$this->view->addHelperPath('helper','Zend_View_Helper_');
if ($this->_request->isPost()) {
//发送邮件
$formData=$this->_request->getPost();
include_once("bcspamblock.php");
if (bcspamblock_verify() && $form->isValid($formData)) {
$mail=new Zend_Mail('utf-8');
....

因为第3步中的validator自动调用不成功,因此在此进行了手工的判断。

PHP的Framework

Posted on 十二月 11th, 2006 in Program | No Comments »

很长时间没有关注PHP,今天无意中点到javaeye.com,发现其已经改版,使用了ruby on rails框架技术,做得很好,然后又看到了还有php相关的框架,最近最近一段时间在PHP的世界里也出现了很多框架。作为php的发行公司,Zend自己也推出了一个框架,简称为ZF,目前最新的稳定版本还是0.2。觉得php的动作有点慢了,应该在php5推出后,要是能紧跟就推出几个框架系统,那对于php世界应该有非常大的推动!不过,虽然动作慢了一些,但是已经有了很多的php框架发展起来了。粗粗阅读了zf的文档后,发现框架的功能还是蛮丰富的,但是ZF目前还是有相当多的进步空间的,就是说,目前还是有一些缺点的。

一些framework的比较:

http://www.mustap.com/phpzone_post_73_top-10-php-mvc-frameworks

http://www.phpit.net/article/ten-different-php-frameworks/

http://www.5itag.com/viewtopic.php/177

seagull感觉像是一个大的CMS系统
ZF感觉像是一个库,或者就是pear
最后看了symfony的manual,感觉symfony相当好,不过也有缺陷,就是配置太麻烦了。
在symfony中,用Propel实现了OR映射,支持多种数据库,包括mysql,sqlserver,pgsql,sqlite,oracle。
感觉这套框架和zend framework有很大不同,对我来说,symfony要好于zf。
还支持schema, or map, paging, multitype databases, ...

Conclusion: 首选symfony,其次cakephp,最后再考虑zf。当然还可以考虑seagull。