• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Php More
 

Php More

on

  • 599 views

 

Statistics

Views

Total Views
599
Views on SlideShare
599
Embed Views
0

Actions

Likes
0
Downloads
2
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Php More Php More Document Transcript

    • PHPMORE VOL 5 本期目录 新闻 2 PHP5 面向对象程序设计之:THIS , SELF 和 PARENT 3 PHP5 面向对象程序设计之: STATIC 和 CONST 7 PEAR 探奇系列之 PEAR::TEXT_PASSWORD 9 PEAR::PEAR 的析构器模拟 16 SMARTY 中 SECTION 的简单使用 18 XMLHTTP 试用手记 23 推荐图书 26 Editors: Avenger Binzy Cozo Easy Freeman Happay KnightE RainX Shenkong Thanks to: . 感谢所有关心和支持 PHPMORE 的人,“感谢你们让我们梦想”。 PHPMORE VOL5
    • 新闻 Zend 和 IBM 合作推出 Zend Core for IBM PHP 5.0.4 and 4.3.11 Released PHPMORE.com 改版,推出中文 PHP Blog 聚合服务和 PHP 知识书签服务。欢迎大家到 club.phpe.net 的 PHPMORE 版推荐自己喜爱的 PHP Blog 信息源。 PHPe.net 的论坛已经完成了和 PHP 知识书签的整合,点击帖子中的 图标可以直接将帖子收藏到你的 PHP 知识书签中。 PHPMORE VOL5 2/26
    • PHP5 面向对象程序设计之:this , self 和 parent 文/ heiyeluren PHP5 是一具备了大部分面向对象语言的特性的语言,比 PHP4 有了很多的面向对象的特性,但是有部分概念也比较 绕人,所以今天拿出来说说,说的不好,请高手见谅. (阅读本文,需要了解 PHP5 的面向对象的知识) 首先我们来明白上面三个关键字: this,self,parent,从字面上比较好理解,是指这,自己,父亲,呵呵,比较好玩 了,我们先建立几个概念,这三个关键字分别是用在什么地方呢?我们初步解释一下,this 是指向当前对象的指针 (我们姑且用 C 里面的指针来看吧),self 是指向当前类的指针,parent 是指向父类的指针。我们这里频繁使用指 针来描述,是因为没有更好的语言来表达,呵呵,语文没学好。 -_-# 这么说还不能很了解,那我们就根据实际的例子结合来讲讲。 (1)this <? Code ?> 1 <?php 2 3 class UserName 4{ 5 //定义属性 6 private $name; 7 8 //定义构造函数 9 function __construct( $name ) 10 { 11 $this->name = $name; //这里已经使用了 this 指针 12 } 13 14 //析构函数 15 function __destruct(){} 16 17 //打印用户名成员函数 18 function printName() 19 { 20 print( $this->name ); //又使用了 this 指针 21 } 22 } 23 24 //实例化对象 25 $nameObject = new UserName( "heiyeluren" ); PHPMORE VOL5 3/26
    • 26 27 //执行打印 28 $nameObject->printName(); //输出: heiyeluren 29 30 //第二次实例化对象 31 $nameObject2 = new UserName( "PHP5" ); 32 33 //执行打印 34 $nameObject2->printName(); //输出:PHP5 35 ?> 我们看,上面的类分别在 11 行和 20 行使用了 this 指针,那么当时 this 是指向谁呢?其实 this 是在实例化的 时候来确定指向谁,比如第一次实例化对象的时候(25 行),那么当时 this 就是指向$nameObject 对象,那么执 行 18 行的打印的时候就把 print( $this-><name )变成了 print( $nameObject->name ),那么当然就输 出了"heiyeluren"。第二个实例的时候,print( $this->name )变成了 print( $nameObject2->name ), 于是就输出了"PHP5"。所以说,this 就是指向当前对象实例的指针,不指向任何其他对象或类。 (2)self 首先我们要明确一点,self 是指向类本身,也就是 self 是不指向任何已经实例化的对象,一般 self 使用来指向 类中的静态变量。 <? Code ?> 1 <?php 2 3 class Counter 4{ 5 //定义属性,包括一个静态变量 6 private static $firstCount = 0; 7 private $lastCount; 8 9 //构造函数 10 function __construct() 11 { 12 $this->lastCount = ++self::$firstCount; //使用 self 来调用静态变量,使 用 self 调用必须使用::(域运算符号) 13 } 14 15 //打印最次数值 16 function printLastCount() 17 { 18 print( $this->lastCount ); 19 } 20 } PHPMORE VOL5 4/26
    • 21 22 //实例化对象 23 $countObject = new Counter(); 24 25 $countObject->printLastCount(); //输出 1 26 27 ?> 我们这里只要注意两个地方,第 6 行和第 12 行。我们在第二行定义了一个静态变量$firstCount,并且初始值为 0,那么在 12 行的时候调用了这个值得,使用的是 self 来调用,并且中间使用"::"来连接,就是我们所谓的域运 算符,那么这时候我们调用的就是类自己定义的静态变量$frestCount,我们的静态变量与下面对象的实例无关, 它只是跟类有关,那么我调用类本身的的,那么我们就无法使用 this 来引用,可以使用 self 来引用,因为 self 是指向类本身,与任何对象实例无关。换句话说,假如我们的类里面静态的成员,我们也必须使用 self 来调用。 (3)parent 我们知道 parent 是指向父类的指针,一般我们使用 parent 来调用父类的构造函数。 <? Code ?> 1 <?php 2 3 //基类 4 class Animal 5{ 6 //基类的属性 7 public $name; //名字 8 9 //基类的构造函数 10 public function __construct( $name ) 11 { 12 $this->name = $name; 13 } 14 } 15 16 //派生类 17 class Person extends Animal //Person 类继承了 Animal 类 18 { 19 public $personSex; //性别 20 public $personAge; //年龄 21 22 //继承类的构造函数 23 function __construct( $personSex, $personAge ) 24 { 25 parent::__construct( "heiyeluren" ); //使用 parent 调用了父类的 构造函数 PHPMORE VOL5 5/26
    • 26 $this->personSex = $personSex; 27 $this->personAge = $personAge; 28 } 29 30 function printPerson() 31 { 32 print( $this->name. " is " .$this->personSex. ",this year " .$this->personAge ); 33 } 34 } 35 36 //实例化 Person 对象 37 $personObject = new Person( "male", "21"); 38 39 //执行打印 40 $personObject->printPerson(); //输出: 41 42 ?> 我们注意这么几个细节:成员属性都是 public 的,特别是父类的,是为了供继承类通过 this 来访问。我们注意 关键的地方,第 25 行:parent::__construct( "heiyeluren" ),这时候我们就使用 parent 来调用父类的 构造函数进行对父类的初始化,因为父类的成员都是 public 的,于是我们就能够在继承类中直接使用 this 来调 用。 总结: this 是指向对象实例的一个指针,self 是对类本身的一个引用,parent 是对父类的引用。 PHPMORE VOL5 6/26
    • PHP5 面向对象程序设计之: static 和 const 文/ heiyeluren PHP5 中加入了很多面向对象的思想,PHP5 的面向对象比较接近 Java 的面向对象思想。我们这里对 PHP5 中的 static 和 const 关键字作用进行一下描述,希望对学习 PHP5 的朋友有帮助。 (1) static static 关键字在类中是,描述一个成员是静态的,static 能够限制外部的访问,因为 static 后的成员是属于 类的,是不属于任何对象实例,其他类是无法访问的,只对类的实例共享,能一定程序对该成员尽心保护。类的静 态变量,非常类似全局变量,能够被所有类的实例共享,类的静态方法也是一样的,类似于全局函数。类的静态方 法能访问类的静态的属性。另外说明的是,static 的成员,必须使用 self 来访问,使用 this 会出错。 另外,还有一个比较重要的特点就是,如果一个方法使用了 static,那么这个方法就能够在不需要实例化对象的前 提下直接使用该方法. (关于 this 和 self 的异同,请参考: http://blog.csdn.net/heiyeshuwu/archive/2004/11/03/165828.aspx ) (2)const const 是一个定义常量的关键字,类似于 C 中的#define,能够定义一个常量,如果在程序中改变了它的值,那么 会出现错误。 举例说明上面的代码:(注:以下代码来自 phpe.net) <? Code ?> <?php class Counter { private static $count = 0;//定义一个静态属性 const VERSION = 2.0;//定义一个常量 //构造函数 function __construct() { self::$count++; } //析构函数 function __destruct() { self::$count--; PHPMORE VOL5 7/26
    • } //定义一个静态的方法 static function getCount() { return self::$count; } } //创建一个实例 $c = new Counter(); //执行打印 print( Counter::getCount(). "<br>n" ); //使用直接输入类名来访问静态方 法 Counter::getCount //打印类的版本 print( "Version useed: " .Counter::VERSION. "<br>n" ); ?> 嗯,基本到这里了,心里知道的那点东西就讲清楚了,不过我觉得自己对 static 还有点不理解,等以后慢慢去思 考。 作者信息: heiyeluren Email: heiyeluren@163.com Blog: http://blog.csdn.net/heiyeshuwu PHPMORE VOL5 8/26
    • PEAR 探奇系列之 PEAR::Text_Password Haohappy/文 上期在介绍 PEAR::Quick_Form 后,收到一些读者来信,希望继续介绍 PEAR 库中的其 它类库。Haohappy 在此作个尝试,在《PHP&More》上开个专栏,今后每一期介绍一个 实用的 PEAR 类,希望大家喜欢。 PEAR 库中目前共有 273 个 package,是全球 PHP 程 序员智慧的结晶,均经过较严格的质量控制,基本上每个 package 都很不错。我选择的原 则主要是两点:1。实用;2。稳定,只选择开发状态为 stable 的版本。如果大家对某个 package 特别感兴趣可以告诉我,将在杂志上优先介绍。 事实上将来有一些 package 是 Haohappy 也没有在实际开发中使用过的,所以写这 一系列文章的过程将是作者和读者共同学习, 共同进步的过程, 希望能得到更多同仁的反馈 和鼓励。有任何意见和建议请到超越 PHP 论坛(club.phpe.net)上的《PHP & MORE》杂 志专区提出,或发信至 haohappy@msn.com,我一定会及时回复。 In reality, it is not lazy to want to be able to do things quickly and easily, especially if they’re things that need to be done often。聪明的人总是懂得利用资源,不会尝试任何工作 都亲自从头做一遍。如果你也和我一样想站在前人的肩膀之上,就跟我来吧。 关于随机密码 系统自动生成随机密码或口令,这是 WEB 程序常见的功能之一。例如这样的注册模式你一定不会感到陌生:当用户 注册时,系统为用户生成一个随机密码并发至其注册邮箱。用户登录自己的邮箱得到系统所给的随机密码后,再登 录系统修改为自己想要的密码。这和直接发送密码到用户邮箱相比,避免了用户密码在网络上的明文传输,大大增 强了系统安全性。随机密码还常用于“忘记密码”功能,用户忘记密码后,系统可以为之自动再生成一个密码。 /*随机字符串的生成还有一个很酷的应用就是验证码,PEAR 中有一个对应的类库 Text_CAPTCHA。目前 Text_CAPTCHA 还只是 Alpha 版本,所以我们暂不讨论,等到 Stable 版本释出后我会向大家介绍。 Text_CAPTCHA 就基于即将介绍的 Text_Password 开发的。本文中也将会有一个图形验证码的实例,采用 Text_Password+GD 开发。*/ 我们在 WEB 开发中生成的密码都是由数字,字母和特殊字符组成的。根据不同的组合方式,密码的类型可以大概分 成纯数字型,纯字母型,纯特殊字符型,数字字母混合型,数字字母特殊字符混合型等。 PEAR::Text_Password 简介 http://pear.php.net/package/Text_Password 今 天 向 大 家 介 绍 的 PEAR 类 是 PEAR::Text_Password , 可 以 称 之 为 随 机 密 码 生 成 器 。 PEAR::Text_Password 是个比较简单的类,只包含一个 PHP 文件(Password.php),代码连注释在内只有 500 多行。Text_Password 易学易用,功能却相当强大,可以满足 WEB 应用中绝大部份情况下的需求(如果你觉得还 需要定制一些自己的功能,可以将这个类库再开发,相当方便)。 Text_Password 的主要特性如下: 可创建多种格式的随机密码,如纯字母,纯数字,纯特殊字符及混用型密码; PHPMORE VOL5 9/26
    • 可自定义密码的长度(字符数); 可限定密码中只能出现某些字符; 可一次性创建多个密码; 创建基于某个字符串的密码(非随机,使用不同算法对字符串进行处理,如翻转)。 Text_Password 把密码分为 pronounceable(可发音的)和 Unpronounceable(不可发音的)两种类型。 可发音型即纯英文字母型,虽然整个口令不是正常的英文单词,但一般可以划分出音节来发音,有助于记忆,例如 “steagionea”。不可发音型则是混用型,无法发音,如“miC106AIB7” 。显然,可发音型容易记忆而安全性相 对较差, 不可发音型不易记忆但安全性较好。 通常情况下我们不太需要记忆随机密码, 所以选用 Unpronounceable 的情况较常见一些。你可以视实际情况选择。 系统需求: PHP4.3.* /PHP5 PEAR::Text_Password 使用 Text_Password,实际上我们使用到的只有四个类方法,通过传递不同的参数来生成所需的密码。四个类方 法分别是 create(),createMultiple(),createFromLogin(),createMultipleFromLogin()。下面我们 来举例说明它们的用法。 (1) 创建可发音密码 <? Code - PronounceablePWD.php?> <?php require_once "Text/Password.php"; echo "创建 10 个字符的可发音密码....:<BR> "; echo Text_Password::create(10,'Pronounceable') . "<P>"; echo "创建三个 10 字符的可发音密码...:<BR> "; print_r(Text_Password::createMultiple(3)); ?> 运行结果如图: 在 这 个 程 序 中 , 我 们 使 用 create() 来 创 建 一 个 长 度 为 10 , 类 型 为 pronounceable 的 密 码 ; 使 用 createMultiple()来同时创建三个长度为 10,类型为 pronounceable 的密码密码。 PHPMORE VOL5 10/26
    • (2) 创建不可发音密码 <? Code - UnpronounceablePWD.php?> <?php require_once "Text/Password.php"; echo "创建一个 10 字符的不可发音密码....:<BR>"; echo Text_Password::create(10, 'unpronounceable') . "<P>"; echo "创建一个 8 字符且只包含有 a,b,c 的不可发音密码....:<BR>"; echo Text_Password::create(8, 'unpronounceable', 'a,b,c') . "<P>"; echo "<BR>同时创建 4 个不可发音密码...:n<BR>"; print_r(Text_Password::createMultiple(4, 10, 'unpronounceable')); echo "<P>"; echo "创建一个长度为 8 的只含有数字的不可发音密码:<BR>"; echo Text_Password::create(8, 'unpronounceable', 'numeric') . "<P>"; echo "创建一个长度为 8 的只包含数字或字母的不可发音密码::<BR>"; echo Text_Password::create(8, 'unpronounceable', 'alphanumeric') . "<P>"; ?> 运行结果如图: PHPMORE VOL5 11/26
    • 在这个程序中,我们仍然使用的是 create()和 createMultiple()两个类方法,但是在传递参数时使用的是 unpronounceable。 好,看过以上两个例子后,你应该大概知道如何使用 create()和 createMultiple()两个类方法了。create() 有三个参数,分别是密码长度,密码类型和密码组成。 具体用法请参看源代码: http://cvs.php.net/co.php/pear/Text_Password/Password.php?r=1.12 (2) 创建基于某个字符串的密码 有时候我们希望得到的密码不完全随机,而是有一定规律的。我们希望根据我们所给的字符来获得最终的密码。这 样有个好处就是可以将密码还原成明文,只要我们知道算法。 Text_Password 内建了一些算法来对字符串进行处理。有以下几种算法(或可称操作) : • xor • rotx • rotx++ • rotx-- • ascii_rotx • ascii_rotx++ • ascii_rotx-- • shuffle • reverse <? Code - GivenStrPWD.php ?> <?php require_once "Text/Password.php"; echo "n 密码原文为: 'haohappy', 加密方法为: 'reverse',<BR>加密结果为: "; echo Text_Password::createFromLogin('haohappy', 'reverse') . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'rot13',<BR>加密结果为:"; echo Text_Password::createFromLogin('haohappy', 'rot13') . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'rotx',<BR>加密结果为:"; echo Text_Password::createFromLogin('haohappy', 'rotx', 13) . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'rotx++',<BR>加密结果为:"; echo Text_Password::createFromLogin('haohappy', 'rotx++', 13) . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'rotx--',<BR>加密结果为:"; echo Text_Password::createFromLogin('haohappy', 'rotx--', 13) . "<P>"; PHPMORE VOL5 12/26
    • echo "n 密码原文为 'haohappy', 加密方法为: 'xor',<BR>加密结果为:"; echo Text_Password::createFromLogin('haohappy', 'xor', 5) . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'ascii_rotx',<BR>加密结果为: "; echo Text_Password::createFromLogin('haohappy', 'ascii_rotx', 5) . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'ascii_rotx++',<BR>加密结果为: "; echo Text_Password::createFromLogin('haohappy', 'ascii_rotx++', 5) . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'ascii_rotx--',<BR>加密结果为: "; echo Text_Password::createFromLogin('haohappy', 'ascii_rotx--', 5) . "<P>"; echo "n 密码原文为 'haohappy', 加密方法为: 'shuffle',<BR>加密结果为:"; echo Text_Password::createFromLogin('haohappy', 'shuffle', 1) . "<P>"; echo "n<b>密码组</b>原文为: 'haohappy', 'martin', 'vanhoucke', 'jansen', 加密 方法为: 'reverse':n"; $logins = array('haohappy', 'martin', 'vanhoucke', 'jansen'); echo "结果如下:<pre>"; print_r(Text_Password::createMultipleFromLogin($logins, 'reverse')); echo "</pre>"; ?> 运行结果如图: 你可以按 F5 刷新几次,会发现除了 Shuffle 操作(打乱)之外,其它结果都是固定不变,也即非随机的。 PHPMORE VOL5 13/26
    • 以上即 Text_Password 的三个主要应用,相信你已经初步掌握。 应用实例――图形验证码: 下面 Haohappy 将给出一个应用实例,那就是大家都非常熟悉的图形验证码。虽然只是一个简单的例子,却是一个 完整的验证码程序的核心部份。思路是采用随机的背景图,再用不同的颜色写上随机字符串。 首先,我们准备三个图形背景文件,分别命名为 bg1.png,bg2.png,bg3.png,放在 images 目录下。 代码如下: <? Code - ImageCode.php?> <?php require_once "Text/Password.php"; $string = Text_Password::create(10, 'pronounceable'); $num = rand(1,3); header("Content-type: image/png"); $im = imagecreatefrompng("images/bg$num.png"); switch ($num) { case 1: $orange = imagecolorallocate($im, 253, 238, 227); //字体颜色 break; case 2: $orange = imagecolorallocate($im, 255, 204, 51); break; case 3: $orange = imagecolorallocate($im, 255,255,200); break; } $px = (imagesx($im) - 7.5 * strlen($string)) / 2; //位置 imagestring($im, 5, $px-3, 2, $string, $orange); //写上随机字符串 imagepng($im); imagedestroy($im); ?> PHPMORE VOL5 14/26
    • 运行结果如下: 左图为随机码类型 pronounceable,右图为 unpronounceable 使用 Text_Password 的好处就在这里,可以非常方便地使用你想要的随机码类型。 程序非常简单,只有二十多行,但功能算是相当强大,想使用程序进行边缘识别不那么容易,安全性较高。 至少比腾讯网站上 QQ 免费注册的那个验证码强多了:) 当然你也可以再加入随机杂点,画线,使用随机字体,旋 转等等(如果有必要的话) 。你可以在网页中加入<IMAGE SRC='imagetest2.php'>来引用该验证码,配合 Session,就可以在用户登录时进行图形验证码认证。具体不详述,没什么难度。 如果对几个图像函数不熟悉,请自行查阅 PHP 手册。 参考资料: End-user Documentation and API documentation of PEAR::Text_Password PHPMORE VOL5 15/26
    • PEAR::PEAR 的析构器模拟 EasyChen / 文 Pear 是 Pear 的基类,其中提供了 Pear 类的一些基本服务,主要包括 o 析构器的模拟 o 错误处理机制 这里我们说析构器的模拟 。虽然 PHP4 中的 class 是没有析构器的,但是所有扩展自 Pear 的 class,都会在程序 结束时调用_classname()函数来析构。很神奇是吧,我们就来看看 pear 是怎么做到的。 首先,我们需要在构造器中调用$this->Pear()方法,实际上运行的是如下代码: <? Code ?> $classname = get_class($this); if ($this->_debug) { print "PEAR constructor called, class=$classnamen"; } if ($error_class !== null) { $this->_error_class = $error_class; } while ($classname) { $destructor = "_$classname"; if (method_exists($this, $destructor)) { global $_PEAR_destructor_object_list; $_PEAR_destructor_object_list[] = &$this; break; } else { $classname = get_parent_class($classname); } } 可以看到,Pear 取得了当前对象的 class 名,然后开始拼接出析构器的名称_classname,接着调用 method_exists 方法察看当前对象是否存在着方法,如果存在,把这个对以引用方式推入一个数组。从这个数组的名字上我们就可 以知道,析构时 pear 将遍历这个数组中的对象并调用其析构方法。 需要注意的是,这里为什么会使用一个数组。实际上,pear 用 while 语句制造了一个类似递归的效果。当当前对象 没有析构器时,pear 会去找它的父类的析构器,直到找到为止。 现在剩下的就是一个问题了,如何在程序执行完时触发这个析构过程? 要明白这一点,需要先了解一个函数 register_shutdown_function。这个函数可以添加一个函数,使 php 在脚本 运行结束前,调用它。可以注册多个函数,调用的顺序和注册的顺序一致。 pear 的代码里边有这么一句。 PHPMORE VOL5 16/26
    • register_shutdown_function("_PEAR_call_destructors"); 显然,_PEAR_call_destructors 就是那个析构过程了,代码和 Pear()有些类似。 <? Code ?> function _PEAR_call_destructors() { global $_PEAR_destructor_object_list; if (is_array($_PEAR_destructor_object_list) && sizeof($_PEAR_destructor_object_list)) { reset($_PEAR_destructor_object_list); while (list($k, $objref) = each($_PEAR_destructor_object_list)) { $classname = get_class($objref); while ($classname) { $destructor = "_$classname"; if (method_exists($objref, $destructor)) { $objref->$destructor(); break; } else { $classname = get_parent_class($classname); } } } // Empty the object list to ensure that destructors are // not called more than once. $_PEAR_destructor_object_list = array(); } // Now call the shutdown functions if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { call_user_func_array($value[0], $value[1]); } } } 总结一下,Pear 在初始化时建立了需要析构的对象数组,并利用了 register_shutdown_function 触发析构函数, _PEAR_call_destructors,从而完美的模拟了析构过程。 PHPMORE VOL5 17/26
    • Smarty 中 section 的简单使用 翟翔/文 什么是 section? 就像在 Smarty 官方手册里提到的,模板 section 是用来循环数组里的数据的。所有的 section 标签必须和 /section 标签成对儿使用。必须使用的参数是 name 和 loop。section 的 name 可以随你所好,可以是由字母、 数字和下划线组成的。section 可以嵌套使用,互相嵌套的 section 它们的 name 必须与众不同。变量 loop(通 常是数组的值)决定着 section 将要循环的次数。当用 section 显示一个变量时,section 的 name 必须紧跟 在变量名的后面,并用中括号 [] 括起来。当 loop 变量没有值时,sectionelse 就会运行。 下面就是一个 name 为 left_block,loop 为$LEFT_BLOCK_BODY 的 section,注意到<div class=”left_block”></div>当中显示变量的方法了么?section 的 name 也就是 left_block 紧跟在 $LEFT_BLOCK_BODY 的后面,并用中括号 [] 括起来了。 <{section name=left_block loop=$LEFT_BLOCK_BODY}> <div class="left_block"><{$LEFT_BLOCK_BODY[left_block]}></div> <{/section}> 为什么要使用 section? 就像 phpBB2 的成员列表,如下图,显示的内容 当你设计成员列表时(如图 1 所示) ,你要用到 section。 (图 1) 因为你无法确认有多少个用户注册,即使确认就 100 个限制用户注册,用传统的 table 设计网页你需要作的是牲 口般的工作,所以把这些交给 section 来处理吧。 其实还有很多地方可以用到 section。比如用 div 来作网页布局的时候,左、中、右区域的区块儿和模块儿都是 由后台数据库的 block management 来管理的,网页设计者根本就不知这些动态浮动的区块儿、模块儿在什么地 方、什么时候、什么样式、什么内容出现,或者这些区块儿和模块儿压根儿就不让你看见(管理员控制面板对一般 用户就是隐藏的),section 可以轻松地管理登陆框、导航栏、新闻发布、谁在线、语言选择等区块儿和模块儿。 如何使用 section? PHPMORE VOL5 18/26
    • Smarty 中的 section 和 PHPLib 中 template 的 block 很相似, section 更为 smart。 但 如果你使用过 PHPLib 的 block 很快你就会过渡到 section,如果你以前压根儿就没有听说过这些事儿, 反而更容易掌握 section 的 概念,因为什么都不知道嘛。Just kidding^_^ 来个简单的导航栏元素设计的例子。传统的导航栏设计很实诚(如图 2 所示), (图 2) 有多少个链接就用 dreamweaver 设计几个,有千千万万个怎么办呢?而且还要随时变化怎么办呢?你只用设计一 个链接其他的就让 section 去循环显示好了。 dreamweaver 设计一个名为 navigation.htm 的页面 用 (只保留 了 table 当中要用到的元素,其余的 html 元素在不影响显示的前提下均以省略) ,如下面 html 代码。 <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td><h2><{$L_TITLE_NAVIGATION}></h2></td> </tr> <{section name=navigation loop=$l_navigation}> <tr> <td><img src="<{$IMG_DOT}>" width="12" height="12"> <a href="<{$u_navigation[navigation]}>"><{$l_navigation[navigation]}></a></td> </tr> <{/section}> </table> 其中<a href="<{$u_navigation[navigation]}>"></a>就定义了超链接变量, <{$l_navigation[navigation]}>就定义了超链接的名称,用<{section name=navigation loop=$l_navigation}>和<{/section}>框住要循环显示的部分,一个自动化的导航栏的表现层就设计好了。 (请参看 MVC 模型) 光有皮肤没有骨架是支撑不起导航栏来的,所以让我们看看如何用 PHP 代码控制显示导航栏的。写一个名为 navigation.php 的 PHP 文件,代码如下: PHPMORE VOL5 19/26
    • $template->assign("l_navigation", array( //要在其他地方给$lang[' …… ']负值 $lang['index'], $lang['your_account'], $lang['downloads'], $lang['submit_news'], $lang['topics'], $lang['top10'] ) ); $template->assign("u_navigation",array( "./index.php", "./modules.php?name=Your_Account", "./modules.php?name=Downloads", "./modules.php?name=Submint_News", "./modules.php?name=Topics", "./modules.php?name=Top10" ) ); 你肯定要惊叹:“really?”真的是这么简单呀^_^ 首先,$template->assign 是在调用 Smarty 的 smarty 类当中的 assign 函数,assign 的意思就是赋值、分 配、指派的意思。$template->assign 给 navigation.htm 网页模板中的 l_navigation 变量赋了一个数组, 并提供了 6 个变量型的数组值(你要在其他地方给它们负值,或者直接像给超链接地址负值一样用" …… "的形式) ——用来显示超链接的名称,其中的数组键值用 PHP 默认的 0、1、2……就省略了;还给 u_navigation 变量赋了一 个数组,相对称的也是 6 个但已给出数值的变量——用来定义超链接的去向(其中运用了参数?name 来判断转向哪个 模块儿)。你可能会产生疑问:循环的次数在哪里定义的?loop 变量名仅仅是$l_navigation 数组呀!如果你有 机会查看 Smarty 的代码,你会发现 loop = count($l_navigation),只是这个过程被封装了,你只用调用这 个 section 接口就 OK 了。 然后,利用 smarty 类当中的 display 函数,就可以运行 navigation.php 查看你的导航栏了 PHPMORE VOL5 20/26
    • $template->display(“navigation.htm”); 进一步使用 section 就像我前面提到的,section 主要在处理多个重复其不断变化的元素上优势明显。这里由于篇幅有限,就把思想和 大家共享,把未完善的内容留给以后的文章。变化的数据来源于数据库,那么在$template->assign 一个 section 变量的时候可以用到 DB(是 PEAR 提供的对多种数据库操作的集成度很高的类,可以一次编写标准的 SQL 语句在大 多数主流数据库上到处运行)和 section 的综合利用。 在网页中显示居于左侧的区块儿和模块儿 $sql = "SELECT block_value FROM sirtoozee_blocks WHERE block_side = 'left' and block_visble = 'true' ORDER BY 'weight "; //用 getCol 这个 API 可以得到一维数组$block = array('','',...) $block_value = $db->getCol($sql); $template->assign("LEFT_BLOCK_BODY", $block_value) 你可以 print_r($block_value)看看$block_value 这个数组结构是不是就是 array('' …… '', ... )的 结构一模一样。其中具体的 DB 类的使用和网页 layout 布局我会在以后的文章中详细讲解。 如果大家对调用 Smarty 不熟悉,我在这里也简单介绍安装配置 Smarty 的方法: 到 http://smarty.php.net 下载 stable 版本的 smarty,将压缩包里./libs 文件夹里的所有文件解压缩到 Smarty(需要自己新建)文件夹中,并将你设计的网页模板文件,如 navigation.htm 放在 templates(需要 自己新建)文件夹下,还需要为 Smarty 新建 config、cache、templates_c 文件夹用来编译生成临时文件, 最后形成如下的文件目录结构: ./ ./Smarty/internals ./Smarty/plugins ./Smarty/Config_File.class ./Smarty/debug ./Smarty/Smarty.class ./Smarty/Smarty_Compiler.class ./templates PHPMORE VOL5 21/26
    • ./templates_c ./config ./cache 用如下代码调用 Smarty 类 // //模板引擎配置,采用 smarty-2.6.6 // include("./Smarty/Smarty.class.php"); $template = new Smarty; //安装并配置 Smarty 模板引擎 $template->template_dir = "./templates/ "; $template->compile_dir = "./templates_c"; $template->config_dir = "./configs"; $template->cache_dir = "./cache"; //为了和 javascript 标签区别开来 $template->left_delimiter = "<{"; $template->right_delimiter = "}>"; 您可以通过如下方式和作者翟翔联系 Email:legendren2008@yahoo.com.cn PHPMORE VOL5 22/26
    • XmlHttp 试用手记 EasyChen / 文 什么是 XmlHttp Xmlhttp 是一种浏览器对象,可用于模拟 http 的 GET 和 POST 请求。配合 JavaScript 可以实现页面数据在无 刷新下的定时数据更新,如果应用在聊天室、文字直播上可以取得较好的视觉效果。 IE 中的 XmlHttp 对象 在 IE 中 XmlHttp 被实现为 ActiveX 对象,通常使用 var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); 来创建一个对象,然后使用该对象的 open 方法来发出一个 Http 请求。 xmlhttp.open("GET", fragment_url); 这时候浏览器已经发出了 Http 请求,我们需要注册一个匿名函数给 XmlHttp 对象的 onreadystatechange 方 法,这样当请求返回时,xmlhttp 就会自动调用我们注册的这个函数,下边是一个实际的例子。 xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { element.innerHTML = xmlhttp.responseText; } } 因为我们不需要再发送任何信息,所以用下边的语句结束 xmlhttp.send(null); 我们将上边的过程封装为一个函数,下边是这个函数的完整代码: function loadFragmentInToElement(fragment_url, element_id) { var element = document.getElementById(element_id); var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); xmlhttp.open("GET", fragment_url); PHPMORE VOL5 23/26
    • xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { element.innerHTML = xmlhttp.responseText; } } xmlhttp.send(null); } 函数的调用方法如下所示: loadFragmentInToElement( 'http://domain.com/url.php' , DynamicContent_id ); 有了上边的代码,再配合 JavaScript 的定时函数,我们就可以实现定时的无刷新数据更新了,下边这个函数每隔 5 秒对 element_id 的数据进行一次更新。 function refresh( element_id ) { loadFragmentInToElement( 'show.php' , '' + element_id ); setTimeout( "refresh('ts')" , 5000 ); } 在 IE 上使用 XmlHttp 要注意的问题 特别要注意的是由于 IE 的 Cache 的关系,我们看见的 XmlHttp 并不总是最新读取的那一个,为了让 IE 不启用 Cache,我们发送给 IE 一个特殊的 Header,用 PHP 实现如下: header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); header( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" ); header( "Cache-Control: no-cache, must-revalidate" ); header( "Pragma: no-cache" ); XmlHttp 对象在 Gecko 上的实现 Gecko 上的 XmlHttp 和 IE 上略有不同,它并不需要通过 ActiveX 来创建。另外回调函数必须在 open 方法之前 注册,而 IE 并不要求,这是一个很需要注意的问题。 使用 JavaScript 实现 XmlHttp 的跨浏览器应用 为了能在多种浏览器上有一个统一的实现,我们可以用 JavaScript 来对不同浏览器的差异进行封装。这里我们采 用 Andrew Gregory 的实现。首先我们要引用 Andrew Gregory 的一个名为 xmlhttprequest.js 的 Js 脚本。 PHPMORE VOL5 24/26
    • <script type="text/javascript" src="xmlhttprequest.js"></script> 然后在创建 XmlHttp 对象时统一使用 new XMLHttpRequest()就可以了;其它的方法不用改变。这个 Js 脚本允 许 我 们 在 IE 、 Gecko ( Mozilla/FireFox ) 和 Opera 的 特 定 版 本 使 用 XmlHttp 。 下 边 是 调 整 后 的 loadFragmentInToElement 函数,这个函数在 IE6 和 FireFox1.0pre 上运行通过。 <script type="text/javascript" src="xmlhttprequest.js"></script> <script> function loadFragmentInToElement(fragment_url, element_id) { var element = document.getElementById(element_id); var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { element.innerHTML = xmlhttp.responseText; } } xmlhttp.open("GET", fragment_url); xmlhttp.send(null); } </script> xmlhttprequest.js 文件和具体的使用例子可以在我写的一个 DEMO 中找到。 XmlHttp 中的中文乱码问题 在默认情况下, XmlHttp 都是使用 Utf-8 字符集, 而我们使用的多是 GB2312 字符集, 这就要求我们进行 GB2312 到 Utf-8 的转码。PHP 提供了一个可选的专码模块,可以实现多种字符集之间的相互转化。加载这个专码模块的方 法如下: 打开 PHP 配置文件 php.ini,将 ;extension=php_mbstring.dll(*nix 是 php_mbstring.so) 前的分 号去掉。重新启动 Apache 以后,这个模块就可以使用了。如果有错误出现,请检查扩展目录的路径设置是否正确。 加载这个模块以后,我们就可以使用 mb_convert_encoding 函数来转码了: $utf8_string = mb_convert_encoding( $gb_string , 'UTF-8' , 'GB2312' ); 将转码后的字符输出就可以看见正确显示的中文了。 PHPMORE VOL5 25/26
    • 推荐图书 著名的 J2ee 核心模式,最近原书第 李维的新作,对于面向对象的初学者 《程序员修炼之道》同系列的书,深 二版的中文版出来了,书不错,翻译 和 Delphi For dotnet 的用户来说很不 入浅出的讲解了 JUNIT 的使用。 得也不错。 错,Delphi 也开始 UT 和 TDD 了 PHPMORE VOL5 26/26