Archive for the 'PHP' Category

用 Smarty 实现多语言网站

2007-4-12 22:03 | by 2ndboy

  用 PHP 实现多语言的正途似乎是 gettext 函数族,但是用 gettext 也有很多不方便的地方,今天实现了一种利用 Smarty 来实现多语言 B/S 应用的方法。最后希望达到的效果是程序中除了切换语言的地方,其它地方能够完全不用关心当前的显示语言,比如同样的 $Tmpl->display( ‘welcome.tpl’ ) 在中文状态下会显示中文的欢迎页面,而在英文状态下就显示英文欢迎页面。

  既然对 Smarty 对象的调用方式在不同语言下保持一致,那么就要拿 Smarty 类来开刀啦。Smarty 里面把模版“实例化”的接口有两个,一个是 display(),另外一个是 fetch(),而 display() 内部其实调用了 fetch(),所以关键点就在于改造这里。从 Smarty 派生一个新类 CSmarty,重载其中的 fetch() 和 display() 接口:

  1.  class CSmarty extends Smarty
  2.  {
  3.      function CSmarty()
  4.      {
  5.          $this->Smarty();
  6.      }
  7.      function set_dirs( $lang )
  8.      {
  9.          $base_path = '2ndboy/';
  10.          $this->template_dir = $base_path . $lang . '/templates/';
  11.          $this->compile_dir  = $base_path . $lang . '/templates_c/';
  12.          $this->config_dir   = $base_path . $lang . '/configs/';
  13.          $this->cache_dir    = $base_path . $lang . '/cache/';
  14.      }
  15.      function fetch( $template, $cache_id = null, $compile_id = null, $display = false )
  16.      {
  17.          $this->set_dirs( $_SESSION['lang'] );
  18.          if( !$this->template_exists( $template ) )
  19.              $this->set_dirs( 'en' )// Default language is English
  20.  
  21.          return( parent::fetch( $template, $cache_id, $compile_id, $display ) );
  22.      }
  23.      function display( $template, $cache_id = null, $compile_id = null )
  24.      {
  25.          $this->fetch( $template, $cache_id, $compile_id, true );
  26.      }
  27.  }
  28.  ?>

  可以看出,上述代码把当前的显示语言设置放在 session 里面,所以还要有针对语言切换操作设置 session 的响应代码:

  1.  if( isset( $_REQUEST['lang'] ) )
  2.  {
  3.      if( 0 == strcasecmp( 'cn', $_REQUEST['lang'] ) )
  4.          $_SESSION['lang'] = 'cn';
  5.      else
  6.          $_SESSION['lang'] = 'en';
  7.  
  8.      header( 'Location: ' . $_SERVER['HTTP_REFERER'] );
  9.      exit;
  10.  }
  11.  ?>

假设上述代码放在 index.php 里面,那么用 index.php?lang=en 就可以实现把当前语言切换成英文的操作,注意代码里设置完显示语言后会跳转到 referer 所指的页面,这样处理可以实现切换语言后所在位置不变的效果。

  以上的代码实现要求模版路径下的目录结构这样布局:第一级目录采用语言名,如 cn,en 等,各个语言目录内部再按 Smarty 的惯例分成 templates、templates_c、cache 等等。

  下面再发挥一下想象力,让程序自动识别用户熟悉的语言,比如老外访问看到的是英文内容,国人访问看到的是中文内容:

  1.  session_start();
  2.  if( !isset( $_SESSION['lang'] ) )
  3.  {
  4.      if( strstr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 'zh' ) )
  5.          $_SESSION['lang'] = 'cn';
  6.      else
  7.          $_SESSION['lang'] = 'en';
  8.  }
  9.  ?>

其实就是通过分析客户端浏览器可接受的语言来设定默认显示的语言:)

  呵呵,其实两年多以前就实现过这个功能,今天是旧瓶装新酒,把之前的实现加以改进放上来晒晒,不知各位看官有收获没?:D

如何在 BlueHost 空间中用 PHP 以 SMTP 方式发送邮件

2006-12-17 22:55 | by 2ndboy

  用 PHP 发邮件的方法很多,但自从我体会到了 PEAR 的威力之后就喜欢上 Mail 类。你可以用 mail,sendmail 和 smtp 三种方式来借助 Mail 类发送邮件。话说几天前刚买了个 BlueHost 的空间,在上面跑程序的时候用 PHP 发邮件搞出点心得来,放在这里跟大家分享。

  首先我在系统中添加了一个邮件账户 test,密码 123456,然后写下了如下代码:

  1.  require_once( 'Mail.php' );
  2.  $conf = array(
  3.   'host'     => 'mail.yourdomail.com',
  4.   'auth'     => true,
  5.   'username' => 'test',
  6.   'password' => '123456'
  7.  );
  8.  $headers['From']         = 'noreply@yourdomain.com';
  9.  $headers['To']           = $To;
  10.  $headers['Subject']      = '=?GB2312?B?' . base64_encode( $Subject ) . '?=';
  11.  $headers['Content-Type'] = 'text/plain; charset=gb2312';
  12.  $Mail = & Mail::factory( 'smtp', $conf );
  13.  $res = $Mail->send( $To, $headers, $Content );
  14.  ?>

  $To 是想要发送到的信箱地址,比如 foobar@gmail.com,$Subject 是邮件主题,$Content 是 GB2312 编码的邮件正文。结果用以上程序屡试屡败,后来经过多次试验才得出在 BlueHost 主机上用 PHP 以 SMTP 方式发送邮件的正确方法,注意事项如下:
1) BlueHost 帮助信息中说跟你账户(域名)相对应的 SMTP 主机地址是 mail.yourdomain.com,但其实应该是 localhost。你用 mail.yourdomain.com 只会得到 SMTP 拒绝链接的错误信息。
2) SMTP 服务器需要验证才能发邮件。
3) SMTP 验证时用户名需要写 user+yourdomain.com,不能写 user@yourdomain.com。想想这个也好理解,在虚拟主机上一个 SMTP server 要支撑很多个账户,这种写法应该是为了区别发件的账户。
4) 邮件头中的发件邮件账户一定要是存在于系统中的真实账户,象我上面那样注册了一个 test@yourdomain.com,但是发件人账户又写 noreply@yourdomain.com 是不行的,只会得到这样的错误信息:
SMTP: Invalid response code received from server (code: 550, response: Verification failed for No Such User Here Sender verify failed)

  知道了上面这 4 个注意事项以后就好办了,删掉刚才注册的 test 邮件帐号,注册一个 noreply 帐号,修改程序如下:

  1.  require_once( 'Mail.php' );
  2.  $conf = array(
  3.   'host'     => 'localhost',
  4.   'auth'     => true,
  5.   'username' => 'noreply+yourdomain.com',
  6.   'password' => '123456'
  7.  );
  8.  $headers['From']         = 'noreply@yourdomain.com';
  9.  $headers['To']           = $To;
  10.  $headers['Subject']      = '=?GB2312?B?' . base64_encode( $Subject ) . '?=';
  11.  $headers['Content-Type'] = 'text/plain; charset=gb2312';
  12.  $Mail = & Mail::factory( 'smtp', $conf );
  13.  $res = $Mail->send( $To, $headers, $Content );
  14.  ?>

  邮件被成功的发送出去了,而且由于邮件服务器在美国,发送到 GMail 信箱非常之快,一般这边一发那边刷新一下就能看到新邮件:)

  这里再说些题外话,买了 BlueHost 的空间将近一周时间了,感觉美国的虚拟主机市场确实非常成熟,功能强大。跟国内价格还行但是配置超受限的主机比起来性价比高的不得了!只要你选对了服务提供商,可以说绝对让你满意。但是缺点也比较明显,就是速度实在是慢!这里面的原因众所周知,感谢伟大的电信运营商,感谢伟大的 GFW!

  今天跟 HostMonster 的客户沟通了一下,问问他们那边从中国过去的访问速度怎么样,估计人家遇到这样的情况不是个别现象,上来就是一句,我们对来自中国的访问速度无法做出承诺。

  国内的虚拟主机服务商有万网这样把大家当 SB 漫天要价的主,但是也有兢兢业业踏踏实实做服务的公司,不过性价比跟国外的运营商确实没法比。一边是价格高不了多少,动辄几十 G 空间几百 G 月流量,支持 SSH,支持多 Addon domain 的国外主机,一边是价廉物不太美的国内主机,我想诱惑力是不言而喻的。但是速度,唉,伤心是一种说不出的痛!

  价廉物美,速度又快的好主机,你在哪里???

PHP 5.2.0 来了!

2006-11-3 13:14 | by 2ndboy

  今天看到新闻——PHP 5.2.0 已经发布了,到官方网站上看了看,似乎有不少不错的新特性(http://www.php.net/releases/5_2_0.php)!

Input filtering extension was added and enabled by default
这个扩展不错,数据库注入是 Web 开发永远不能避开的问题,现在官方已经有了这样的解决方案,我们自己可以省掉一部分工作了:)

JSON extension was added and enabled by default
JSON 就是 JavaScript Object Notation,看似是一个 JavaScript 数据/对象的 serialization 规范,还有专门的 rfc(http://www.ietf.org/rfc/rfc4627.txt?number=4627)。从来没用过,知道其中妙处的朋友不妨指教一二。这个扩展似乎在 SourceForge 上有自己的项目站点:http://sourceforge.net/projects/php-json

ZIP extension for creating and editing zip files was introduced
这个扩展比较实在,以后你就可以在 PHP 脚本中方便的操纵 zip 文件了!

Hooks for tracking file upload progress were introduced
在 PHP 里面跟踪文件上传的进度在以前来说是根本不可能的,文件上传之后你只能从解析器那里拿到临时文件和上传结果,中间的一切步骤都不能插手。如果你要用 PHP 来做文件或者照片共享程序,那么用户上传文件的时候将得不到任何进度指示,现在好了,有时间要试试这个新特性。这里有个额外的参考:http://blog.bitflux.ch/archive/2006/09/28/upload-progress-meter-extension-for-php-5-2.html

  另外这个版本还修复了超过 200 个 bug,性能也得到了一些提升,一些组件的 client library 也更新了版本。总体来说是个值得升级和尝试一下的版本!

把 dotProject 1.0.2 搬到 PHP 5 下了

2005-1-30 16:12 | by 2ndboy

  差不多一年前研究了一下 dotProject 这个项目管理/多人协作项目,还翻译了一个简体中文版语言包出来,最近刚好有用得着它的地方就安装好用起来了,幸好当时有笔记所以过程还比较顺利,但经过测试 dotProject 1.0.2 在 PHP 5 下运行还是有问题的。解决方法如下:

/classes/dp.class.php:98
function clone() => function MyClone()

/modules/tasks/tasks.class.php:165
newObj = this->clone(); => newObj = this->MyClone();

/classes/ui.class.php:647
function CTabBox() => function CTabBox_core()

  基本上都跟 PHP 5 的对象模型/用法有关,看来大量现存应用要想从 PHP 4 迁移到 PHP 5 还是存在诸多问题的。

偶识 PHP 5 SOAP

2004-6-19 23:58 | by 2ndboy

  最近由于工作需要,要用 PHP 实现一个 Web Services。在网上搜了一圈后找到了 NUSOAP 这个东西,今晚有时间于是写代码测试一下,谁知下载的最新版 NUSOAP 在我们的 PHP 5 下面一直报 soapclient 有错,百思不得其解。排除了其它可能性之后想到——难道跟 PHP 内建的函数/类名冲突?翻出文档一查,果然!

  原来 PHP 5 已经内建了对 SOAP 的支持,这倒是勾起了我的兴趣,于是马上扔下 NUSOAP 开始研究起 PHP 5 自带的 SOAP 扩展来,下面是我查了查文档写的两个小测试程序:

Web Services 服务端(soap_server.php):

  1. <?php
  2.  function DemoEcho( $String )
  3.  {
  4.      return( strrev( $String ) );
  5.  }
  6.  
  7.  $pServer = new SoapServer( NULL, array( "uri" => "http://localhost/" ) );
  8.  
  9.  $pServer->addFunction( "DemoEcho" );
  10.  
  11.  $pServer->handle();
  12.  ?>

调用此 Web Services 的客户端(soap_client.php):

  1. <?php
  2.  $soap = new SoapClient( null, array( "location" => "http://localhost/soap_server.php", "uri" => "http://localhost/" ) );
  3.  
  4.  echo $soap->__call( "DemoEcho", array( "Hello, SOAP!" ) );
  5.  
  6.  ?>

抱着试试的态度在浏览器里输入了 localhost/soap_client.php,回车。哗!居然显示出了“!PAOS ,olleH”的结果!

这可是我第一次写 Web Services 啊!呵呵,脚本语言就是强!