现在的位置: 首页 > 综合 > 正文

php 正则表达式函数库

2018年05月28日 ⁄ 综合 ⁄ 共 85138字 ⁄ 字号 评论关闭

关于正则表达式 (regular expression),似乎译成:字符串解析处理,较合乎字面上的意义。但目前所有的相关书籍都译成正则表达式或是正规表示法....等等,实际上是负责字符串解析比对,并对字符串做相关的处理。

本函数库让 php 也能处理复杂的字符串操作。它采用了 posix 1003.2 的扩充常规处理 (regular expression) 的标准。更多关于正则表达式的信息可以参考 unix shell、perl 或是 awk 等相关的书籍。

ereg: 字符串比对解析。

ereg_replace: 字符串比对解析并取代。

eregi: 字符串比对解析,与大小写无关。

eregi_replace: 字符串比对解析并取代,与大小写无关。

split: 将字符串依指定的规则切开。

sql_regcase: 将字符串逐字返回大小写字符。

ereg字符串比对解析。

语法: int ereg(string pattern, string string, array [regs]);

返回值: 整数数组

函数种类: 资料处理

内容说明: 本函数以 pattern 的规则来解析比对字符串 string。比对结果返回的值放在数组参数 regs 之中,regs[0] 内容就是原字符串 string、regs[1] 为第一个合乎规则的字符串、regs[2] 就是第二个合乎规则的字符串,余类推。若省略参数 regs,则只是单纯地比对,找到则返回值为 true。

使用范例,这个例子可对使用者输入的 e-mail 作简单的检查,检查使用者的 e-mail 字符串是否有 @ 字符,在 @ 字符前有英文字母或数字,在之后有数节字符串,最后的小数点后只能有二个或三个英文字母。super@mail.wilson.gs 就可以通过检查,super@mail.wilson 就不能通过检查。

<;?php

if (eregi(";^[_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$";,$email)) {

echo ";您的 e-mail 通过初步检查";;

}

?>;

参考: ereg_replace() eregi() eregi_replace()

ereg_replace字符串比对解析并取代。

语法: string ereg_replace(string pattern, string replacement, string string);

返回值: 字符串

函数种类: 资料处理

内容说明: 本函数以 pattern 的规则来解析比对字符串 string,欲取而代之的字符串为参数 replacement。返回值为字符串类型,为取代后的字符串结果。

使用范例

<;?php

$text = ‘this is a {1} day, not {2} and {3}.‘;

$daytype = array( 1 =>; ‘fine‘,

2 =>; ‘overcast‘,

3 =>; ‘rainy‘ );

while (ereg (‘{([0-9]+)}‘, $text, $regs)) {

$found = $regs[1];

$text = ereg_replace(";{";.$found.";}";, $daytype[$found], $text);

}

echo ";$textn";;

this is a fine day, not overcast and rainy.

?>;

参考: ereg() eregi() eregi_replace()

eregi字符串比对解析,与大小写无关。

语法: int eregi(string pattern, string string, array [regs]);

返回值: 整数数组

函数种类: 资料处理

内容说明: 本函数和 ereg() 类似,用法也相同。不同之处在于 ereg() 有区分大小写,本函数与大小写无关。

参考: ereg() ereg_replace() eregi_replace()

eregi_replace字符串比对解析并取代,与大小写无关。

语法: string eregi_replace(string pattern, string replacement, string string);

返回值: 字符串

函数种类: 资料处理

内容说明: 本函数和 ereg_replace() 类似,用法也相同。不同之处在于 ereg_replace() 有区分大小写,本函数与大小写无关。

参考: ereg() ereg_replace() eregi()

split将字符串依指定的规则切开。

语法: array split(string pattern, string string, int [limit]);

返回值: 数组

函数种类: 资料处理

内容说明: 本函数可将字符串依指定的规则分开。切开后的返回值为数组变量。参数 pattern 为指定的规则字符串、参数 string 则为待处理的字符串、参数 limit 可省略,表示欲处理的最多合乎值。值得注意的是本函数的 pattern 参数有区分大小写。

参考: explode() implode()

sql_regcase将字符串逐字返回大小写字符。

语法: string sql_regcase(string string);

返回值: 数组

函数种类: 资料处理

内容说明: 本函数可将字符串之字符逐字返回大小写。在 php 使用上,本函数没有什么作用,但可能可以提供外部程序或数据库处理。

使用范例,例中的返回字符串为 [ww][ii][ll][ss][oo][nn]

<;?php

print(sql_regcase(";wilson";));

?>;

php 正则表达式中的特殊字符

字符

意义:对于字符,通常表示按字面意义,指出接着的字符为特殊字符,不作解释。

例如:b匹配字符’b’,通过在 b 前面加一个反斜杠,也就是 b,则该字符变成特殊字符,表示匹配一个单词的分界线。

或者:

对于几个字符,通常说明是特殊的,指出紧接着的字符不是特殊的,而应该按字面解释。

例如:* 是一个特殊字符,匹配任意个字符(包括0个字符);例如:a* 意味匹配 0 个或多个 a。为了匹配字面上的 *,在a前面加一个反斜杠;例如:a* 匹配’a*’。

字符^

意义:表示匹配的字符必须在最前边。

例如:^a 不匹配";an a,";中的’a’,但匹配 ";an a.";中最前面的’a’。

字符$

意义:与^类似,匹配最末的字符。

例如:t$不匹配";eater";中的’t’,但匹配";eat";中的’t’。

字符*

意义:匹配*前面的字符0次或n次。

例如:bo*匹配";a ghost booooed";中的’boooo’或";a bird warbled";中的’b’,但不匹配";agoat g

runted";中的任何字符。

字符+

意义:匹配+号前面的字符1次或n次。等价于{1,}。

例如:a+ 匹配";candy";中的’a’和 ";caaaaaaandy.";中的所有’a’。

字符?

意义:匹配?前面的字符0次或1次。

例如:e?le? 匹配";angel";中的’el’和 ";angle."; 中的’le’。

字符.

意义:(小数点)匹配除换行符外的所有单个的字符。

例如:.n 匹配 ";nay, an apple is on the tree"; 中的’an’和’on’,但不匹配’nay’。

字符(x)

意义:匹配’x’并记录匹配的值。

例如:(foo) 匹配和记录 ";foo bar."; 中的’foo’。匹配子串能被结果数组中的素[1], ...,[n] 返回,或被regexp对象的属性, ..., 返回。

字符x│y

意义:匹配’x’或者’y’。

例如:green│red 匹配 ";green apple"; 中的’green’和 ";red apple."; 中的’red’。

字符{ n }

意义:这里的n是一个正整数。匹配前面的n个字符。

例如:a{ 2 }不匹配 ";candy,"; 中的’a’,但匹配 ";caandy,"; 中的所有’a’和 ";caaandy."; 中前面的两个’a’。

字符{ n, }

意义:这里的 n 是一个正整数。匹配至少n个前面的字符。

例如:a{ 2, } 不匹配 ";candy"; 中的’a’,但匹配 ";caandy"; 中的所有’a’和 ";caaaaaaandy."; 中的所有’a’

字符{ n,m }

意义:这里的 n 和 m 都是正整数。匹配至少n个最多m个前面的字符。

例如:a{ 1,3 } 不匹配 ";cndy"; 中的任何字符,但匹配 ";candy,"; 中的’a’,";caandy,"; 中的前面两个

’a’和 ";caaaaaaandy"; 中前面的三个’a’,注意:即使 ";caaaaaaandy"; 中有很多个’a’,但只匹配前面的三 个’a’即 ";aaa";。

字符[xyz]

意义:一字符列表,匹配列出中的任一字符。你可以通过连字符-指出一个字符范围。

例如:[abcd]跟 [a-c] 一样。它们匹配 ";brisket"; 中的’b’和 ";ache"; 中的’c’。

字符[^xyz]

意义:一字符补集,也就是说,它匹配除了列出的字符外的所有东西。 你可以使用连字符-指出一 字符范围。

例如:[^abc]和[^a-c] 等价,它们最早匹配 ";brisket"; 中的’r’和 ";chop."; 中的’h’。

字符

意义:匹配一个空格(不要与 b 混淆)

字符b

意义:匹配一个单词的分界线,比如一个空格(不要与混淆)

例如:bnw 匹配 ";noonday"; 中的’no’,wyb 匹配 ";possibly yesterday."; 中的’ly’。

字符b

意义:匹配一个单词的非分界线

例如:wbn 匹配 ";noonday"; 中的’on’,ybw匹配 ";possibly yesterday."; 中的’ye’。

字符cx

意义:这里的 x 是一个控制字符。匹配一个字符串的控制字符。

例如:cm 匹配一个字符串中的 control-m。

字符d

意义:匹配一个数字,等价于 [0-9]。

例如:d或[0-9] 匹配 ";b2 is the suite number."; 中的’2’。

字符d

意义:匹配任何的非数字,等价于 [^0-9]。

例如:d或[^0-9] 匹配 ";b2 is the suite number."; 中的’b’。

字符f

意义:匹配一个表单符

字符n

意义:匹配一个换行符

字符r

意义:匹配一个回车符

字符s

意义:匹配一个单个 white 空格符,包括空格,tab,form feed,换行符,等价于 [ fnrtv]。

例如:sw* 匹配 ";foo bar.";中的’ bar’。

字符s

意义:匹配除 white 空格符以外的一个单个的字符,等价于 [^ fnrtv]。

例如:sw* 匹配 ";foo bar."; 中的’foo’。

字符t

意义:匹配一个制表符

字符v

意义:匹配一个顶头制表符

字符w

意义:匹配所有的数字和字母以及下划线,等价于 [a-za-z0-9_]。

例如:w 匹配 ";apple,"; 中的’a’,";.28,"; 中的’5’和 ";3d."; 中的’3’。

字符w

意义:匹配除数字、字母外及下划线外的其它字符,等价于 [^a-za-z0-9_]。

例如:w 或者 [^$a-za-z0-9_] 匹配 ";50%."; 中的’%’。

字符n

意义:这里的n是一个正整数。匹配一个正则表达式的最后一个子串的n的值(计数左圆括号)。

例如:apple(,)sorange1 匹配 ";apple, orange, cherry, peach."; 中的’apple, orange’,下面有一个更加完整的例子。

注意:如果左圆括号中的数字比n指定的数字还小,则n取下一行的八进制 escape 作为描述。

字符 ooctal 和 xhex

意义:这里的 ooctal 是一个八进制的 escape 值,而 xhex 是一个十六进制的 escape 值,允许在一个正则表达式中嵌入 ascii 码

附:下表是元字符及其在正则表达式上下文中的行为的一个完整列表:

字符 描述

将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。例如,‘n‘ 匹配字符 ";n";。‘n‘ 匹配一个换行符。序列 ‘‘ 匹配 ";"; 而 ";("; 则匹配 ";(";。

^

匹配输入字符串的开始位置。如果设置了 regexp 对象的 multiline 属性,^ 也匹配 ‘n‘ 或 ‘r‘ 之后的位置。

$

匹配输入字符串的结束位置。如果设置了regexp 对象的 multiline 属性,$ 也匹配 ‘n‘ 或 ‘r‘ 之前的位置。

*

匹配前面的子表达式零次或多次。例如,zo* 能匹配 ";z"; 以及 ";zoo";。 * 等价于{0,}。

+ 匹配前面的子表达式一次或多次。例如,‘zo+‘ 能匹配 ";zo"; 以及 ";zoo";,但不能匹配 ";z";。+ 等价于 {1,}。

?

匹配前面的子表达式零次或一次。例如,";do(es)?"; 可以匹配 ";do"; 或 ";does"; 中的";do"; 。? 等价于 {0,1}。

{n}

n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}‘ 不能匹配 ";bob"; 中的 ‘o‘,但是能匹配 ";food"; 中的两个 o。

{n,}

n 是一个非负整数。至少匹配n 次。例如,‘o{2,}‘ 不能匹配 ";bob"; 中的 ‘o‘,但能匹配 ";foooood"; 中的所有 o。‘o{1,}‘ 等价于 ‘o+‘。‘o{0,}‘ 则等价于 ‘o*‘。

{n,m}

m 和 n 均为非负整数,其中n <;= m。最少匹配 n 次且最多匹配 m 次。刘, ";o{1,3}"; 将匹配 ";fooooood"; 中的前三个 o。‘o{0,1}‘ 等价于 ‘o?‘。请注意在逗号和两个数之间不能有空格。

?

当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 ";oooo";,‘o+?‘ 将匹配单个 ";o";,而 ‘o+‘ 将匹配所有 ‘o‘。

.

匹配除 ";n"; 之外的任何单个字符。要匹配包括 ‘n‘ 在内的任何字符,请使用象 ‘[.n]‘ 的模式。

(pattern)

匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 matches 集合得到,在vbscript 中使用 submatches 集合,在jscript 中则使用 {content}… 属性。要匹配圆括号字符,请使用 ‘(‘ 或 ‘)‘。

(?:pattern)

匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 ";或"; 字符 (|) 来组合一个模式的各个部分是很有用。例如, ‘industr(?:y|ies) 就是一个比 ‘industry|industries‘ 更简略的表达式。

(?=pattern)

正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, ‘windows (?=95|98|nt|2000)‘ 能匹配 ";windows 2000"; 中的 ";windows"; ,但不能匹配 ";windows 3.1"; 中的 ";windows";。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

(?!pattern)

负向预查,在任何不匹配negative lookahead matches the search string at any point where a string not matching pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如‘windows (?!95|98|nt|2000)‘ 能匹配 ";windows 3.1"; 中的 ";windows";,但不能匹配 ";windows 2000"; 中的 ";windows";。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

x|y

匹配 x 或 y。例如,‘z|food‘ 能匹配 ";z"; 或 ";food";。‘(z|f)ood‘ 则匹配 ";zood"; 或 ";food";。

[xyz]

字符集合。匹配所包含的任意一个字符。例如, ‘[abc]‘ 可以匹配 ";plain"; 中的 ‘a‘。

[^xyz]

负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]‘ 可以匹配 ";plain"; 中的‘p‘。

[a-z]

字符范围。匹配指定范围内的任意字符。例如,‘[a-z]‘ 可以匹配 ‘a‘ 到 ‘z‘ 范围内的任意小写字母字符。

[^a-z]

负值字符范围。匹配任何不在指定范围内的任意字符。例如,‘[^a-z]‘ 可以匹配任何不在 ‘a‘ 到 ‘z‘ 范围内的任意字符。

b

匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘erb‘ 可以匹配";never"; 中的 ‘er‘,但不能匹配 ";verb"; 中的 ‘er‘。

b

匹配非单词边界。‘erb‘ 能匹配 ";verb"; 中的 ‘er‘,但不能匹配 ";never"; 中的 ‘er‘。

cx

匹配由x指明的控制字符。例如, cm 匹配一个 control-m 或回车符。 x 的值必须为 a-z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c‘ 字符。

d

匹配一个数字字符。等价于 [0-9]。

d

匹配一个非数字字符。等价于 [^0-9]。

f

匹配一个换页符。等价于 x0c和 cl。

n

匹配一个换行符。等价于 x0a和 cj。

r

匹配一个回车符。等价于 x0d 和 cm。

s

匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ fnrtv]。

s

匹配任何非空白字符。等价于 [^ fnrtv]。

t

匹配一个制表符。等价于 x09 和 ci。

v

匹配一个垂直制表符。等价于 x0b 和 ck。

w

匹配包括下划线的任何单词字符。等价于‘[a-za-z0-9_]‘。

w

匹配任何非单词字符。等价于 ‘[^a-za-z0-9_]‘。

xn

匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如, ‘x41‘ 匹配 ";a";。‘x041‘ 则等价于 ‘x04‘ &; ";1";。正则表达式中可以使用 ascii 编码。.

num

匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,‘(.)‘ 匹配两个连续的相同字符。

n

标识一个八进制转义值或一个后向引用。如果 n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。

nm

标识一个八进制转义值或一个后向引用。如果 nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若n 和 m 均为八进制数字 (0-7),则 nm 将匹配八进制转义值 nm。

nml

如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。

un

匹配 n,其中 n 是一个用四个十六进制数字表示的 unicode 字符。例如,u00a9 匹配版权符号 (?)。

php 程序执行功能函数库

escapeshellcmd: 除去字符串中的特殊符号。

exec:执行外部程序。

system:执行外部程序并显示输出资料。

passthru:执行外部程序并不加处理输出资料。

escapeshellcmd除去字符串中的特殊符号。

语法: string escapeshellcmd(string command);

返回值: 字符串

函数种类: 操作系统与环境

内容说明: 本函数除去了字符串中的特殊符号,可以防止使用者耍花招来破解该服务器系统。可以用本函数搭配 exec() 或是 system() 二个函数,酱子可以减少网络上的使用者恶意的破晃募机会。

使用范例

<;?php

system(escapeshellcmd($cmdline));

?>;

exec执行外部程序。

语法: string exec(string command, string [array], int [return_var]);

返回值: 字符串

函数种类: 操作系统与环境

内容说明:本函数执行输入 command 的外部程序或外部指令。它的返回字符串只是外部程序执行后返回的最后一行;若需要完整的返回字符串,可以使用 passthru() 这个函数。

要是参数 array 存在,command 会将 array 加到参数中执行,若不欲 array 被处理,可以在执行 exec() 之前呼叫 unset()。若是 return_var 跟 array 二个参数都存在,则执行 command 之后的状态会填入 return_var 中。值的注意的是若需要处理使用者输入的资料,而又要防止使用者耍花招破解系统,则可以使用 escapeshellcmd()。

参考 system() passthru() popen() escapeshellcmd()

system执行外部程序并显示输出资料。

语法: string system(string command, int [return_var]);

返回值: 字符串

函数种类: 操作系统与环境

内容说明 本函数就像是 c 语中的函数 system(),用来执行指令,并输出结果。若是 return_var 参数存在,则执行 command 之后的状态会填入 return_var 中。同样值得注意的是若需要处理用户输入的资料,而又要防止用户耍花招破解系统,则可以使用 escapeshellcmd()。若 php 以模块式的执行,本函数会在每一行输出后自动更新 web 服务器的输出缓冲暂存区。若需要完整的返回字符串,且不想经过不必要的其它中间的输出界面,可以使用 passthru()。

参考 passthru() popen() exec()

passthru执行外部程序并不加处理输出资料。

语法: string passthru(string command, int [return_var]);

返回值: 字符串

函数种类: 操作系统与环境

内容说明: 本函数类似 exec() 用来执行 command 指令,并输出结果。若是 return_var 参数存在,则执行 command 之后的状态会填入 return_var 中。若输出的资料是二进位的资料,并且需要输出到浏览器中的话,使用本函数就相当合适了。例如使用 pbmplus 工具来执行指令,并返回二进位的图形资料。可以先配置返回资料的标头 (header) 为 content-type: imagegif,然后呼叫 pbmplus 程序处理图形资料,并将二进位的图形资料直接返回浏览器。

参考 passthru() exec()

用 php 生成 excel 文件

<;?

header(‘content-type:applicationvnd.ms-excel‘);

header(‘content-disposition:filename=test.xls‘);

echo ‘test1t‘;

echo ‘test2tn‘;

echo ‘test1t‘;

echo ‘test2tn‘;

echo ‘test1t‘;

echo ‘test2tn‘;

echo ‘test1t‘;

echo ‘test2tn‘;

echo ‘test1t‘;

echo ‘test2tn‘;

echo ‘test1t‘;

echo ‘test2tn‘;

?>;

在 php 环境运行上面的代码,大家就可以看到浏览器询问用户是否下载 excel 文档,点击保存,硬盘上就多了一个 excel 的文件,使用 excel 打开就会看到最终的结果,怎么样不错吧。

其实在做真正的应用的时候,大家可以将数据从数据库中取出,然后按照每一列数据结束后加t,每一行数据结束后加n的方法 echo 出来,在 php 的开头用 header(‘content-type:applicationvnd.ms-excel‘);表示输出的是 excel 文件,用header (‘content-disposition:filename=test.xls‘);表示输出的文件名为text.xls。这样就行了。

我们更可以修改 header 让他输出更多格式的文件,这样 php 在处理各种类型文件方面就更加方便了。

正确理解 php 错误信息

我们编写程序时,无论怎样小心谨慎,犯错总是在所难免的。这些错误通常会迷惑php编译器。如果开发人员无法了解编译器报错信息的含义,那么这些错误信息不仅毫无用处,还会常常让人感到沮丧。

编译 php 脚本时,php 编译器会尽其所能报告它遇到的第一个问题。这样就产生一个问题:只有当错误出现时,php 才能将它识别出来(本文后面对此问题进行了详细描述)。正是由于这个缘故,编译器指出出错的那行,从表面上看来可能语法正确无误,或者可能是根本就不存在的一行!

更好地理解错误信息可以大大节省确定并改正错误内容所花费的时间。因此,在本文中,我将努力阐明多种不同类型的php报错信息,以及在开发过程中如何正确理解各种报错信息的含义。

本文中所讲述的内容与您所应用的php的版本无关,因为本文所描述的各种错误并不限定于某一特殊版本的特定错误。另外我们假定您是一位初级或者中级程序员,并已经从事编程工作有半年或一年的时间。

要搞清楚编译器为什么会报告某一行上存在错误,首先必须明确编译器解析php代码的机制。我并不打算在本文中对此进行详细论述,但是,我们将会讨论一些更易于引发错误的简单概念。

变量声明

如果在一条语句中声明一个变量,具体方式如下所示:

$variable = ‘value‘;

编译器首先求出语句右半部分的值(即等号右边的所有内容)。在一些编程书籍中,将此表示为语句的 rhs (右半部分)。恰恰正是语句的这一部分常常会引发错误。如果使用的语法不正确,就会出现解析错误。

解析错误

parse error:解析错误,unexpected t_while in c:program filesapache groupapachehtdocsscript.php on line 19

每次确定了前一错误时,解析错误一个接一个地不断出现。因为 php 在第一个解析错误之后就停止执行脚本,调试并纠正这一系列的错误往往会让人觉得特别厌烦。

而且,解析错误具有很少的信息,几乎不报告错误所在的行号。具体原因就是当出现错误时,编译器判定好几行的语法看起来应该是有效的,直至遇到无效的语法,最可能的情形就是表达式中使用了预定义的字词,例如;

while = 10; bad ? while 就是一个预定义字词,不能分配给一个值

预定义的字词包括 while、function 等,如果 php 使用 uses to evaluate your code。您不能使用这些预定义字词来命名变量,而且如果您非要这样做的话,php就会报出更多的错误,这是您无法忍受。

关于这个问题,下面的示例可能会对您有所帮助。请咨询阅读一下下面所示的 php 代码:

<;?php

$b = ";somevalue";

if($b == ";somevalue";){

print ";hello world!";;

}

?>;

错误位于";$b =";一行(在语句的末端缺少分号),所以错误应该是";解析错误:第3行缺少分号";对吧?而不应该依据解析器判定的:

parse error: parse error, unexpected t_if in c:program filesapache

groupapachehtdocsereg2.php on line 4

在第 4 行,if() 语句的语法是正确的。那么,编译器是被什么给搞糊涂了呢?线索就是";unexpected t_if"; 部分。出现 ";unexpected t_???";错误时,它所表示的含义为:编译器发现在预定义字不应该出现的位置出现。t_if 代表 if(), t_while 代表 while(), t_for 代表 for()等。

值得庆幸的是,一些错误的原因也很简单:

语句没有使用分号(;)结束,比如上面的示例。字符串中缺少引号。

其他一些常见的错误

我见过的最常见的错误就是,当没有使用大括号( } )结束一个函数或者一个循环时出现的错误,这很可能是最常见,最让人烦的错误。具体代码如下:

function uselessfunction() {

for($i <; 0; $i <; 10; $i++){

}

将产生下列错误:

parse error: parse error, unexpected $ in c:program filesapache

groupapachehtdocsereg2.php on line 9

由于函数 uselessfunction 没有使用大括号( } )来结束,php 编译器不断查找表示结束的大括号直至到达文件末尾为止。因为编译器未找到一个匹配的大括号,就会报告文件末尾处有错误。

如果正确地反映了代码的层次结构,错误信息就会变得非常明显。如果没有标明代码的层次结构,那么最后要想查清楚到底忘记了什么也会变得几乎是不可能的。所以,请记住,一定要标明代码的层次结构。tab 键可以很容易地实现这一点。对后续的开发人员来说,把握代码框架并对其进行修改也会更容易一些。

mysql 错误

另一极其令人讨厌的错误信息就是最常见的mysql错误,这常常使 php新手感到颇为头疼:

warning: supplied argument is not a valid mysql result resource in...

上面所报告有错的一行可能是:

while($row = mysql_fetch_array($result)) {

参数 $result 并不是一个有效的资源。在英语中它表示因为查询失败,将无法处理 mysql_fetch_array。任一查询的语法无效(您应该将查询复制-粘贴到 mysql 控制台参考来进行测试),或者与数据库的连接失败(这种情况下您应该再次检查用户名和口令等)。

防止错误发生

第一步,智能代码器可采取以下几步来消除下列错误出现:

· 在每一条语句的末尾处,不必考虑添加分号——这应该成为一种习惯。

· 总是要尽可能标明代码的层次结构,这可以使您能够查看是否忘记在 if 调用或函数末端等位置添加大括号。

· 请使用可突出显示语法的编辑器(如 html-kit)。有了这类编辑器的辅助,您就能确定是否忘记了添加引号,是否缺少分号等。

结论

本文我们对php编译器可报出的一些看起来可能没有什么意义的错误有了一定的了解。我们需要将所学的知识应用到如何避免错误以及错误出现时如何纠正错误。调试是一个开发人员所有工作中的最重要的部分之一。提高调试效率可大大加快整个工作的进度,缩短完成一项工程所需花费的时间,同时还可以明显减轻代码失败所带来的精神压力。

用 php 轻松搞定虚拟域名

不知道大家最近上网是否发现一个新现象,就是有一些网站开始提供“username@server”的虚拟域名服务。由于“@”的魅力,大家纷纷申请,你或许会想:“如果我也能提供这种服务,该多好阿:)人气肯定不错1本文将给大家揭开“@”的“神秘”面纱,让大家都可以来“@”!(do u @ today?)

这个并不是电子邮件的地址,是一种虚拟域名,不相信的话可以在浏览器中访问“bbs@zphp.com”。部分朋友应该使用过ie的ftp功能,就是在浏览器的地址栏中键入“password:username@server”ie就会自动登陆ftp服务器;而在 http1.1 协议中,就规定了http访问授权功能,形式同样为“password:username@server”,其中“password:”可以省略,也是是访问“bbs@zphp.com”实际上是以 bbs 的身份访问“zphp.com”这个服务器。

那么我们只是需要将具体的 uri 传送给 php 程序,在数据库中搜索出真实的 url 重定向就可以了。

首先我们需要制作一个传送 uri 的页面(作为服务器的默认文档,一般命名为 index.htm);在 js 的window 对象中就可以实现这项功能,下面是 index.htm 的源代码:

<;script>;

this.location = ‘gotourl.php?url=’ + this.location.href;

<;script>;

上面的代码会将浏览器重定向到 gotourl.php,并且通过 querystring 给变量 $url 赋值为当前的uri。

成功将 uri 传递给 php 程序后,就可以进入数据库查找真实 url,下面是 sql 数据库相对应的 table 的结构:

create table domain(

id int(3) unsigned default ‘0’ not null, # 域名id

domain char(20) not null, # 域名

gotourl char(255) not null, # 真实的url

);

建立好了 table,就可以开始编写 gotourl.php 了,程序分为三个部分:

1、分析url:

$url = preg_replace(“^http:i”, “”, $url); 将 url 前面的“http:”去掉,不区分大小写

$url = preg_replace(“@.+$”, “”, $url); 将“@”后面的部分去除。

那么,剩下的url就只含有“username”的部分了。为了给数据库应用,需要对敏感的字符进行处理:

$url = addslashes($url);

2、搜索真实的url:

这里为了实现程序的通用性,使用了一个数据库的操作类(修改自 phplib)来操作sql数据库:

$db = new dbsql(); 连接数据库

$querystring = sprinf(“select gotourl from domain where domain=’%s’;”, $url); 生成查询字符串

$gotourl = $db->;result($querystring); 查询取得结果

3、重定向:

在 php 中重定向浏览器有多种方法,在这里使用比较简单的 httpheader 来实现:

header(“location: $gotourl”);

其实像网易那样子的“username.yeah.net”的虚拟域名服务和“@”的实现方法大同小异,但是“.”需要以价值 200 元的 dns 泛解析为代价,而“@”所需要的仅仅是:

1、 phpsql数据库的权限;

2、真正dns解析的域名。

如果需要在虚拟域名服务中加入广告,比如网易的 popup 窗口,可以将重定向部分改为:

<;script>;

window.open(";url";,";nease";,";width=windth,height=height";);

<;script>;

为了对得起“天地良心”,笔者没有将合并后完整的程序加上来(骗稿费?),如果大家比较懒,需要完整的代码(包括了添加等等),可以在 http:zphp.com 或者 http:bbs@zphp.com 取得。希望大家都有一个好的访问量。

如何文档化 php 类

你已经阅读过关于:面向对象编程可以帮助你管理你的大型 web 项目,并且你已经开始使用 php 来进行面向对象编程了吗?如果你已经编写了几个类应用在网站上并且你是一个有条理的人的话,那么你应该已经编写了关于它们的一些文档。但是如果你是一个象我一样的不拘小节的人,你只是会在类的源代码中加一些注释而没有别的文档。没有文档就很难记住方法的名字和它们的使用方法(参数和含义)。解决这种情况最典型的办法就是打开 源代码文件,从成百上千的语句中查找。

应该有一种好的方法----如果你曾经使用过 java 语言,你将知道 javadoc 文档系统。这个工具允许你在源代码文件注释中插入一些标记,这些标 记可以被 javadoc 工具进行分析以便生成一系列的 html 页面把你的类文档化。那样在编程的同时你可以开着浏览器并且可以得到类列表和带有说明的类方 法的列表。在你开发 web 应用时,这个可以成为你的参考,提高工作效率和加快开发速度。

我的意见是维护一个作为源代码内的引用文档要比维护一个独立的文档要容易和更实用,因为这个方法更容易保持更新。否则就非常容易变得懒惰从而将对文档 的更新推后到无限期(如果一定要给它加个期限,我想是一万年)。相反使用象这样的一个工具,只有一点工作量就是在你正在修改的源代码附近更新一个标记,接 着运行工具再一次生成更新过的 html 页面。

一些 php 文档工具的预览

在对上面了解了之后,我搜索了一下哪些是可用的,并且我发现了如下一些有趣的工具:

phpsearchdoc 是 enzyme 项目的一部分。因为 enzyme是一个巨大的项目,所以需要将其文档化。那里的开发人员已经编写 了他们自已的文档系统并且他们非常慷慨地将其作为一个独立的包进行发布。得到的文档首先被写入数据库,然后可以被一些php脚本查看,象一个动态的 web 站点。

从现存的信息中将用于分析的逻辑分离出来的想法相当好,然而 phpsearchdoc (版本1.01)不具有一个真正的分析器,而是从源 文件,甚至包括注释中搜索关键字。事实上,对我来说碰巧发生过在我的注释中存在 ‘function‘ 单词,结果分析器愚蠢地认为在这个单词后面的词就是函 数的名字。更不幸的是,我不巧在同一行放了一个单引号(‘),接着我试图将数据写到数据库中,mysql 作出了抱怨(出错了,因为单引号在 mysql 中被用于分割字符串)。

而且它的安装及运行相当困难,因为它还是一个 alpha 测试版。毕竟比起文档系统来说它更象是一个交叉引用生成器,正如我知道的,你不能在函数和方法中加入自已的注释。

phpxref,就象名字所指的比起一个真正的文档系统来似乎更象是面向交叉引用的生成处理。更进一步说它更适合于正常的过程化编程而不是面向对象编程。

phpautodoc 的目标是实现象 javadoc应用于 java 那样用于 php。它看上去是满足我的文档需求的完美解决。为了试验它我 不得不编译了 php的cgi 版本(我通常使用模块版本),因为生成器是用 php 编的。我可能容易地在一个 linux 系统下编译和安装静态的执行程序,可以 使用这些命令:

rmconfig.chche

makeclean

.configure

make

cpphpusrlocalbin

我决定对它自已的 php 源码进行测试,并且我发现它只有部分可以工作:它只能够生成类的文档(生成整齐的格式),但是不能生成小结。我不知道是否这个 只是碰巧发生在我的机器上,但是在试图生成小结时却因为 coredump (内核崩溃)而停止(php4.0pl2, redhat6.2 环境)。假如在你的机器 usrlocalbin 下安装了 php 执行版本,调用它的语法是(为了得到结果我不得不给出 php 文件和输出目录的全路径)

phpautodoc-o

phpdoc 是一个用来维护在 web 站点上的 php文件,并且它非常适合分布式开发方式。文档是从数据库中生成;在安装之后,你可以使用 web 界面来增加你的类将其文档化。这个的确有意思,但是它是一种低级的从源代码中分离文档的维护方法,这一点就我来说不是非常方便。

在经受了试验所有这些工具但却得不到怎么成功的挫折之后,直到 pearproject 提出了一种标准的解决方法,我发现了一个与 php 完全无关的可工作的工具在 opensourceprojectsatapple 站点。项目的名字是 headerdoc。就象站点所说的 ";headerdoc 是一种从c或c++头文件的注释中生成 html 的引用文档的工具。它是 用 perl 编写的以便于移植。与 javadoc相似,它允许开发者容易地文档化他们的接口,并且将接口信息输出到 html。";

是的,你看的没错,headerdoc 只支持 c 和 c++。没有其它的语言,但是它不象 javadoc,它大部分依赖写在注释中的标记,所以只要做些小 改动(我会在后面解释)就可以很好的用在 php 上。这些标记同javadoc 很象,headerdoc 标记的一些例子是 @class,@function 和 @var。

ok,让我们现在进入细节吧。首先让我们看一下一个类如何被文档化。

--------------------------------------------------------------------------------

*!@classbagitem

@abstractanitemintheshoppingbag-itisashopitemwithquantity

@discussionabagitemobjectmaybeconstructedwithoutprevious

instantiationofneithershopitemnorproduct

*

--------------------------------------------------------------------------------

文档化一个类。可以在左边的帧选择类的方法。

第一件需要注意的事情是用在打开注释上的风格不完全象 javadoc 注释 ** (一个斜线和两个星号),而是换成 *!(一个斜线,一个星号和一个感叹号)。标记使用也不一样,但是它们以相似的方式工作。例如,第一个标记是 @class 标记,它用于文档化一个类,这个标记跟着类的名字。下 一个标记是 @abstract标记,它是一个可选的标记,用少量词语来描述一个类的含义,同时 @discussion标记是另一个可选的标记,用于进一步的讨论。当然由你来决定是在 @discussion 标记中描述所有的事情还是使用
@abstract 来处理,但是要记住,一般来说,你使用的标记越精确,结果就越好。

文档化函数或方法

成员函数或方法使用 @function 标记被文档化。

--------------------------------------------------------------------------------

*!@functiongetitemingroup

@abstractgetsabagitemofagivengroupandagivenposition

@paramgroupnoint-thedeliverygroupordinalpositioninthebag

@paramposint-thepositionofthebagitemwithinthegroup

@resultobject-thebagiteminagivenpositionofgivengroup

or-1ifitcouldnotbefound

*

--------------------------------------------------------------------------------

文档化一个方法。

@function 标记声明了一个函数并且后面跟着函数或成员函数名。然后你可以象前面一样使用@abstract 和 @discussion 标记。然而还有两个额外的标记。@param 标记用于描述函数的参数;第一个词假设为变量的名字,其它的则为任意的文本描述。我建 议要声明想要的变量类型,尽管php不是一个强类型语言。@result 标记被用于描述返回值。

文档化变量

变量或类变量都使用 @var 标记来描述。在这个标记中,第一个词被认为是变量的名字,同时其它的则为任意的文本描述。象前面一样,我建议写出所期望的变量类型是好的做法。它也是一个文档化所有类变量的好主意。

文档化一个类变量。

--------------------------------------------------------------------------------

*!@varidsessionstring-anuniquesessionidentifier*

var$idsession;

--------------------------------------------------------------------------------

最后接触

--------------------------------------------------------------------------------

*!@headermyprojectname

@abstractavirtualstoretoshoponmars

@discussionthedifference[...]

*

--------------------------------------------------------------------------------

@header 标记用来提供一些关于被文档化的项目或类组的一般性信息。@header标记本身跟着项目的名字,而且可以用 @abstract 标记和 @discussion 标记来补充说明。因为类通常存在于不同的文件中(一个文件一个类,且用类的名字给文件名字是一种好的想 法),你可能想知道应该将 @header标记放在什么地方。答案很让人吃惊,哪都可以。我的建议是:如果它比较长就把它放在一个独立的文件 中,或如果是一个简短的说明就把它放在最重要的类的前面。

如何修改脚本用于 php

从 apple 得到的初始的 headerdoc 脚本是用于 c 或 c++ 头文件的,所以要用在 php 中需要对它做一些小改动。如果你对细节没有兴趣,你可以从这里下载,并且跳过下面部分。

修改源程序所做的唯一的事情就是在主 perl 文件中,使脚本可以接受 .php 和 .php3 后缀。

--------------------------------------------------------------------------------

$diffheaderdoc2html.plusrlocalbinheaderdoc2html

195c195

<;($rootfilename=$filename)=~s.(h|i)$;

---

>;($rootfilename=$filename)=~s.(h|i|php|php3)$;

--------------------------------------------------------------------------------

运行脚本

在安装完脚本之后,假设你的类放在 classes 子目录下,并且你想将生成的文档放在 docs 目录下,你应该执行这个命令:

headerdoc2html-odocsclasses*.php

不幸的是如果存在多个 php 文件,这个脚本有一个坏习惯就是将那些文件分割到不同的目录中去,使得在类的文档中浏览变得很困难。而且因为初始的脚本是 为 cc++ 头文件所写的(头文件中只有类和函数的声明而没有他们的定义),脚本会将函数名下的所有代码输出,直到碰到 ";;";,所以典型的就是代码的第一行。

但是在你好不容易读到现在却感到绝望之前,放松,因为我写了一段简单的脚本来解决这两个问题。

--------------------------------------------------------------------------------

catclasses*.php|sed‘s*{;#{g‘|tr";#";";

";>;docsall.php

headerdoc2html-odocsdocsall.php

rmdocsall.php

--------------------------------------------------------------------------------

如果你想知道为什么我在这里使用 tr 命令而不是都用 sed 来做,原因就是用在仍然用在 redhat6.2上的 sed3.02 版本不处理换行符。应该替换成新的版本 sed3.02a。如果你对 sed 感兴趣,可以看 sedfaq

php 中重新定向到新的页面

如何在php中从一个页面重定向到另外一个页面呢?这里列出了三种办法,供参考。

一、用http头信息

也就是用 php 的 header 函数。php 里的 header 函数的作用就是向浏览器发出由 http 协议规定的本来应该通过 web 服务器的控制指令,例如声明返回信息的类型(";context-type: xxxxxx";),页面的属性(";no cache";, ";expire";)等等。

用http头信息重定向到另外一个页面的方法如下:

<;?

if (isset($url)){

header(";http1.1 303 see other";);[感谢李凌先生]

header(";location: $url";);

exit;

}

?>;

注意一下,";localtion:";后面有一个空格。

二、用html标记

用html标记,就是用meta的refresh标记,举例如下:

<;? if (!isset($url)) exit;?>;

<;html>;

<;head>;

<;meta http-equiv=";refresh"; content=";5; url=<;? echo $url;?>;>;

<;head>;

<;body>;

<;body>;

<;html>;

三、用脚本来实现

举例如下:

<;?

$url=";http:www.phpuser.com";;

echo ";<;!--<;script language=";javascript";>;";;

echo ";location.href=‘$url‘";;

echo ";<;script>;-->;";;

?>;

php 目录管理函数

chdir :

改变目录。

dir :

目录类别类。

closedir :

关闭目录 handle。

opendir :

打开目录 handle。

readdir :

读取目录 handle。

rewinddir :

重设目录 handle。

chdir改变目录。

语法: int chdir(string directory);

返回值: 整数

函数种类: 文件存取

内容说明 本函数用来改变目前 php 执行的目录到新的 directory 目录中。若无法改变则返回 false,成功则返回 true。

dir目录类别类。

语法: new dir(string directory);

返回值: 类

函数种类: 文件存取

内容说明 这是一个类似面向对象的类别类,用来读取目录。当目录参数 directory 打开之后,有二个属性可用:handle 属性就像其它非类的函数所用的 readdir()、rewinddir() 及 closedir();path 属性则配置打开目录后的路径参数。本类有三个方法 (method):read、rewind 与 close。

使用范例

<;?

$d = dir(";etc";);

echo ";handle: ";.$d->;handle.";<;br>;n";;

echo ";path: ";.$d->;path.";<;br>;n";;

while($entry=$d->;read()) {

echo $entry.";<;br>;n";;

}

$d->;close();

?>;

closedir关闭目录。

语法: void closedir(int dir_handle);

返回值: 无

函数种类: 文件存取

内容说明

本函数用来关闭目录资料流的 dir_handle。这个 dir_handle 参数所操作的目录必须要 opendir() 打开的方可使用。

opendir打开目录。

语法: int opendir(string path);

返回值: 整数

函数种类: 文件存取

内容说明:

本函数用来打开目录资料流。返回的整数是可供其它目录函数操作的 handle。

readdir读取目录。

语法: string readdir(int dir_handle);

返回值: 字符串

函数种类: 文件存取

内容说明: 本函数用来读取目录。返回目录中的文件名称,读取不照任何特殊的顺序。

使用范例 本例列出目前目录的所有文件

<;?php

$handle=opendir(‘.‘);

echo ";目录 handle: $handlen";;

echo ";文件:n";;

while ($file = readdir($handle)) {

echo ";$filen";;

}

closedir($handle);

?>;

rewinddir重设目录。

语法: void rewinddir(int dir_handle);

返回值: 无

函数种类: 文件存取

内容说明: 本函数用来重设目录资料流到开始处。

定义 mysql 数据库类

俗话说“好的开始是成功的一半”,而 php+mysql 项目中数据库的操作是重点之一,能否简化数据库操作程序的编写,就成了影响工作效率的关键之一。

  所以小阳并不是一开始就做页面,而是先建立一个“dbclass.php”文件,开始编写操作mysql数据库的类“dbclass”。即在“dbclass.php”中编写以下程序:

<? php

$db_username=";myusername";; 连接数据库的用户名

$db_password=";mypassword";; 连接数据库的密码

$db_database=";mydatabase";; 数据库名

$db_hostname=";localhost";; 服务器地址

class dbclass{ 开始数据库类

var $username;

var $password;

var $database;

var $hostname;

var $link;

var $result;

function dbclass($username,$password,$database,$hostname=";localhost";){

$this->;username=$username;

$this->;password=$password;

$this->;database=$database;

$this->;hostname=$hostname;

}

function connect(){ 这个函数用于连接数据库

$this->;link=mysql_connect($this->;hostname,$this->;username,$this->;password) or die(";sorry,can not connect to database";);

return $this->;link;

}

function select(){ 这个函数用于选择数据库

mysql_select_db($this->;database,$this->;link);

}

function query($sql){ 这个函数用于送出查询语句并返回结果,常用。

if($this->;result=mysql_query($sql,$this->;link)) return $this->;result;

else {

这里是显示sql语句的错误信息,主要是设计阶段用于提示。正式运行阶段可将下面这句注释掉。

echo ";sql语句错误: <font color=red>;$sql<font> <br><br>错误信息: ";.mysql_error();

return false;

}

}

*

  以下函数用于从结果取回数组,一般与 while()循环、$db->;query($sql) 配合使用,例如:

$result=query(";select * from mytable";);

while($row=$db->;getarray($result)){

echo ";$row[id] ";;

}

*

function getarray($result){

return @mysql_fetch_array($result);

}

*

  以下函数用于取得sql查询的第一行,一般用于查询符合条件的行是否存在,例如:

  用户从表单提交的用户名$username、密码$password是否在用户表“user”中,并返回其相应的数组:

if($user=$db->;getfirst(";select * from user where username=‘$username‘ and password=‘$password‘ ";))

echo ";欢迎 $username ,您的id是 $user[id] 。";;

else

echo ";用户名或密码错误!";;

*

function getfirst($sql){

return @mysql_fetch_array($this->;query($sql));

}

*

  以下函数返回符合查询条件的总行数,例如用于分页的计算等要用到,例如:

$totlerows=$db->;getcount(";select * from mytable";);

echo ";共有 $totlerows 条信息。";;

*

function getcount($sql){

return @mysql_num_rows($this->;query($sql));

}

*

  以下函数用于更新数据库,例如用户更改密码:

$db->;update(";update user set password=‘$new_password‘ where userid=‘$userid‘ ";);

*

function update($sql){

return $this->;query($sql);

}

*

  以下函数用于向数据库插入一行,例如添加一个用户:

$db->;insert(";insert into user (userid,username,password) values (null,‘$username‘,‘$password‘)";);

*

function insert($sql){

return $this->;query($sql);

}

function getid(){ 这个函数用于取得刚插入行的id

return mysql_insert_id();

}

}

*

  主要函数就是这些,如果你自己有另外的需要,也可以自己添加上去。因为凡使用该类的都必须连接数据库,下面就连接并选择好数据库吧:

*

$db=new dbclass(";$db_username";,";$db_password";,";$db_database";,";$db_hostname";);

$db->;connect();

$db->;select();

?>;

  ok,数据库的类已经写好了,它不但可以用在目前这个项目中,其他项目的同样适用!只要把“dbclass.php”复制过去就行了。要用本文件的时候只要用语句“inslude_once(";dbclass.php";)”就行,具体语法在编写数据库类时已有举例,不再赘述。

  写好数据库的类后,数据库的操作就方便多了,项目的制作已跨出了重要的第一步。

php dba 函数库

在柏克莱的 bsd 系列操作系统中,有个简单的数据库结构,它以数个文件组成超小型的数据库系统,架构成抽象层 (abstraction layer) 的 dba 数据库。

目前 php 支持的 dba 数据库包括

dbm:柏克莱发展的最早期 dba 数据库。 ndbm:较新且较有弹性的 dba。 gdbm:gnu 发展的 dba, ftp:ftp.gnu.orgpubgnugdbm

db2:由 sleepycat 软件开发的 db2 (非 ibm 的 db2), http:www.sleepycat.com

cdb:这是 qmail 作者开发快速可靠的 dba, http:pobox.com~djbcdb.html

以下是简单的使用范例,当然在使用前,必须先装好 dba。

<;?php

$id = dba_open ( ‘tmptest.db‘ , ‘n‘ , ‘db2‘ );

if(! $id ) {

echo ‘dba_open failedn‘ ;

exit;

}

dba_replace ( ‘key‘ , ‘this is an example!‘ , $id );

if( dba_exists ( ‘key‘ , $id )) {

echo dba_fetch ( ‘key‘ , $id );

dba_delete ( ‘key‘ , $id );

}

dba_close ( $id );

?>;

dba_close :

关闭数据库。

dba_delete :

删除指定资料。

dba_exists :

检查键是否存在。

dba_fetch :

取回指定资料。

dba_firstkey :

取回首笔键值。

dba_insert :

加入资料。

dba_nextkey :

取回下笔键值。

dba_popen :

打开并保持数据库链接。

dba_open :

打开数据库链接。

dba_optimize :

最佳化数据库。

dba_replace :

改动或加入资料。

dba_sync :

数据库同步化。

dba_close关闭数据库。

语法: void dba_close(int handle);

返回值: 无

函数种类: 数据库功能

内容说明 本函数用来将已打开的数据库关闭。参数 handle 为打开数据库时所返回来的代号 id。

参考 dba_popen() dba_open()

dba_delete删除指定资料。

语法: int dba_delete(string key, int handle);

返回值: 整数

函数种类: 数据库功能

内容说明 本函数将删除指定的资料。参数 key 为欲删除的键值 (key)。参数 handle 为打开数据库时所返回来的代号 id。删除成功则返回 true 值。

参考 dba_exists() dba_fetch() dba_insert() dba_replace()

dba_exists检查键是否存在。

语法: boolean dba_exists(string key, int handle);

返回值: 布尔值

函数种类: 数据库功能

内容说明 本函数用来检查指定的键是否存在。参数 key 为待检查的键值 (key)。参数 handle 为打开数据库时所返回来的代号 id。若键存在则返回 true 值。

参考 dba_delete() dba_fetch() dba_insert() dba_replace()

dba_fetch取回指定资料。

语法: string dba_fetch(string key, int handle);

返回值: 字符串

函数种类: 数据库功能

内容说明 本函数取得指定的资料。参数 key 为欲取出资料的键值 (key)。参数 handle 为打开数据库时所返回来的代号 id。返回值即为资料字符串,若取出失败则返回 false。

参考 dba_exists() dba_delete() dba_insert() dba_replace()

dba_firstkey取回首笔键值。

语法: string dba_firstkey(int handle);

返回值: 字符串

函数种类: 数据库功能

内容说明 本函数取得数据库的第一笔键值 (key)。参数 handle 为打开数据库时所返回来的代号 id。返回值即为键值,若取出失败则返回 false。

参考 dba_nextkey()

dba_insert加入资料。

语法: boolean dba_insert(string key, string value, int handle);

返回值: 布尔值

函数种类: 数据库功能

内容说明 本函数将加入资料至数据库中。参数 key 为键值 (key) 字符串。参数 value 为欲加入的资料内容。参数 handle 为打开数据库时所返回来的代号 id。成功则返回 true 值。

参考 dba_exists() dba_fetch() dba_delete() dba_replace()

dba_nextkey取回下笔键值。

语法: string dba_nextkey(int handle);

返回值: 字符串

函数种类: 数据库功能

内容说明 本函数取得数据库的下一笔键值 (key)。参数 handle 为打开数据库时所返回来的代号 id。返回值即为键值,若取出失败则返回 false。

参考 dba_firstkey()

dba_popen

打开并保持数据库链接。

语法: int dba_popen(string path, string mode, string handler);

返回值: 整数

函数种类: 数据库功能

内容说明 本函数用来打开指定的数据库,并保持与数据库连接的状态。参数 path 为数据库的路径及数据库名称,例如 ‘tmpmysitewahaha.db‘。参数 mode 值如下表

属性

说明

r

打开只读既有数据库

w

打开可读写既有数据库

c

打开可读写数据库,若不存在则建立

n

删去现有数据库,若不存在则建立,之后可读写

参数 handler 为打开数据库的种类,有 dbm、ndbm、gdbm、db2 或 cdb 等种类。返回值为数据库的代号 id,若失败则返回 false。 参考 dba_close() dba_open()

dba_open打开数据库链接。

语法: int dba_open(string path, string mode, string handler);

返回值: 整数

函数种类: 数据库功能

内容说明 本函数用来打开指定的数据库。参数 path 为数据库的路径及数据库名称,例如 ‘tmpmysitewahaha.db‘。参数 mode 值如下表

属性

说明

r

打开只读既有数据库

w

打开可读写既有数据库

c

打开可读写数据库,若不存在则建立

n

删去现有数据库,若不存在则建立,之后可读写

参数 handler 为打开数据库的种类,有 dbm、ndbm、gdbm、db2 或 cdb 等种类。返回值为数据库的代号 id,若失败则返回 false。本函数和 dba_popen() 不同的地方在于本函数打开的数据库在 php 程序结束后即关闭,dba_popen() 会保持与数据库连接,待下次再执行,则不必再打开与数据库的链接。

参考 dba_close() dba_popen()

dba_optimize

最佳化数据库。

语法: boolean dba_optimize(int handle);

返回值: 布尔值

函数种类: 数据库功能

内容说明 本函数将数据库最佳化。参数 handle 为打开数据库时所返回来的代号 id。最佳化成功则返回 true 值,反之则返回 false。

参考 dba_sync()

dba_replace改动或加入资料。

语法: boolean dba_replace(string key, string value, int handle);

返回值: 布尔值

函数种类: 数据库功能

内容说明 本函数改动数据库中的资料,若资料不存在则加入。参数 key 为键值 (key) 字符串。参数 value 为欲改动的资料内容。参数 handle 为打开数据库时所返回来的代号 id。成功则返回 true 值。

参考 dba_exists() dba_fetch() dba_delete() dba_insert()

dba_sync数据库同步化。

语法: boolean dba_sync(int handle);

返回值: 布尔值

函数种类: 数据库功能

内容说明 本函数使系统在更新数据库时,能同时写入实体的数据库储存装置 (如硬碟) 之中。参数 handle 为打开数据库时所返回来的代号 id。同步成功则返回 true 值,反之则返回 false。

参考 dba_optimize()

php 中的日期处理(2)

**修改日期

有时我们需要知道 6 小时以后是什么时间,35 天前的日期或者从你最后一次玩 quake3 后已过去多少秒。我们已经知道如何用 mktime() 函数从单独的日期和时间中获得unix的时间戳值。如果我们需要的并非目前日期和时间的 unix 时间戳值,我们该咋办?下面是一些练习可以帮助说明我们后面所要做的。

正如前面所见,mktime() 使用以下参数:小时、分、秒、月、天和年。想想第二节,getdate() 函数可以为我们获得这些参数。

<;?

将目前的时间戳值放入一数组内

$timestamp = time();

echo $timestamp;

echo ";p";;

$date_time_array = getdate( $timestamp);

用mktime()函数重新产生unix时间戳值

$timestamp = mktime($date_time_array [";hours";], $date_time_array[";minutes"; ],$date_time_array[ ";seconds";],$date_time_array [";mon";], $date_time_array[";mday"; ],$date_time_array[ ";year";]);

echo $timestamp;

?>;

看起来有一些令人感到迷惑。我将用一些变量来使上面的程序看起来更容易了解。

<;?

将目前的时间戳值放入一数组内

$timestamp = time();

echo $timestamp;

echo ";p";;

$date_time_array = getdate( $timestamp);

$hours = $date_time_array[ ";hours";];

$minutes = $date_time_array[";minutes";];

$seconds = $date_time_array[ ";seconds";];

$month = $date_time_array[";mon";];

$day = $date_time_array[";mday";];

$year = $date_time_array[";year";];

用mktime()函数重新产生unix时间戳值

$timestamp = mktime($hours ,$minutes, $seconds,$month ,$day,$year);

echo $timestamp;

?>;

现在我们将由 getdate() 所产生的时间戳值放入相对应的名称变量中,所以代码变得相对容易阅读和理解。现在如果我们需要在目前的时间上加上 19 个小时,我们用 $hours+19 代替 mktime() 函数中的 $hours。mktime() 将自动为我们将时间转到第二天。

<;?

将目前的时间戳值放入一数组内

$timestamp = time();

echo strftime( ";%hh%m %a %d %b";,$timestamp);

echo ";p";;

$date_time_array = getdate($timestamp);

$hours = $date_time_array[";hours";];

$minutes = $date_time_array[";minutes";];

$seconds = $date_time_array[";seconds";];

$month = $date_time_array[";mon";];

$day = $date_time_array[";mday";];

$year = $date_time_array[";year";];

用mktime()函数重新产生unix时间戳值

增加19小时

$timestamp = mktime($hours + 19, $minutes,$seconds ,$month, $day,$year);

echo strftime( ";%hh%m %a %d %b";,$timestamp);

echo ";br~e after adding 19 hours";;

?>;

运行后得到:14h58 saturday 03 jun

09h58 sunday 04 jun

~e after adding 19 hours

减少时间也是同样的-你只需要减少相应变量的值即可。得到两个不同时间值的差同样也是非常简单。你所需要做的只是将两个时间值转换为 unix 的时间戳值,然后两者相减即可。两者之差即为两个时间所相隔的秒数。另外一些算法可以很快地将秒转为天、小时、分和秒。

**为php添加dateadd函数

正如在文章一开始我所说的-写本文的原因是因为我在 php 中找不到类似 asp 的 datediff 函数。在介绍完 php 是如何处理日期和时间,让我们将 asp 中常用的两个函数移植到 php。第一个函数是 dateadd。

根据 vbscript 的文档,dateadd(interval,number,date)函数的定义为“返回已添加指定时间间隔的日期。”

inetrval 为表示要添加的时间间隔字符串表达式,例如分或天;number 为表示要添加的时间间隔的个数的数值表达式;date 表示日期。

interval(时间间隔字符串表达式)可以是以下任意值:

yyyy year年

q quarter季度

m month月

y day of year一年的数

d day天

w weekday一周的天数

ww week of year周

h hour小时

n minute分

s second秒

w、y和d的作用是完全一样的,即在目前的日期上加一天,q加3个月,ww加7天。

<;?

function dateadd ($interval, $number, $date) {

$date_time_array = getdate($date);

$hours = $date_time_array[";hours";];

$minutes = $date_time_array[";minutes";];

$seconds = $date_time_array[";seconds";];

$month = $date_time_array[";mon";];

$day = $date_time_array[";mday";];

$year = $date_time_array[";year";];

switch ($interval) {

case ";yyyy";: $year +=$number; break;

case ";q";: $month +=($number*3); break;

case ";m";: $month +=$number; break;

case ";y";:

case ";d";:

case ";w";: $day+=$number; break;

case ";ww";: $day+=($number*7); break;

case ";h";: $hours+=$number; break;

case ";n";: $minutes+=$number; break;

case ";s";: $seconds+=$number; break;

}

$timestamp = mktime($hours ,$minutes, $seconds,$month ,$day, $year);

return $timestamp;}

?>;

我们可以将上面的代码保存为dateadd.inc文件,然后运行以下代码:

<;?

include(‘dateadd.inc‘);

$temptime = time();

echo strftime( ";%hh%m %a %d %b";,$temptime);

$temptime = dateadd(";n"; ,50,$temptime);

echo ";p";;

echo strftime( ";%hh%m %a %d %b";,$temptime);

?>;

我们将得到:15h41 saturday 03 jun

16h31 saturday 03 jun

现在 dateadd 已经完成,那么 datediff 呢?

根据文档,datediff(interval,date1,date2)函数的定义为“返回两个日期之间的时间间隔”。

intervals 参数的用法与 dateadd 函数中的相同。出于避免过于复杂的考虑,我们决定忽略 vbscript 中datediff 函数中其它复杂的参数,即其两个可选的参数变量[firstdayofweek[, firstweekofyear]](它们用于决定星期中第一天是星期天还是星期一和一年中第一周的常数。而且我们只允许 intervals 有以下五个值:";w";(周)、";d";(天)、";h";(小时)、";n";(分钟) 和";s";(秒)。

let‘s see what we can come up with: 下面的代码是我们所需要的:

<;?

function datediff ($interval, $date1,$date2) {

得到两日期之间间隔的秒数

$timedifference = $date2 - $date1;

switch ($interval) {

case ";w";: $retval = bcdiv($timedifference ,604800); break;

case ";d";: $retval = bcdiv( $timedifference,86400); break;

case ";h";: $retval = bcdiv ($timedifference,3600); break;

case ";n";: $retval = bcdiv( $timedifference,60); break;

case ";s";: $retval = $timedifference; break;

}

return $retval;}

?>;

将上面的代码存为datediff.inc文件,然后运行下面的代码:

<;?

include(‘datediff.inc‘);

include(‘dateadd.inc‘);

$currenttime = time();

echo ";current time: ";. strftime(";%hh%m %a %d %b"; ,$currenttime).";br";;

$newtime = dateadd (";n";,50 ,$currenttime);

echo ";time plus 50 minutes: ";. strftime(";%hh%m %a %d %b"; ,$newtime).";br";;

$temptime = datediff (";n";,$currenttime ,$newtime);

echo ";interval between two times: ";.$temptime;

?>;

如果一切顺利,你可以看到以下结果:current time: 16h23 saturday 03 jun

time plus 50 minutes: 17h13 saturday 03 jun

interval between two times: 50

如果你在 unix 机器上运行 php,你必须编译 php 支持 bc 高精度函数。你必须从以下地址 http: www.php.netextranumber4.tar.gz 下载 bc 库,然后将其解压到 php4 的根目录下,重新编译 php,编译时要加上 --enable-bcmath 的选项。(详细说明见 php4 中 readme.bcmath)。php4 的 windows 版本则不需要做任何修补即可直接使用 bc 高精度函数。

现在你已经得到处理日期和时间的函数,剩下的就是如何将其运用到你的 php 程序中。

php 中的日期处理(1)

我正打算用 php 编写一种帮助处理系统。我发现我必须知道处理完最后一位客户的问题后已经过去了多长时间?当我过去用 asp 时解决这个问题相当简单,asp 有相应的函数 datediff 可以给出两个日期间间隔多少月、多少天和多少秒。当我搜寻完 php 手册后我发现 php 并没有类似的函数。

本文包含以下内容:

1、 得到目前的日期和时间-我们有多少种方式?

2、 改变日期显示的方式-日期和时间的显示形式

3、 转换现在的日期为 uni x的时间戳值

4、 改变日期

a. 增加时间

b. 减去时间

c. 找出两日期之间的间隔

5、 为 php 添加 dateadd 函数

6、 为 php 添加 datediff 函数

**得到目前的日期和时间

在 unix 中,时间的表示方式为计算从 1970 年 1 月 1 日零时起所过去的秒数,这称为 unix 时间戳(unix epoch)。

如果我们有这样一段的代码:

<;?

echo time();

?>;

将返回值958905820,而此时的时间为2000年5月21日12时43分。你也许会说这相当不错。当这对我毫无帮助,或者只有一点帮助。在 php 中,对日期处理的函数都必须用到由 time() 返回的时间戳值。同时,由于php 在 unix 和 windows 系统中均使用同样的时间戳值,这就允许你不需要修改代码即可在不同的系统间移植。另外的一个好处是 time() 函数返回的是一个整数,你可以将其作为整数字段或文本字段存入数据库,而不必使用特别的日期时间字段。

你已经基本了解了 unix 的时间戳值,现在让我们来展示它的实际用途。

改变日期显示的方式-日期和时间的显示形式

php 提供两个办法来将 unix 的时间戳值转换成为有用的数据。第一个是 date() 函数。这个函数有两个参数-第一个字符串用于设定你所希望返回的格式,第二个为 unix 的时间戳值。

格式化字符串通过一些简单的特殊格式化字符来显示你所希望看到的格式的日期和时间。假设你希望日期以这样的格式显示“18h01 sunday 21 may”。

我们需要对字符串中的每一部分使用一个特殊格式化字符,你可以从 php 手册中日期和时间函数库中找到。这样的特殊格式化字符数量不少,他们所表示的类似于星期几、月的英文名、用2位或4位数表示的年份,是否是上午(am)或下午(pm)以及其他。对于这个例子我们需要的特殊字符为:

‘h’ -24 小时制的小时

‘i’- 分钟

‘l’- 星期几的英文全名

‘d’- 本月的第几日

‘f’- 月份的英文全名

因此我们的格式化字符串为”hhi l d f”, php代码为:

<;?

echo date (";hhi l d f"; ,time());

?>;

当我们执行这段代码,我们发现我们所得到的结果为:180609 sunday 21 may

这样的结果看起来有些奇怪。让我们再查一下 php 手册,原来’h’所代表的是 12 小时制的小时数。这再次证明了一句真理:“计算机只做你所告诉它该做的,而不是你想要它做的”。我们有两个选择。第一个是在 h 前使用转义字符“”:

echo date (";hhi l d f";, time());

我们得到这样的结果:18h12 sunday 21 may

这正是我们所要的。但如果我们在一个十分复杂的句子中需要包含日期和时间,我们是否需要对每个字符使用转义字符?

答案当然是不。我们使用另一个函数strftime()。

strftime ()有两个好处。第一个好处我们并不在本文讨论范围内-如果你使用 setlocale() 函数,你可以通过 strftime 得到相应语言的月份的名称。另外的一个好处是你可以将特别的日期和时间的格式化字符包含在你的字符串中。这同时也意味着无论你是否要学习 date() 函数的所有特殊格式化字符,你都必须学习一整套完全不同的格式化字符。

strftime()工作的方式和 date() 没有什么不同,除了特殊格式化字符的前面必须添加一个百分号 %。如果用 strftime() 函数,前面例子的代码如下:

<;?

echo strftime (";%hh%m %a %d %b"; ,time());

?>;

结果为:18h24 sunday 21 may

这也许看起来将简化繁,但考虑一下如果你所需要的显示的为 ";today is sunday 21 may 2000. the time is somewhere close to 18h24."; 我想使用 date() 函数无疑令人感到厌烦。

在开始的时候,我提及我们有两种方式可以从 unix 时间戳值中得到有用的数据。我们刚刚了解了 date() 和strftime()。另一个 getdate()。这个函数只需要 unix 的时间戳值作为参数,而函数的返回值为日期和时间的数组。

下面是一个例子:

<;?

$date_time_array = getdate (time());

echo $date_time_array[ ";weekday";];

?>;

返回的结果为:sunday

除了 ";weekday";,该数组的其他部分为:

";seconds"; ╟秒

";minutes"; ╟分

";hours"; ╟小时

“mday"; - 本月的第几天

";wday"; -本周的第几天(数字)

";mon"; -月(数字)

";year"; ╟年

";yday"; - r本年的第几天(数字)

";month"; -月份全名

我们现在可以得到容易辨认的日期和时间。那么其他呢?

**转换现在的日期为unix的时间戳值

通常你必须处理一些日期或时间格式的数据。打开 m$ 的一个 access 数据库,所有的日期都以yyyymmdd 的格式存储,加入目前的日前即为 20000527。mktime() 函数可以将一个时间转换成 unix 的时间戳值。

函数的格式为:int mktime(int hour, int minute, int second, int month, int day, int year, int [is_dst] );

从左往右你必须提供小时、分、秒、月、天和年。最后一个参数用于指定你是否处于夏令时,此参数是可选的,所以我们将忽略它。

代码如下:

<;?

echo mktime (0, 0,0 ,5, 27,2000 );

?>;

由于不知道小时、分和秒同时这些参数必须填写,我将其设置为0。设置为0意味着时间为午夜。

<;?

$access_date = ";20000527";;

explode()函数用一个字符串作为分界来分解另一个字符串。这个例子$access_date通过字符串””来分解

$date_elements = explode(";"; ,$access_date);

此时

$date_elements[0] = 2000

$date_elements[1] = 5

$date_elements[2] = 27

echo mktime (0, 0,0 ,$date_elements [1], $date_elements[ 2],$date_elements [0]);

?>;

我们看一个比从access数据库单纯获得日期更复杂的情况,我们得到一个以下格式的日期和时间:20000527 02:40:21 pm

<;?

来自access的字符串

$date_time_string = ";20000527 02:40:21 pm";;

将字符串分解成3部分-日期、时间和上午下午

$dt_elements = explode("; "; ,$date_time_string);

分解日期

$date_elements = explode(";"; ,$dt_elements[ 0]);

分解时间

$time_elements = explode(";:"; ,$dt_elements[ 1]);

如果是下午,我们将时间增加12小时以便得到24小时制的时间

if ($dt_elements [2]== ";pm";) { $time_elements[ 0]+=12;}

输出结果

echo mktime ($time_elements [0], $time_elements[ 1], $time_elements[ 2], $date_elements[1], $date_elements[2], $date_elements[0]);

?>;

php 日期与时间函数库

checkdate :

验证日期的正确性。

date :

将服务器的时间格式化。

strftime :

将服务器的时间本地格式化。

getdate :

获得时间及日期信息。

gettimeofday :

取得目前时间。

gmdate :

取得目前与 gmt 差后的时间。

easter_date :

计算复活节日期。

easter_days :

计算复活节与三月廿一日之间日期数。

mktime :

取得 unix 时间戳记。

gmmktime :

取得 unix 时间戳记的格林威治时间。

time :

取得目前时间的 unix 时间戳记。

microtime :

取得目前时间的 unix 时间戳记的百万分之一秒值。

checkdate验证日期的正确性。

语法: int checkdate(int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明 若日期是有效的则返回 true,若日期有问题,则返回 false。本函数可以用来检查日期是否有效。有效范围如下:

年 为 0 至 32767 年

月 为 1 至 12 月

日 则随着月份及闰年变化

date将服务器的时间格式化。

语法: string date(string format, int [timestamp]);

返回值: 字符串

函数种类: 时间日期

内容说明 返回值的字符串依配置的格式来决定。若有传入时间戳记值,则将时间戳记格式化返回;若无传入时间戳记值,则将目前服务器的时间格式化返回。要将日期转为 其它的语系格式,应使用setlocale() 及 strftime() 二个函数。字符串格式化的选项如下:

a - ";am"; 或是 ";pm";

a - ";am"; 或是 ";pm";

d - 几日,二位数字,若不足二位则前面补零; 如: ";01"; 至 ";31";

d - 星期几,三个英文字母; 如: ";fri";

f - 月份,英文全名; 如: ";january";

h - 12 小时制的小时; 如: ";01"; 至 ";12";

h - 24 小时制的小时; 如: ";00"; 至 ";23";

g - 12 小时制的小时,不足二位不补零; 如: ";1"; 至 12";

g - 24 小时制的小时,不足二位不补零; 如: ";0"; 至 ";23";

i - 分钟; 如: ";00"; 至 ";59";

j - 几日,二位数字,若不足二位不补零; 如: ";1"; 至 ";31";

l - 星期几,英文全名; 如: ";friday";

m - 月份,二位数字,若不足二位则在前面补零; 如: ";01"; 至 ";12";

n - 月份,二位数字,若不足二位则不补零; 如: ";1"; 至 ";12";

m - 月份,三个英文字母; 如: ";jan";

s - 秒; 如: ";00"; 至 ";59";

s - 字尾加英文序数,二个英文字母; 如: ";th";,";nd";

t - 指定月份的天数; 如: ";28"; 至 ";31";

u - 总秒数

w - 数字型的星期几,如: ";0"; (星期日) 至 ";6"; (星期六)

y - 年,四位数字; 如: ";1999";

y - 年,二位数字; 如: ";99";

z - 一年中的第几天; 如: ";0"; 至 ";365";

其它不在上列的字符则直接列出该字符。

使用范例,范例一:

<;?

print(date( ";l ds of f y h:i:s a"; ));

print(";july 1, 2000 is on a "; . date(";l";, mktime(0,0,0,7,1,2000)));

?>;

范例二:

<;?

$tomorrow = mktime(0,0,0,date(";m";) ,date(";d";)+1,date(";y";));

$lastmonth = mktime(0,0,0,date(";m";)-1,date(";d";), date(";y";));

$nextyear = mktime(0,0,0,date(";m";), date(";d";, date(";y";)+1);

?>;

参考 gmdate() mktime()

strftime将服务器的时间本地格式化。

语法: string strftime(string format, int [timestamp]);

返回值: 字符串

函数种类: 时间日期

内容说明 返回值的字符串依配置的格式来决定。若有传入时间戳记值,则将时间戳记格式化返回;若无传入时间戳记值,则将目前服务器的时间本地格式化返回。月份或者星期名称随着本地语系配置 setlocale() 的不同而改变。

返回的字符串可以依下列的格式而定:

%a 星期几的缩写。

%a 星期几的全名。

%b 月份名称的缩写。

%b 月份名称的全名。

%c 本地端日期时间较佳表示字符串。

%d 用数字表示本月的第几天 (范围为 00 至 31)。

%h 用 24 小时制数字表示小时数 (范围为 00 至 23)。

%i 用 12 小时制数字表示小时数 (范围为 01 至 12)。

%j 以数字表示当年度的第几天 (范围为 001 至 366)。

%m 月份的数字 (范围由 1 至 12)。

%m 分钟。

%p 以 ‘am‘ 或 ‘pm‘ 表示本地端时间。

%s 秒数。

%u 数字表示为本年度的第几周,第一个星期由第一个周日开始。

%w 数字表示为本年度的第几周,第一个星期由第一个周一开始。

%w 用数字表示本周的第几天 ( 0 为周日)。

%x 不含时间的日期表示法。

%x 不含日期的时间表示法。

%y 二位数字表示年份 (范围由 00 至 99)。

%y 完整的年份数字表示,即四位数。

%z 时区或名称缩写。

%% % 字符。

使用范例

<;?php

setlocale (";lc_time";, ";c";);

print(strftime(";%a in finnish is ";));

setlocale (";lc_time";, ";fi";);

print(strftime(";%a, in french ";));

setlocale (";lc_time";, ";fr";);

print(strftime(";%a and in german ";));

setlocale (";lc_time";, ";de";);

print(strftime(";%a.n";));

?>;

参考 setlocale() mktime()

getdate获得时间及日期信息。

语法: array getdate(int timestamp);

返回值: 数组

函数种类: 时间日期

内容说明 返回数组的元素包括下列的项目:

";seconds"; - 秒

";minutes"; - 分

";hours"; - 时

";mday"; - 当月的第几天

";wday"; - 当周的第几天数字

";mon"; - 月份数字

";year"; - 年,数字

";yday"; - 当年的第几天数字; 如: ";299";

";weekday"; - 星期几全名; 如: ";friday";

";month"; - 月份全名; 如: ";january";

gettimeofday取得目前时间。

语法: array gettimeofday(void);

返回值: 数组

函数种类: 时间日期

内容说明 返回数组的元素包括下列的项目:

";sec"; - 秒

";usec"; - 百万分之一秒

";minuteswest"; - 格林威治时间的分

";dsttime"; - 目的的时区

gmdate取得目前与 gmt 差后的时间。

语法: string gmdate(string format, int timestamp);

返回值: 字符串

函数种类: 时间日期

内容说明 本函数与 date() 函数相似,不同的是本函数返回与格林威治标准时间 (greenwich mean time, gmt) 时间差后的时间

使用范例

<;?php

echo date( ";m d y h:i:s";,mktime(0,0,0,1,1,1998) );

echo gmdate( ";m d y h:i:s";,mktime(0,0,0,1,1,1998) );

?>;

若执行本范例的机器在芬兰 (finland, gmt +0200),返回的结果为:

jan 01 1998 00:00:00

dec 31 1997 22:00:00

参考 date() mktime() gmmktime()

easter_date计算复活节日期。

语法: int easter_date(int [year]);

返回值: 整数

函数种类: 时间日期

内容说明:

输入某一年份,则以 unix 时间戳记的格式返回该年的复活节日期,若没有输入年份,则计算当年的日期。值的注意的是输入的年份必需在公元 1970 至 2037 年之间,否则无法计算。

使用范例

<;?

echo date(";m-d-y";, easter_date(1999));

echo date(";m-d-y";, easter_date(2000));

echo date(";m-d-y";, easter_date(2001));

?>;

返回结果为

apr-04-1999

apr-23-2000

apr-15-2001

easter_days计算复活节与三月廿一日之间日期数。

语法: int easter_days(int [year]);

返回值: 整数

函数种类: 时间日期

内容说明 输入某一年份,则以计算该年复活节与三月二十一日之间的日期数,若没有输入年份,则以当年计算。这个函数可以用来替代 easter_date() 1970-2037 年外范围无法计算的问题。

使用范例

<;?

echo easter_days(1999);

echo easter_days(1492);

echo easter_days(1913);

?>;

返回结果为:

14 (44)

32 (422)

2 (323)

参考 easter_date()

mktime取得 unix 时间戳记。

语法: int mktime(int hour, int minute, int second, int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明:

输入一个时间,则返回 unix 时间戳记的长整数。

使用范例

<;?

echo date( ";m-d-y";, mktime(0,0,0,12,32,1997) );

echo date( ";m-d-y";, mktime(0,0,0,13,1,1997) );

echo date( ";m-d-y";, mktime(0,0,0,1,1,1998) );

?>;

参考 date() time()

gmmktime取得 unix 时间戳记的格林威治时间。

语法: int gmmktime(int hour, int minute, int second, int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明: 输入一个时间,则返回 unix 的格林威治时间戳记的长整数。

time取得目前时间的 unix 时间戳记。

语法: int time(void);

返回值: 整数

函数种类: 时间日期

内容说明 返回目前时间的戳记值。

参考 date()

microtime取得目前时间的 unix 时间戳记的百万分之一秒值。

语法: string microtime(void);

返回值: 字符串

函数种类: 时间日期

内容说明 返回目前时间的百万分之一秒戳记值。若操作系统没有提供 gettimeofday() 的系统呼叫函数,则本函数亦无效。

参考 time()

php 中的日期和时间(2)

以下是处理表单的函数:

<;?php

function process_form() {

global $dotw;

global $month;

global $day;

global $year;

$timestamp = mktime(0,0,0,$month,$day,$year);

$next_dotw = ‘‘;

$next_timestamp = $timestamp;

while ($next_dotw != $dotw) {

$next_timestamp += 86400;

$next_dotw = date(‘l‘,$next_timestamp);

}

$formatted_first = date(‘f d, y‘,$timestamp);

$formatted_next = date(‘f d, y‘,$next_timestamp);

echo ";the first $dotw after $formatted_first is $formatted_next.";;

}

?>;

首先,此代码将所得到的日期转化为 unix 时间戳形式。如果我们需要更为谨慎的话,可以加入某些代码以确保所得到的日期在合法的日期范围内,不过在这此我们暂时没有必要这样做。

当我们要寻找的“下一天”的星期数不是用户所输入的一个星期数时,循环继续。当不一样时,日期所代表的总秒数就会被增加(同样是 86400 秒 =24 小时 *60 分钟 *60 秒),然后那个秒数所代表的星期数就会被重新计算。

一旦星期数一致,process_form() 函数就会输出一行正确消息:

the first sunday after june 25, 1999 is june 27, 1999.

我们同样需要那个熟悉的主循环将这些函数捆绑在一起:

<;?php

if (empty($stage)) { display_form(); }

else { process_form(); }

?>;

日期处理代码有时需要更为复杂以处理夏令时及不同时区,不过 date() 以及 mktime() 函数都是处理unix 时间戳变换的基本工具,它们在算法上操作简单,且以直观方式表达日期与时间。函数 date() 以及mktime() 以机器所在时区来对时间进行操作。如果想使用格林威治时间(gmt),则可使用函数 gmdate() 以及 gmmktime()。

例如,对于一台处于美国东部夏令时的计算机(落后格林威治时间四小时):

<;?php

$today = mktime(12,0,0,6,25,1999);

echo ‘here it is ‘.date(‘g:i:s a, f d, y‘,$today);

echo ‘‘;

echo ‘in gmt it is ‘.gmdate(‘g:i:s a, f d, y‘,$today);

?>;

将显示

here it is 12:00:00 pm, june 25, 1999

in gmt it is 4:00:00 pm, june 25, 1999

php 中的日期和时间 (1)

php有很多便于使用的函数以显示及处理日期。

要以某种特定格式显示日期或时间,可使用 date() 函数。它有两个参数:如何显示日期的格式以及代表你所要显示日期的时间戳。这个时间戳必须是先前所提到的从 1970 年起算的总秒数(如果你要使用当前时间可使用 time() 函数,此函数会返回“现在”的时间戳)。date() 有很多格式选项,如同 c 语言中的strftime() 函数或 perl 语言的 posix::strftime() 函数一样。

<;?php

$birthday_stamp = mktime(19,45,0,3,10,1975);

$birthday_formatted = date(‘f d, y - g:ia‘,$birthday_stamp);

echo ";david was born on $birthday_formatted.";

?>;

会显示:david was born on march 10, 1975--7:45 p.m.

当然,如果你需要某已知的特定日期,这种复杂的格式函数并不会十分有用。因为你事先已经知道你的格式将会是什么。当在处理需要用户选择某日期的表单输出部分时,这些函数会比较有用:

<;select name=";when";>;

<;?php

$d = time();

for ($i = 0; $i <; 10; $i++) {

echo ‘<;option value=";‘.$d.‘";>;‘.date(‘f d‘,$d);

$d += 86400;

}

?>;

<;select>;

以上会输出一个单选框,其中有十个选项——今天及以后九天。在程序循环开始之前,我们将当前时间存放于变量$d中。每一个<; option>;值会被显示,而其中的值会是以 unix 时间戳计算,且所显示出来的文字设定为月、日(“july 27”、“july 28”等等)。在显示值后,变量 $d 会被加上 86,400(是一天二十四小时的总秒数——24 小时 *60 分钟 *60 秒)。

通过结合 mktime() 及 date() 函数,你就可以得出关于某特定用户输入日期的相关信息。那如果要寻找从某特定日期算起的第一个星期天(或者一周中的任意一天)呢?首先,先编写一个会输出适当格式的函数:

<;?php

functiondisplay_form() {

global $php_self;

$dotw = array(‘sunday‘,‘monday‘,‘tuesday‘,‘wednesday‘,‘thursday‘,

‘friday‘,‘saturday‘);

$months = array( 1 =>; ‘january‘,‘february‘,‘march‘,‘april‘,‘may‘,‘june‘,

‘july‘,‘august‘,‘september‘,‘october‘,‘november‘,‘december‘);

?>;

<;form target=";<;?php echo $php_self; ?>;"; method=get>;

find the first

<;select name=";dotw";>;

<;?php

for ($i = 0; $i <; 7; $i++) {

echo ";<;option>; $dotw[$i]";;

}

echo ‘<;select>; after <;select name=";month";>;‘;

for ($i = 1; $i <;= 12; $i++) {

echo ";<;option value=";$i";>; $months[$i]";;

}

echo ‘<;select>; <;select name=";day";>;‘;

for ($i = 1; $i <;= 31; $i++) {

echo ";<;option>; $i";;

}

echo ‘<;select>;, <;select name=";year";>;‘;

$start_year = date(‘y‘) - 10;

$end_year = $start_year + 20;

for ($i = $start_year; $i <;= $end_year; $i++) {

echo ";<;option>; $i";;

}

echo ‘<;input type=";hidden"; name=";stage"; value=";process";>;‘;

echo ‘<;select>; <;input type=";submit"; value=";do it!";7>;<;form>;‘;

}

?>;

这当中含有一些函数是我们到目前为止还没讨论过的。$months 数组写得略微不同,因为需要让一月份索引为 1,而非 0。另外,由程序自动产生此表单要比将所有这个表单元素的值一一手动列出要更为轻松,因此,顶端的表单开始部分是 display_form() 函数中唯一不是属于 php 模式的。此外,使用数据(“y”)设置变量 $start_year 以及变量 $end_year 能够方便处理从今年算起十年前后的时间范围。

用 php 连接数据库 (2)

if(ora_errorcode($in_cur)){

echo ";oracle code - ";.ora_error($in_cur).";<;br>;n";;

ora_logoff($conn);

exit;

}

return;

}

function exequery($w_qry,$conn){

$cursor=ora_open($conn); printoraerr($cursor,$conn);

ora_parse($cursor,$w_qry,0); printoraerr($cursor,$conn);

ora_exec($cursor); printoraerr($cursor,$conn);

$numrows=0;

$w_numcols=ora_numcols($cursor);

显示头部

echo ";

<;table width=";100%"; border=";0"; cellspacing=";1";cellpadding=";2";>;

<;tr>;n";;

for ($i=0;$i<;$w_numcols;$i++){

$align=(ora_columntype($cursor,$i)==";number";)?";right";:";left";;

echo ";t<;th valign=top align=$align>;";.ora_columnname($cursor,$i).";<;th>;n";;

echo ";<;tr>;n";;

while(ora_fetch($cursor)){

echo ";<;tr>;n";;

for ($i=0;$i<;$w_numcols;$i++){

$align=(ora_columntype($cursor,$i)==";number";)?";right";:";left";;

if(ora_columntype($cursor,$i)==";long";)

echo ";<;td valign=top align=$align>;<;pre>;";.

ora_getcolumn($cursor,$i).";<;pre>;<;td>;n";;

}

else{

echo ";<;td valign=top align=$align>;";.ora_getcolumn($cursor,$i).";<;td>;n";;

printoraerr($cursor,$conn);

}

$numrows++;

echo ";<;tr>;n";;

}

if ($numrows==0){

echo ";<;tr>;<;td colspan=";$w_numcols";>;<;b>;query

returned no records

<;b>;<;td>;<;tr>;n";;

}

else{

echo ";<;tr>;n";;

echo ";<;th colspan=";";.($w_numcols-1).";"; align=right>;count<;th>;n";;

echo ";<;th align=right>;$numrows<;th>;n";;

echo ";<;tr>;n";;

}

echo ";<;table>;n";;

ora_close($cursor);

return;

}

主程序

if(!($conn=ora_logon(";user@sid";,";password";))){

echo ";error: cannot connect to databasen";;

exit;

}

$qry=";select

deptno ";dept";

,empno ";emp";

,empnm ";name";

,salary ";salary";

from

employee

order by 1,2";;

exequery($qry);

ora_logoff($conn);

?>;

基于 http 的 oracle 登录

将以下代码加在php页面代码之前以确认oracle登录。注意你必须正确设定$ sid。

<;?

if(!isset($php_auth_user)){

header(";www-authenticate: basic realm=";$sid";";);

header(";http1.0 401 unauthorized";);

$title=";login instructions";;

echo ";<;blockquote>;

you are not authorized to enter the site

<;blockquote>; n";;

exit;

}

else{

if (!($conn=ora_logon(";$php_auth_user@$sid";,$php_auth_pw))){

header(";www-authenticate: basic realm=";$sid";";);

header(";http1.0 401 unauthorized";);

$title=";login instructions";;

echo ";<;blockquote>;you are not authorised to enter the site<;blockquote>; n";;

exit;

}

}

?>;

用 php 连接数据库 (1)

通过 ph p你可以轻松的连接到数据库,请求数据并将其显示在你的 web 站点中,甚至修改数据库中的数据。mysql 是一种很流行的数据库,并且在互联网中有许多有关 php 与 mysql 的教程。mysql 是免费的,这一点也许就吸引了不少人。由于其广泛应用,我就不想在这里赘述 mysql 的使用方法了。oracle 被大量在企业应用中采用,因此我们就利用 oracle 来介绍 php 与数据库的连接。我们当然不会提及 oracle 数据库的设计原理,原因是这已经超出了我们的讨论范围。

php 提供了两套函数与 oracle 连接,分别是 ora_和 oci 函数。其中 ora_函数略显陈旧。oci 函数更新据说更好一些。两者的使用语法几乎相差无几。如前所述,你的 php 安装选项应该可以支持两者的使用。

想获得更多有关在 microsoft windows 平台上安装支持php3的apache服务器的知识以及更多有关oracle数据库的知识,请查阅以下url:www.csoft.net~vsbabuarticlesoraphp.html。

连接

<;?

if ($conn=ora_logon(";user@tnsname";,";password";)){

echo ";<;b>;success ! connected to database<;b>;n";;

}

else{

echo ";<;b>;failed :-( could not connect to database<;b>;n";;

}

ora_logoff($conn);

phpinfo();

?>;

以上代码使用 tnsname (在你的 tnsnames.ora 文件中指明)定义的 oracle 数据库名称、用户名称和密码连接数据库。在成功连接的基础上,ora_logon 函数返回一个非零的连接id并储存在变量 $conn 中。

查询

假设与数据库已经连接就绪,下面我们就来实际的应用对数据库的查询。下面的代码演示了一个连接并查询的典型例子:

<;?

连接数据库并执行查询

function printoraerr($in_cur){

检查oracle是否出错,如果存在错误则显示

当指针被激活时每次请求oracle后调用该函数

if(ora_errorcode($in_cur)){

echo ";oracle code - ";.ora_error($in_cur).";n";;

return;

}

}

** 主程序 *

if (!($conn=ora_logon(";user@tnsname";,";password";))){

echo ";connection to database failedn";;

exit;

}

echo ";connected as connection - <;b>;$conn<;b>;<;br>;n";;

echo ";opening cursor ...<;br>;n";;

$cursor=ora_open($conn); printoraerr($cursor);

echo ";opened cursor - <;b>;$cursor<;b>;<;br>;n";;

$qry=";select user,sysdate from dual";;

echo ";parsing the query <;b>;$qry<;b>; ...<;br>;n";;

ora_parse($cursor,$qry,0); printoraerr($cursor);

echo ";query parsed <;br>;n";;

echo ";executing cursor ...<;br>;n";;

ora_exec($cursor); printoraerr($cursor);

echo ";executed cursor<;br>;n";;

echo ";fetching cursor ...<;br>;n";;

while(ora_fetch($cursor)){

$user=ora_getcolumn($cursor,0); printoraerr($cursor);

$sysdate=ora_getcolumn($cursor,1); printoraerr($cursor);

echo "; row = <;b>;$user, $sysdate <;b>;<;br>;n";;

}

echo ";fetched all records<;br>;n";;

echo ";closing cursor ...<;br>;n";;

ora_close($cursor);

echo ";closed cursor<;br>;n";;

echo ";logging off from oracle... <;br>;n";;

ora_logoff($conn);

echo ";logged off from oracle <;br>;n";;

?>;

显示结果

以下代码演示了怎样查询数据库并将结果输出:

<;?

function printoraerr($in_cur, $conn){

检查oracle是否出错,如果存在错误则显示,当指针被激活时每次请求oracle后调用该函数

if it encountered an error, we exit immediately

用 php 控制缓冲区

php4.0 提供了一个输出缓冲函数集合。输出缓冲支持允许你写包裹函数功能压缩缓冲区。在 php4 的输出缓冲支持允许 html 头信息存放, 无论 html 的正文是否输出。但在 php 中,头信息( (header(), content type, and cookies )不采用缓冲。

在使用 php 的过程中不免要使用到 header 和 setcookie 两个函数,这两个函数会发送一段文件头信息给浏览器,但是如果在使用这两个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错,提示信息如下:“header had all ready send by”#在 php 4.0 里面加入了缓冲区控制的几个函数,使用这些函数可以帮我们解决很多问题。

函数名称 函数格式 功能 说明

flush flush()

输出缓冲区内的内容并且删除缓冲区。 这个函数经常使用,效率很高。

ob_start void ob_start(void)

打开输出缓冲区。 当缓冲区激活时,所有来自php程序的非文件头信息均不会发送,而是保存在内部缓冲区。为了输出缓冲区的内容,可以使用ob_end_flush()或者使用ob_end_clean()来输出缓冲区的内容。

ob_get_contents string ob_get_contents(void)

返回内部缓冲区的内容。 这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 false 。

ob_get_length int ob_get_length(void)

返回内部缓冲区的长度。 这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激活。则返回 false。

ob_end_flush void ob_end_flush(void)

发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。 这个函数发送输出缓冲区的内容(如果有的话)。

ob_end_clean void ob_end_clean(void)

删除内部缓冲区的内容,并且关闭内部缓冲区。 这个函数不会输出内部缓冲区的内容!

ob_implicit_flush void ob_implicit_flush ([int flag])

打开或关闭绝对刷新 使用过perl的人都知道$|=x的意义,这个字符串可以打开关闭缓冲区,而ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出。

二、实例分析:

1、用缓冲区控制的函数防止文件头发送信息出错。

<;? php提示符

ob_start(); 打开缓冲区

echo ";welcome n";; 输出

header(";location:next.php";); 把浏览器重定向到next.php

?>;

如果去掉 ob_start,php 就会提示在文件的第4行出错,出错信息为“header had all ready send by”,但是加上 ob_start,就不会提示出错,原因是当打开了缓冲区,echo 后面的字符不会输出到浏览器,而是保留在服务器的缓冲区中,直到你使用 flush 或者 ob_end_flush 才会输出,所以并不会出现文件头已输出的错误!

2、保存输出(这是一个很经典的用途)。

假如你想知道客户端的屏幕输出信息像函数的输出结果等,而且这个输出信息会因客户端的不同而不同。我们可以用函数 <;? phpinfo(); ?>; 得到服务器的设置信息,但是如果想要保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了缓冲区的控制,我们可以轻松的解决。

<;?

ob_start(); 打开缓冲区

phpinfo(); 使用phpinfo函数

$info=ob_get_contents(); 得到缓冲区的内容并且赋值给$info

$file=fopen(‘phpinfo.txt‘,‘w‘); 打开文件phpinfo.txt

fwrite($file,$info); 写入信息到phpinfo.txt

fclose($file); 关闭文件phpinfo.txt

?>;

用以上的方法,就可以把不同用户的 phpinfo 信息保存下来,这在以前恐怕没有办法办到!同样,用缓冲区的方法可以保存一般方法难以完成的任务,这其实上就是将一些“过程”转化为“函数”的方法。

使用 php 制作计数器

php的功能非常强大,你可以利用它做几乎任何事。不需要复杂的变量和代码,你就可以非常迅速地做出漂亮的计数器来。下面,就让我们一步一步的来做。

其实,计数器的原理大家都知道,首先,确定一个记录文件,例如 counter.txt 或 counter.log,每一次访问这个页面,就对这个文件加 1,然后把结果显示出来。因此,我们的 php 代码开始应该是这样的:

<;?php

$countfile = ";jscounter.inf";;

定义计数器写入的文件是当前目录下js目录中counter.inf,然后我们应当测试该文件能否打开

if (($fp = fopen($countfile, ";r+";)) == false) { 用读写模式打开文件,若不能打开就退出

printf (";open file %s failed!";,$countfile);

exit;

}

else{

如果文件能够正常打开,就读入文件中的数据,假设是1

$count = fread ($fp,10);读取10位数据

$count = $count + 1;

count ++

fclose ($fp);

关闭当前文件

$fp = fopen($countfile, ";w+";)

以覆盖模式打开文件

fwrite ($fp,$count);

写入加1后的新数据

fclose ($fp);

并关闭文件

}

这时,整个计数工作就完成了,如果只是简单的文字计数的话,在这里就可以输出变量 $count 的值。下面是将 $count 转换为图片模式的代码:

$fp = fopen ($countfile, ";r";); 以只读模式打开文件

$array_count = 1; 定义一个表示数组元素位置的变量,下面要用

while (! feof($fp)) {

$current_number = fgetc($fp);

$counter_array[$array_count] = $current_number;

$array_elements = count ($counter_array);

$array_count = $array_count + 1;

}

上面这个 while 循环的作用是把每一位数分离出来。它从 counter.inf 中由左到右逐位读取数值,并依次写入一个叫 counter_array 的数组中,这个数组的索引是从 1 开始的($array_count)。如果现在counter.inf 中的数字是 158,那么数组 $counter_array[] 就像这样:$counter_array[1] = 1、$counter_array[2] = 5、$counter_array[3] = 8。有了上面这些工作,我们就可以方便地显示不同的数字图片了,显示代码如下:

echo (";<;table border=($%$43%^#asd#2@$#f$%^)0($%$43%^#asd#2@$#f$%^) height=($%$43%^#asd#2@$#f$%^)5($%$43%^#asd#2@$#f$%^) align=($%$43%^#asd#2@$#f$%^)center($%$43%^#asd#2@$#f$%^)>;<;tr>;<;td bgcolor=($%$43%^#asd#2@$#f$%^)#bab389($%$43%^#asd#2@$#f$%^) align=($%$43%^#asd#2@$#f$%^)center($%$43%^#asd#2@$#f$%^)>;欢迎您,第";);

for ($array_id = 1;$array_id <; $array_elements; ++ $array_id) {

echo (";<;img src=($%$43%^#asd#2@$#f$%^)imagescounter$counter_array[$array_id].gif($%$43%^#asd#2@$#f$%^) align=absmiddle>;";);

}

echo (";位客人<;td>;<;tr>;<;table>;";);

}

上面的代码很简单,就是画一个表格,并依次在表格中显示所需的图片。在 imagescounter 目录下有0.gif 至 9.gif 十张图片,for 循环遍历数组,从高位到低位给出每一位数相应的图片,直到数组的尾部。这样,一个完整的计数器就完成了。

php cookie 及其使用(2)

上一部分讲了有关 cookie 的技术背景,这部分来说说在php里如何设置、使用、删除 cookie,及cookie 的一些限制。php 对 cookie 支持是透明的,用起来非常方便。

1、设置 cookie

php 用 setcookie 函数来设置 cookie。必须注意的一点是:cookie 是 http 协议头的一部分,用于浏览器和服务器之间传递信息,所以必须在任何属于 html 文件本身的内容输出之前调用 cookie 函数。

setcookie 函数定义了一个 cookie,并且把它附加在 http 头的后面,setcookie 函数的原型如下:

int setcookie(string name, string value, int expire, string path, string domain, int secure);

除了 name 之外所有的参数都是可选的。value,path,domain 三个参数可以用空字符串代换,表示没有设置;expire 和 secure 两个参数是数值型的,可以用0表示。expire 参数是一个标准的unix时间标记,可以用time() 或 mktime() 函数取得,以秒为单位。secure 参数表示这个 cookie 是否通过加密的https协议在网络上传输。

当前设置的 cookie 不是立即生效的,而是要等到下一个页面时才能看到.这是由于在设置的这个页面里cookie 由服务器传递给客户浏览器,在下一个页面浏览器才能把 cookie 从客户的机器里取出传回服务器的原因。

在同一个页面设置 cookie,实际是从后往前,所以如果要在插入一个新的 cookie 之前删掉一个,你必须先写插入的语句,再写删除的语句,否则可能会出现不希望的结果。

来看几个例子:

简单的:

setcookie(";mycookie";, ";value of mycookie";);

带失效时间的:

setcookie(";withexpire";, ";expire in 1 hour";, time()+3600);3600秒=1小时

什么都有的:

setcookie(";fullcookie";, ";full cookie value";, time()+3600, ";forum";, ";.phpuser.com";, 1);

这里还有一点要说明的,比如你的站点有几个不同的目录,那么如果只用不带路径的 cookie 的话,在一个目录下的页面里设的 cookie 在另一个目录的页面里是看不到的,也就是说,cookie 是面向路径的。实际上,即使没有指定路径,web 服务器会自动传递当前的路径给浏览器的,指定路径会强制服务器使用设置的路径。解决这个问题的办法是在调用 setcookie 时加上路径和域名,域名的格式可以是“www.phpuser.com”,也可是 “.phpuser.com”。

setcookie 函数里表示 value 的部分,在传递时会自动被 encode,也就是说,如果 value 的值是“test value”在传递时就变成了“test%20value”,跟 url 的方法一样。当然,对于程序来说这是透明的,因为在 php 接收 cookie 的值时会自动将其 decode。

如果要设置同名的多个 cookie,要用数组,方法是:

setcookie(";cookiearray[]";, ";value 1";);

setcookie(";cookiearray[]";, ";value 2";);

setcookie(";cookiearray[0]";, ";value 1";);

setcookie(";cookiearray[1]";, ";value 2";);

2、接收和处理 cookie

php 对 cookie 的接收和处理的支持非常好,是完全自动的,跟form变量的原则一样,特别简单。

比如设置一个名为 mycookier 的 cookie,php会自动从web服务器接收的 http 头里把它分析出来,并形成一个与普通变量一样的变量,名为 $mycookie,这个变量的值就是cookie的值。数组同样适用。另外一个办法是引用php的全局变量 $http_cookie_vars 数组。

分别举例如下:(假设这些都在以前的页面里设置过了,并且仍然有效)

echo $mycookie;

echo $cookiearray[0];

echo count($cookiearray);

echo $http_cookie_vars[";mycookie";];

3、删除cookie

要删除一个已经存在的 cookie,有两个办法:

一是调用只带有 name 参数的 setcookie,那么名为这个 name 的 cookie 将被从关系户机上删掉;另一个办法是设置 cookie 的失效时间为 time() 或 time()-1,那么这个 cookie 在这个页面的浏览完之后就被删除了(其实是失效了)。

要注意的是,当一个 cookie 被删除时,它的值在当前页在仍然有效的。

4、使用 cookie 的限制

首先是必须在 html 文件的内容输出之前设置;其次不同的浏览器对 cookie 的处理不一致辞,且有时会出现错误的结果。比如:ms ie+service pack 1 不能正确处理带域名和路径的 cookie,netscape communicator 4.05 和 ms ie 3.0不能正确处理不带路径和时间的 cookie。至于 ms ie 5 好象不能处理带域名、路径和时间的 cookie。

第三个限制是在客户端的。一个浏览器能创建的cookie数量最多为30个,并且每个不能超过 4kb,每个web 站点能设置的 cookie 总数不能超过 20 个。

(由于 cookie 最初由 netscape 定义的,所以附上 netscape 公司关于 cookie 的官方原始定义的网址:http:www.netscape.comnewsrefstdcookie_spec.html)

使用 excel api 制作 excel 数据

<;?

$excel = new com(‘excel.application‘) or die(‘unable to instanciate excel‘);

$excel->;visible?=?0;

$book=$excel->;workbooks->;add;

$book->;title=‘excel范例‘;

$book->;subject=‘这是excel范例程序制作的excel档‘;

$sheet=$book->;worksheets(‘sheet1‘);

$range=$sheet->;range(‘a1:c10‘);

for($i=1;$i<;=10;$i++):

for($j=1;$j<;=3;$j++):

$cell=$range->;cells($j,$i);

$cell->;value=chr($i+64).$j;## 塞入a1:c10的值

endfor;

endfor;

$book->;saveas(‘c:excel.xls‘);## 存档

$excel->;quit();

$excel->;release();

$excel=null;

?>;

php 调用 com 组件

如果你是一名冒险份子,而且你正在使用 cgi、isapi 或 apache 模块版本的 windows 系统上运行着php,那么你也可以获得系统的 com 功能。现在,解释 com(微软的组件对象模型)的工作留给了微软和那些大部头的图书来完成。然而,知道点 com 也没什么错,下面有一个普通的(没有双关语,针对很普通)代码小片断。

这代码小片断使用 php 在后台启动 microsoft word、打开一个新文件、键入一些文本、保存该文件然后关闭应用程序:

<;?

create a reference to a new com component (word)

$word = new com(";word.application";) or die(";can‘t start word!";);

print the version of word that‘s now in use

echo ";loading word, v. {$word->;version}<;br>;";;

set the visibility of the application to 0 (false)

to open the application in the forefront, use 1 (true)

$word->;visible = 0;

create a new document in word

$word->;documents->;add();

add text to the new document

$word->;selection->;typetext(";testing 1-2-3...";);

save the document in the windows temp directory

$word->;documents[1]->;saveas(";windowstempcomtest.doc";);

close the connection to the com component

$word->;quit();

print another message to the screen

echo ";check for the file...";;

?>;

假设你正在运行一个内联网 web 站点,该站点把数据存放在 microsoft sql server 数据库内,你的用户需要 excel 格式的数据。那么,你可以让 php 执行必要的 sql 查询并且格式化输出结果,然后使用 com 启动 excel,把数据传输给它,最后再把文件存储到用户的桌面系统内。

php5 克隆

php5 中的对象模型通过引用来调用对象, 但有时你可能想建立一个对象的副本,并希望原来的对象的改变不影响到副本。为了这样的目的,php 定义了一个特殊的方法,称为 __clone。像 __construct 和__destruct 一样,前面有两个下划线。

默认地,用 __clone 方法将建立一个与原对象拥有相同属性和方法的对象。 如果你想在克隆时改变默认的内容,你要在 __clone 中覆写(属性或方法)。

克隆的方法可以没有参数,但它同时包含 this 和 that 指针(that 指向被复制的对象)。 如果你选择克隆自己,你要小心复制任何你要你的对象包含的信息,从 that 到 this。 如果你用 __clone 来复制。 php 不会执行任何隐性的复制,

下面显示了一个用系列序数来自动化对象的例子:

<;?php

class objecttracker 对象跟踪器

{

private static $nextserial = 0;

private $id;

private $name;

function __construct($name) 构造函数

{

$this->;name = $name;

$this->;id = ++self::$nextserial;

}

function __clone() 克隆

{

$this->;name = ";clone of $that->;name";;

$this->;id = ++self::$nextserial;

}

function getid() 获取id属性的值

{

return($this->;id);

}

function getname() 获取name属性的值

{

return($this->;name);

}

}

$ot = new objecttracker(";zeev‘s object";);

$ot2 = $ot->;__clone();

输出: 1 zeev‘s object

print($ot->;getid() . "; "; . $ot->;getname() . ";<;br>;";);

输出: 2 clone of zeev‘s object

print($ot2->;getid() . "; "; . $ot2->;getname() . ";<;br>;";);

?>;

定义 php 类

当声明一个 php 类,需要列出对象应有的所有变量和所有函数—被称为属性和方法。3。1。1中显示了一个类的构成。 注意在大括号({})内你只能声明变量或者函数。3。1。2中显示了如何在一个类中定义三个属性和两个方法。

3。1。1

class name extends another class

{

access variable declaration

access function declaration

}

3。1。2

<;?php

定义一个跟踪用户的类

class user

{

属性

public $name;

private $password, $lastlogin;

方法

public function __construct($name, $password)

{

$this->;name = $name;

$this->;password = $password;

$this->;lastlogin = time();

$this->;accesses++;

}

获取最后访问的时间

function getlastlogin()

{

return(date(";m d y";, $this->;lastlogin));

}

}

创建一个对象的实例

$user = new user(";leon";, ";sdf123";);

获取最后访问的时间

print($user->;getlastlogin() 。";<;br>;n";);

打印用户名

print(";$user->;name<;br>;n";);

?>;

当你声明属性,你不需要指明数据类型。 变量可能是整型,字符串或者是另一个对象,这取决于实际情况。在声明属性时增加注释是一个好主意,标记上属性的含义和数据类型。

当你声明一个方法,你所做的和在类外部定义一个函数是一样的。 方法和属性都有各自的命名空间。这意味着你可以安全地建立一个与类外部函数同名的方法,两者不会冲突。 例如,一个类中可以定义一个名为date() 的方法。 但是你不能将一个方法命名为 php 的关键字,如 for 或者 while。

类方法可能包含 php 中所谓的 type hint。type hint 是另一个传递参数给方法的类的名字。如果你的脚本调用方法并传递一个不是类的实例的变量,php 将产生一个”致命(fatal)错误” 。你可能没有给其它类型给出 type hint,就像整型,字符串,或者布尔值。在书写的时候,type hint 是否应当包含数组类型仍存在争议。

type hint 是测试函数参数或者运算符的实例的数据类型的捷径。你可能总是返回这个方法。确认你强制让一个参数必须是哪种数据类型,如整型。3。2。1 确保编译类只产生 widget 的实例。

3。2。1

<;?php

组件

class widget

{

public $name=‘none‘;

public $created=false;

}

装配器

class assembler

{

public function make(widget $w)

{

print(";making $w->;name<;br>;n";);

$w->;created=true;

}

}

建立一个组件对象

$thing = new widget;

$thing->;name = ‘gadget‘;

装配组件

assembler::make($thing);

?>;

除了传递参数的变量外,方法含有一个特殊的变量。它代表类的个别实例。你应当用这个来指向对象的属性和其它方法。一些面向对象的语言假设一个不合格的变量提交给本地属性,但在 php 中方法的任何变量只是在方法的一定范围内。注意在 user 类的构造函数中这个变量的使用(3。1。2)。

php在属性和方法声明前定义一个访问限定语,如 public,private 和 protected。另外,你可以用”static”来标记一个成员。你也可以在类中声明常量。本章稍后会有不同访问方式的相关讨论。

你可以在一行中列出相同访问方式的几个属性,用逗号来分隔它们。 在3。1。2中,user 类有两个private 属性 --$password 和 $lastlogin。

用 php 类封装数据

一般情况下,如果使用 classname::property 是不能访问到类的属性的,但可以用 classname::method() 使用类的方法。同样的也不能用 objectname->;property 访问到类的方法里的变量。利用这一特点,我们可以将一些数据保存于类中,有 点象 c++ 的私有属性。

<;?

class data {

function value($var) {

static $d = array();

if(func_num_args() >; 1) {

$d[$var] = func_get_arg(1);

}else {

return $d[$var];

}

}

}

测试:

data::value(";a";,1);

data::value(";b";,2);

echo data::value(";a";);

echo data::value(";b";);

?>;

php 实现聊天室的主动更新与被动更新

聊天的内容如何显示在屏幕上,一种是每隔一段时间刷新一次页面,读入全部聊天内容,然后显示,这里采用的是 js 的 document.write 的方法实现不刷新的聊天页面!

1 主页面的生成,规定了css类型,显示欢迎词

function write2(){

if(this.u.document==null)return;

this.u.document.writeln(";<;html>;<;head>;";);

this.u.document.writeln(";<;meta http-equiv=content-type content=textht

ml; charset=gb2312>;";);

this.u.document.writeln(";<;style type=textcss>;";);

this.u.document.writeln(";.p9 { font-size: 11pt; line-height: 15pt}";);

this.u.document.writeln(";body { font-size: 11pt; line-height: 15pt}";);

this.u.document.writeln(";a:visited { font-size: 11pt;color: ext-decoration: none;}";);

this.u.document.writeln(";a:link { font-size: 11pt;color: -decoration: none}";);

this.u.document.writeln(";a:hover { font-size: 11pt;color:

this.u.document.writeln(";<;style>;";);

this.u.document.writeln(";<;head>;";);

this.u.document.writeln(";<;body);

.................. 这里插入生成在线人数组的程序段

this.u.document.writeln(";<;script>;";);

this.u.document.writeln(";<;p class=p9 align=left>;";);

this.u.document.writeln(";<;p align=center>;欢迎光临 playboy 聊天室,本聊天室

正在测试阶段,如有问题请与<;a href=mailto:pccastle@sina.com>;我们联系<;a>;

<;p>;";);

}

2 初始化进入信息,第一次进入聊天室

if($action == ";enter";){

调用显示主屏幕的 js 程序

print(";parent.write2();n";);

发言内容,某某进入聊天室了

$message = ";<;a href=javascript:parent.cs(‘$name‘); target=d>;$name<;a>;来

到聊天室";.$message."; ";.date(";m月d日 h:i";).";<;script>;parent.add(‘$name‘,

‘$photo‘);parent.write1();<;script>;<;br>;";;

}

更新发言内容

while(file_exists($lockfile)){ $pppp++; }

发言的锁定

fclose(fopen($lockfile,";w";));

读入发言的总句数,也就是所有人一共发了多少言!我们可以保存每一个发言,但是这样会占用大量的磁盘空间,我们采用了一种取模的方法,循环使用文件来减少文件操作!

$talkmessage = file($filename);

$number = chop($talkmessage[0]);

发言数增加一,然后保存

$talkhandle = fopen($filename,";w";);

$number++;

fputs($talkhandle,$number);

fclose($talkhandle);

去掉锁定

unlink($lockfile);

对发言总数对 10 取模,作为文件名保存发言内容,也就是说第 11 句和第1句使用同。一个文件名,由于不可能同时有 10 句话没有更新,所以这是数在人不是非常多的情况下很好!当然,考虑到人多的情况,可以设成 100。

$filehandle = fopen(";messageonline";.($number%10).";.php";,";w";);

fputs($filehandle,$message);

fclose($filehandle);

显示进入信息

print(";parent.u.document.writeln(";$message";);n";);

调用主动刷新js程序,传递已经显示的发言数目

print(";parent.flushwin($number)n";);

保存最后一次显示的发言

$last = $number;

}

3 处理发送表单的请求

不处理空的发言和超过一定数目的发言

if( ($message != ";";)&;&;(strlen($message)<;150)){

检查发言者是否在线,防止意外

$onlineperson = file(";useronline.dbf";);

$personsign=0;

for($i=0;$i<;count($onlineperson);$i++){

$person = split($split,$onlineperson[$i],99);

if($person[0] == $name){

$personsign = 1;

$person[3] = date(";u";);

break;

}

}

在线时的处理程序

if($personsign == 1){

添加发言时间的部分

$message = $message."; <;font size=1>;";.date(";m月d日 h:i";).";<;font>;<;br>;";;

锁定发言总数文件

while(file_exists($lockfile)){ $pppp++; }

fclose(fopen($lockfile,";w";));

读入发言总数

$talkmessage = file($filename);

$number = chop($talkmessage[0]);

总数加1,然后保存

$talkhandle = fopen($filename,";w";);

$number++;

fputs($talkhandle,$number);

fclose($talkhandle);

unlink($lockfile);

总数对 10 取模后以文件形式保存发言内容

$filehandle = fopen(";messageonline";.($number%10).";.php";,";w";);

fputs($filehandle,$message);

fclose($filehandle);

}

}

这样,表单的处理已经完成,下面的主动更新程序将会把新的发言内容显示在屏幕上

4 主动更新的自动循环调用方法

可以使用<;meta http-equiv=";reflesh"; content=";3;url=messageflush.php?nam

e=<;?print($name)?>;&;&;pass=<;?print($pass)&;&;last=<;?print($last)?>;的方式更新!

我的程序以前就是使用这种方法自动更新的,但是我发现一个问题,那就是当这个更新程序出现运行错误时,他不会产生调用下次更新的代码,造成后台更新程序停止工作!所以我采用了 js 定时的方法来完成同样的功能!

var flushtimeid=null;

var flushrunning=false;

上次更新标志

var flushflag = true;

function flushstop(){

if(flushtimerrunning)cleartimeout(flushtimerid);

flushtimerrunning=false;

}

function flushstart(){

flushstop();

使用发送表单里面的上次显示的值

flushwin(this.d.document.inputform.last.value);

}

}

function flushwin(winnumber){

如果上次更新正确,则调用下次更新

if(flushflag == true){

url=";messageflush.php?name=<;? print($name); ?>;&;&;pass=<;? print($pass);

?>;&;&;last=";+winnumber;

flush.location=url

flushflag=false

}

否则等待一个循环

flushtimerid=settimeout(";flushstart()";,2000);

flushtimerrunning=true;

}

这种方法保证了在主程序不死的情况下,后台更新程序会一直运行下去!

5 主动更新程序

<;script language=‘javascript‘>;

<;?

读入最大的发言数目

$message = file($filename);

$number = chop($message[0]);

从上次显示的下一个发言开始到最大发言结束,显示发言内容

for($i=$last+1;$i<;=$number;$i++){

读入下一个发言内容

$filename = ";messageonline";.($i%10).";.php";;

$message = file($filename);

$tempmessage = split($split,$message[0],99);

显示发言内容

print(";parent.u.document.writeln(";$message[0]";);rn";);

}

更新发送表单最后一个发言的数目

print(";parent.d.document.inputform.last.value=$number;n";);

通知主程序本次更新已经完成

print(";parent.flushflag=true;n";);

?>;

<;script>;

这样,每个发送的发言,经过被动更新程序处理保存到文件内,然后由一个循环的主动更新程序完成显示任务!

php 分页显示详解

分页显示是一种非常常见的浏览和显示大量数据的方法,属于 web 编程中最常处理的事件之一。对于 web 编程的老手来说,编写这种代码实在是和呼吸一样自然,但是对于初学者来说,常常对这个问题摸不着头绪,因此特地撰写此文对这个问题进行详细的讲解,力求让看完这篇文章的朋友在看完以后对于分页显示的原理和实现方法有所了解。本文适合初学者阅读,所有示例代码均使用 php 编写。

原理

所谓分页显示,也就是将数据库中的结果集人为的分成一段一段的来显示,这里需要两个初始的参数:

每页多少条记录($pagesize)?

当前是第几页($currentpageid)?

现在只要再给我一个结果集,我就可以显示某段特定的结果出来。

至于其他的参数,比如:上一页($previouspageid)、下一页($nextpageid)、总页数($numpages)等等,都可以根据前边这几个东西得到。

以mysql数据库为例,如果要从表内截取某段内容,sql 语句可以用:select * from table limit offset, rows。看看下面一组 sql 语句,尝试一下发现其中的规率。

前 10 条记录:select * from table limit 0,9

第 11 至 20 条记录:select * from table limit 10,19

第 21 至 30 条记录:select * from table limit 20,29

……

这一组 sql 语句其实就是当 $pagesize=10 的时候取表内每一页数据的 sql 语句,我们可以总结出这样一个模板:

select * from table limit ($currentpageid - 1) * $pagesize, $pagesize

拿这个模板代入对应的值和上边那一组sql语句对照一下看看是不是那么回事。搞定了最重要的如何获取数据的问题以后,剩下的就仅仅是传递参数,构造合适的sql语句然后使用php从数据库内获取数据并显示了。以下我将用具体代码加以说明。

简单代码

请详细阅读以下代码,自己调试运行一次,最好把它修改一次,加上自己的功能,比如搜索等等。

<?php

建立数据库连接

$link = mysql_connect(";localhost";, ";mysql_user";, ";mysql_password";)

or die(";could not connect: "; . mysql_error());

获取当前页数

if( isset($_get[‘page‘]) ){

$page = intval( $_get[‘page‘] );

}

else{

$page = 1;

}

每页数量

$pagesize = 10;

获取总数据量

$sql = ";select count(*) as amount from table";;

$result = mysql_query($sql);

$row = mysql_fetch_row($result);

$amount = $row[‘amount‘];

记算总共有多少页

if( $amount ){

if( $amount < $page_size ){ $page_count = 1; } 如果总数据量小于$pagesize,那么只有一页

if( $amount % $page_size ){ 取总数据量除以每页数的余数

$page_count = (int)($amount $page_size) + 1; 如果有余数,则页数等于总数据量除以每页数的结果取整再加一

}else{

$page_count = $amount $page_size; 如果没有余数,则页数等于总数据量除以每页数的结果

}

}

else{

$page_count = 0;

}

翻页链接

$page_string = ‘‘;

if( $page == 1 ){

$page_string .= ‘第一页|上一页|‘;

}

else{

$page_string .= ‘<a href=?page=1>第一页<a>|<a href=?page=‘.($page-1).‘>上一页<a>|‘;

}

if( ($page == $page_count) || ($page_count == 0) ){

$page_string .= ‘下一页|尾页‘;

}

else{

$page_string .= ‘<a href=?page=‘.($page+1).‘>下一页<a>|<a href=?page=‘.$page_count.‘>尾页<a>‘;

}

获取数据,以二维数组格式返回结果

if( $amount ){

$sql = ";select * from table order by id desc limit ";. ($page-1)*$page_size .";, $page_size";;

$result = mysql_query($sql);

while ( $row = mysql_fetch_row($result) ){

$rowset[] = $row;

}

}else{

$rowset = array();

}

没有包含显示结果的代码,那不在讨论范围,只要用 foreach 就可以很简单的用得到的二维数组来显示结果

?>

php + mysql 制作电子贺卡

第一步:首先作一个如下面的表单:(注:这个表单里加了php程序)

<;form method=‘post‘ action=‘mailtocard.php‘ name=‘card‘ onsubmit=‘return card_validator(this)‘>;

<;table width=‘450‘ border=‘0‘ cellspacing=‘0‘ cellpadding=‘0‘ align=‘center‘>;

<;tr>;

<;td valign=‘top‘ width=‘143‘>;

<;input type=‘radio‘ name=‘inout‘ value=‘newyear‘ checked>;

<;img src=‘imagesnewyear1.gif‘ width=‘75‘ height=‘75‘>; <;td>;

<;td width=‘170‘>;

<;input type=‘radio‘ name=‘inout‘ value=‘newyear2_2‘>;

<;img src=‘imagesnewyear2.gif‘ width=‘75‘ height=‘75‘>; <;td>;

<;td width=‘137‘>;

<;input type=‘radio‘ name=‘inout‘ value=‘newyear3_3‘>;

<;img src=‘imagesnewyear1.gif‘ width=‘75‘ height=‘75‘>; <;td>;

<;tr>;

<;tr>;

<;td valign=‘top‘ colspan=‘3‘>;

<;textarea name=‘text‘ rows=‘7‘ cols=‘60‘ wrap=‘virtual‘>;你好朋友:

<;textarea>;

<;td>;

<;tr>;

<;tr>;

<;td valign=‘top‘ colspan=‘3‘>;

<;select name=‘music‘>;

<;option selected>;--卡片背景音乐--<;option>;

<;option value=‘101marry.mid‘>;一千零一夜<;option>;

<;option value=‘canyon.mid‘>;canyon<;option>;

<;select>;

<;input onclick=playsound() type=button value=‘试听音乐‘>;

<;td>;

<;tr>;

<;tr>;

<;td valign=‘top‘ colspan=‘3‘>;<;td>;

<;tr>;

<;tr>;

<;td valign=‘top‘ colspan=‘3‘>;

<;table width=‘370‘ border=‘0‘ cellspacing=‘0‘ cellpadding=‘0‘ align=‘center‘ class=‘p11‘>;

<;tr>;

<;td width=‘108‘>;

<;?

if (strlen($g_username) >; 1)

{

判断是否登陆,若已登陆显示姓名及email,不用填写。

$db=mysql_connect(‘localhost‘,‘root‘,‘‘);

$result=mysql_db_query(‘数据库名‘,‘select email,http from 数据库表名 where username=‘$g_username‘‘);

$row=mysql_fetch_array($result);

$bbs_email=$row[email]; echo ‘<;div align=‘left‘>;您的姓名:<;div>;

<;td>;

<;td width=342>;

$g_username

<;input type=hidden name=username value=$g_username>;

<;td>;

<;tr>;

<;tr>;

<;td width=108>;

<;div align=hidden>;您的email:<;div>;

<;td>;

<;td width=342>;

$bbs_email

<;input type=hidden name=email value=$bbs_email>;

‘;

}

if (strlen($g_username) <; 0)

else 判断没有登陆,需要填写姓名及email。

{

echo ";<;div align=‘left‘>;您的姓名:<;div>;

<;td>;

<;td width=‘342‘>;

<;input type=‘text‘ name=‘username‘>;

<;td>;

<;tr>;

<;tr>;

<;td width=‘108‘>;

<;div align=‘left‘>;您的email:<;div>;

<;td>;

<;td width=‘342‘>;

<;input type=‘text‘ name=‘email‘>;";;

}

?>;

<;td>;

<;tr>;

<;tr>;

<;td width=";108";>;

<;div align=";left";>;朋友姓名:<;div>;

<;td>;

<;td width=";342";>;

<;input type=";text"; name=";f_name";>;

<;td>;

<;tr>;

<;tr>;

<;td width=";108";>;

<;div align=";left";>;朋友email:<;div>;

<;td>;

<;td width=";342";>;

<;input type=";text"; name=";f_email";>;

<;td>;

<;tr>;

<;tr>;

<;td width=";108";>;?<;td>;

<;td width=";342";>;

<;input type=";button"; name=";submit"; value=";预览"; onclick=";preview()";>;

<;input type=";submit"; name=";submit"; value=";发送";>;

<;input type=";reset"; name=";submit3"; value=";重来";>;

第二步:预览

<;? if (submit==";预览";)

{

switch($new)

{

case ";newyear";:

$new=";newyear.gif";;

break;

case ";newyear2_2";:

$query=newyear2_2.gif;

break;

case ";newyear3_3";:

$query=newyear3_3.gif;

break;

}

}

?>;

<;html>;

<;head>;

<;title>;电子贺卡<;title>;

<;meta http-equiv=";content-type"; content=";texthtml; charset=gb2312";>;

<;head>; <;body bgcolor=";#eeeeee";>;

<;form method=";post"; action=";mailtocard.php";>;

<;table width=";497"; border=";0"; cellspacing=";0"; cellpadding=";0"; align=";center"; height=";310";>;

<;tr>;

<;td colspan=";2";>;

<;div align=";center";>;

<;? echo ";<;img src=images";.$new.";.gif>;";; ?>;

<;div>;

<;td>;

<;tr>;

<;tr>;

<;td width=";317"; valign=";top";>;

<;p>;<;font size=";3"; color=";#ff0066";>;您好朋友:<;font>;<;br>;

<;br>;

<;font size=";2"; color=";#3333ff";>;

<;? echo $text; ?>;

<;font>;<;p>;

<;td>;

<;td width=";180"; valign=";top";>;

<;div align=";right";>;

<;table width=";90%"; border=";0"; cellspacing=";0"; cellpadding=";0";>;

<;tr>;

<;td>;

<;p>;<;font size=";3"; color=";#ff0066";>;寄卡给:<;font>;<;font size=";2";>;<;br>;

<;font>;<;p>;

<;p>;<;font color=";#3300cc"; size=";2";>;<;? echo $f_name; ?>;

<;input type=hidden name=f_name value=$f_name>;

<;font>;<;p>;

<;p>;<;font size=";3"; color=";#ff0066";>;您的朋友:<;font>;<;p>;

<;p>;<;font size=";2"; color=";#3300cc";>;

<;? echo $g_username; ?>;

<;input type=hidden name=username>;

<;input type=hidden name=f_email value=";$femail";>;

<;input type=hidden name=email>;

<;font>;<;p>;

<;td>;

<;tr>;

<;table>;

<;div>;

<;td>;

<;tr>;

<;tr>;

<;td colspan=";2"; valign=";top";>;

<;div align=";center";>;

<;input type=";submit"; name=";submit"; value=";发送";>;

<;input type=";button"; onclick=";javascript:window.close()"; name=";close"; value=";关闭窗口";>;

<;div>;

<;td>;

<;tr>;

<;table>;

<;form>;

<;body>;

<;html>;

第三步:发送贺卡

<;?

if(submit==";发送";) $mainurl = ";http:lyjrich.oso.com.cncard";; 该贺卡文件主目录url

$dataurl = ";$mainurlstore";; 存放产生的贺卡的url

$userip = getenv(";remote_addr";);

$daten = date(";m月d日h点i分";);

$roundno = date(";mdhis";);

$fileno .=$roundno.";.html";;

$fileurl = $dataurl.";";.$fileno; 存放产生的贺卡的url

$subject=";朋友给你邮的贺卡";;

$content = eregi_replace(";<;br>;";,";n";,";$text";); $t_body .= ";**************************************n";;

$t_body .= $f_name."; 您好:n";;

$t_body .= $g_username."; 从http:lyjrich.oso.com.cn 寄了一张贺卡给你。n";;

$t_body .= $g_username.";给您的留言上说:n";.$text .";nn";;

$t_body .= ";请你点击http:lyjrich.oso.com.cncard";.$fileurl."; 来欣赏这张贺卡n";;

$t_body .= ";贺卡最长将为你保存一个月。nn";;

$t_body .= ";n************************************n";;

$t_body .= ";发送时间 $datenn";;

$t_body .= ";**************************************nn";;

$t_body .= ";免费电子贺卡由 your web 网站提供nnn";;

$t_body .= ";程序制作:lyjrich(http:lyjrich.oso.com.cn)n";;

mail($f_email,$subject,$t_body,";from: ";.$email.";n";); echo ";<;script language=";javascript";>;history.back();alert(";发送成功,谢谢使用!!";);<;script>;";; $message =";<;html>;

<;head>;

<;title>;电子贺卡<;title>;

<;meta http-equiv=‘content-type‘ content=‘texthtml; charset=gb2312‘>;

<;head>; <;body bgcolor=‘#eeeeee‘>;

<;table width=‘497‘ border=‘0‘ cellspacing=‘0‘ cellpadding=‘0‘ align=‘center‘ height=‘310‘>;

<;tr>;

<;td colspan=‘2‘>;

<;div align=‘center‘>;

<;img src=images$inout.gif>;

<;div>;

<;td>;

<;tr>;

<;tr>;

<;td width=‘317‘ valign=‘top‘>;

<;p>;<;font size=‘3‘ color=‘#ff0066‘>;您好朋友:<;font>;<;br>;

<;br>;

<;font size=‘2‘ color=‘#3333ff‘>;

$text

<;font>;<;p>;

<;td>;

<;td width=‘180‘ valign=‘top‘>;

<;div align=‘right‘>;

<;table width=‘90%‘ border=‘0‘ cellspacing=‘0‘ cellpadding=‘0‘>;

<;tr>;

<;td>;

<;p>;<;font size=‘3‘ color=‘#ff0066‘>;寄卡给:<;font>;<;font size=‘2‘>;<;br>;

<;font>;<;p>;

<;p>;<;font color=‘#3300cc‘ size=‘2‘>;$f_name

<;input type=hidden name=f_name value=$f_name>;

<;font>;<;p>;

<;p>;<;font size=‘3‘ color=‘#ff0066‘>;您的朋友:<;font>;<;p>;

<;p>;<;font size=‘2‘ color=‘#3300cc‘>;

$g_username

<;input type=hidden name=username>;

<;input type=hidden name=f_email value=‘$femail‘>;

<;input type=hidden name=email>;

<;font>;<;p>;

<;td>;

<;tr>;

<;table>;

<;div>;

<;td>;

<;tr>;

<;tr>;

<;td colspan=‘2‘ valign=‘top‘>;

<;td>;

<;table>; <;body>;

<;html>;";; $mydir=dir(";.store";);

$fp = fopen (";store$roundno.html";,";w+";) or die(";建立文件错误!";);;

fwrite ($fp, $message);

fclose ($fp);

?>;

php 历法函数库

想要使用历法函数库,需要先编译好 dlcalendar 函数库。php 中的历法函数库提供不同的公元历法转换。转换的基准是凯撒日计数 (julian day count)。所有的历法计算都必需先转换成凯撒日计数,再转成您所需要的历法,更多的资料可以参考这个网址找到 http:genealogy.org~scottleecal-overview.html

。不过对于使用黄帝纪元的中国,这个函数库就还需要扩充才适合了。

jdtogregorian将凯撒日计数 (julian day count) 转换成为格里高里历法 (gregorian date)。

语法: string jdtogregorian(int julianday);

返回值: 字符串

函数种类: 时间日期

内容说明 将凯撒历法的日期计数转换成为格里高里历法字符串,并以‘月份日期年‘ (monthdayyear) 的字符串返回。格里高里历为教皇格梩高里十三世在公元 1582 年颁行的历法。

gregoriantojd将格里高里历法转换成为凯撒日计数。

语法: int gregoriantojd(int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明 有效的范围为格里高里历法公元前 4714 年至公元 9999 年。这套软件能计算到公元前 4714 年,但这是不太有意义的。格里高里历在 1582 年 10 月 15 日施行,但一些欧洲国家到很久后才实行,如英国在 1752 年实行、苏联在 1918 年施行、希腊在 1923 年实行。大部份的欧洲国家优先使用凯撒历法,再次才是格里高里历法。

使用范例

<;?php

$jd = gregoriantojd(10,11,1970);

echo(‘$jdn‘);

$gregorian = jdtogregorian($jd);

echo(‘$gregoriann‘);

?>;

jdtojulian将凯撒日计数转换成为凯撒历法。

语法: string jdtojulian(int julianday);

返回值: 字符串

函数种类: 时间日期

内容说明:

将凯撒历法的日期计数转换成为凯撒历法字符串,并以‘月份日期年‘ (monthdayyear) 的字符串返回。

juliantojd将凯撒历法转换成为凯撒日计数。

语法: int juliantojd(int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明: 有效的范围为凯撒历法公元前 4713 年至公元 9999 年。这套软件能计算到公元前 4713 年,但这是不太有意义的。凯撒历法是在公元前 46 年建立的,但一些细节等到公元 8 年才稳定下来。

jdtojewish将凯撒日计数转换成为犹太历法。

语法: string jdtojewish(int julianday);

返回值: 字符串

函数种类: 时间日期

内容说明 将凯撒历法的日期计数转换成为犹太历法字符串,并以‘月份日期年‘ (monthdayyear) 的字符串返回。

jewishtojd将犹太历法转换成为凯撒日计数。

语法: int jewishtojd(int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明: 有效的范围为犹太历法公元前 3761 年起。犹太历法存在了数千年,但早期并没有公式化的开始月份计算法。每年的第一个月为首次观测到的新月。

jdtofrench将凯撒日计数转换成为法国共和历法。

语法: string jdtofrench(int month, int day, int year);

返回值: 字符串

函数种类: 时间日期

内容说明: 将凯撒历法的日期计数转换成为法国共和历法字符串,并以 ‘月份日期年‘ (monthdayyear) 的字符串返回。

frenchtojd将法国共和历法转换成为凯撒日计数。

语法: int frenchtojd(int month, int day, int year);

返回值: 整数

函数种类: 时间日期

内容说明 函数只能转换法国共和历元年到十四年,也就是格里高里历的 1792 年 9 月 22 日至 1806 年 9 月 22 日。

jdmonthname返回月份名。

语法: string jdmonthname(int julianday, int mode);

返回值: 字符串

函数种类: 时间日期

内容说明: 本函数返回指定历法的月份字符串。参数 mode 为历法名称,详见下表。

mode

代表义意

0

格里高里历 (缩写)

1

格里高里历

2

凯撒历 (缩写)

3

凯撒历

4

犹太历

5

法国共和历

jddayofweek返回日期在周几。

语法: mixed jddayofweek(int julianday, int mode);

返回值: 混合类型

函数种类: 时间日期

内容说明 本函数返回日期在当周的天数,返回值依 mode 值决定,详见下表

mode

代表义意

0

返回周几为整数值 (0 为周日, 1 为周一... 余类推)

1

返回字符串为周几 (英文-格里高里历)

2

返回字符串为周几的缩写 (英文-格里高里历)

用 php 控制您的浏览器 cache (2)

我们现在介绍实现静态输出的一种办法:使用 ob 系列函数实现。

example 4.

<;?php

ob_start();打开缓冲区

?>;

php页面的全部输出

<;?

$content = ob_get_contents();取得php页面输出的全部内容

$fp = fopen(“output00001.html”, “w”); 创建一个文件,并打开,准备写入

fwrite($fp, $content); 把php页面的内容全部写入output00001.html,然后……

fclose($fp);

?>;

这样,所谓的静态模版就很容易的被实现了……

二、 捕捉输出

example 4.是一种最简单的情况,你还可以在写入前对 $content 进行操作。

你可以设法捕捉一些关键字,然后去对它进行再处理,比如 example 3. 所述的 php 语法高亮显示。个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的想象力.

example 5.

<;?

function run_code($code) {

if($code) {

ob_start();

eval($code);

$contents = ob_get_contents();

ob_end_clean();

}else {

echo “错误!没有输出”;

exit();

}

return $contents;

}

%>;

以上这个例子的用途不是很大,不过很典型 $code 的本身就是一个含有变量的输出页面,而这个例子用eval把$code中的变量替换,然后对输出结果再进行输出捕捉,再一次的进行处理。

example 6. 加快传输

<;?

*

** title.........: php4 http compression speeds up the web

** version.......: 1.20

** author........: catoc <;catoc@163.net>;

** filename......: gzdoc.php

** last changed..: 18102000

** requirments...: php4 >;= 4.0.1

** php was configured with --with-zlib[=dir]

** notes.........: dynamic content acceleration compresses

** the data transmission data on the fly

** code by sun jin hu (catoc) <;catoc@163.net>;

** most newer browsers since 19981999 have

** been equipped to support the http 1.1

** standard known as ‘content-encoding.‘

** essentially the browser indicates to the

** server that it can accept ‘content encoding‘

** and if the server is capable it will then

** compress the data and transmit it. the

** browser decompresses it and then renders

** the page.

**

** modified by john lim (jlim@natsoft.com.my)

** based on ideas by sandy mcarthur, jr

** usage........:

** no space before the beginning of the first ‘<;?‘ tag.

** ------------start of file----------

** |<;?

** | include(‘gzdoc.php‘);

** |? >;

** |<;html>;

** |... the page ...

** |<;html>;

** |<;?

** | gzdocout();

** |? >;

** -------------end of file-----------

*

ob_start();

ob_implicit_flush(0);

function checkcangzip(){

global $http_accept_encoding;

if (headers_sent() || connection_timeout() || connection_aborted()){

return 0;

}

if (strpos($http_accept_encoding, ‘x-gzip‘) !== false) return ‘x-gzip‘;

if (strpos($http_accept_encoding,‘gzip‘) !== false) return ‘gzip‘;

return 0;

}

* $level = compression level 0-9, 0=none, 9=max *

function gzdocout($level=1,$debug=0){

$encoding = checkcangzip();

if ($encoding){

print ‘n<;!-- use compress $encoding -->;n‘;

$contents = ob_get_contents();

ob_end_clean();

if ($debug){

$s = ‘<;p>;not compress length: ‘.strlen($contents);

$s .= ‘

compressed length: ‘.strlen(gzcompress($contents,$level));

$contents .= $s;

}

header(‘content-encoding: $encoding‘);

print ‘x1fx8bx08x00x00x00x00x00‘;

$size = strlen($contents);

$crc = crc32($contents);

$contents = gzcompress($contents,$level);

$contents = substr($contents, 0, strlen($contents) - 4);

print $contents;

print pack(‘v‘,$crc);

print pack(‘v‘,$size);

exit;

}else{

ob_end_flush();

exit;

}

}

?>;

这是 catoc 的一段很早以前的代码,是对传输的内容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……

用 php 控制您的浏览器 cache (1)

output

control

函数可以让你自由控制脚本中数据的输出。它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况。输出控制函数不对使用

header() 或 setcookie(), 发送的文件头信息产生影响,只对那些类似于 echo() 和 php 代码的数据块有作用。

我们先举一个简单的例子,让大家对output control有一个大致的印象:

example 1.

<;?php

ob_start(); 打开缓冲区

echo ‘hellon‘; 输出

header(“location:index.php”); 把浏览器重定向到index.php

ob_end_flush();输出全部内容到浏览器

?>;

所有对 header() 函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用这个函数之前已经有了任何输出(包括空输出,比如空格,回 车和换行)就会提示出错。如果我们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“header had all ready send by”!但是加上 ob_start,就不会提示出错,原因是当打开了缓冲区,echo 后面的字符不会输出到浏览器,而是保留在服务器,直到你使用 flush 或者 ob_end_flush 才会输出,所以并不会有任何文件头输出的错误!

一、 相关函数简介:

1、flush:刷新缓冲区的内容,输出。

函数格式:flush()。说明:这个函数经常使用,效率很高。

2、ob_start :打开输出缓冲区

函数格式:void ob_start(void)。说明:当缓冲区激活时,所有来自php程序的非文件头信息均不会发送,而是保存在内部缓冲区。为了输出缓冲区的内容,可以使用 ob_end_flush( 或 flush() 输出缓冲区的内容。

3 、ob_get_contents :返回内部缓冲区的内容。

使用方法:string ob_get_contents(void)。说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 false 。

4、ob_get_length:返回内部缓冲区的长度。

使用方法:int ob_get_length(void)。说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激活。则返回 false。

5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。

使用方法:void ob_end_flush(void)。说明:这个函数发送输出缓冲区的内容(如果有的话)。

6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区

使用方法:void ob_end_clean(void)。说明:这个函数不会输出内部缓冲区的内容而是把它删除!

7、ob_implicit_flush:打开或关闭绝对刷新

使用方法:void ob_implicit_flush ([int flag])。说明:使用过 perl 的人都知道 $|=x 的意义,这个字符串可以打开关闭缓冲区,而 ob_implicit_flush 函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直接发送到浏览器,不再需要调用 flush()

二、深入了解:

1. 关于flush函数:

这个函数在 php3 中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新 browser 的cache。我们举一个运行效果非常明显的例子来说明flush。

example 2.

<;?php

for($i = 1; $i <;= 300; $i++ ) print(“ “);

这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出

换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经

过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会

源源不断的被发送出去。

for($j = 1; $j <;= 20; $j++) {

echo $j.”

”;

flush(); 这一部会使cache新增的内容被挤出去,显示到浏览器上

sleep(1); 让程序“睡”一秒钟,会让你把效果看得更清楚

}

?>;

注:如果在程序的首部加入 ob_implicit_flush() 打开绝对刷新,就可以在程序中不再使用 flush(),这样做的好处是提高效率!

2. 关于ob系列函数:

example 3.

如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要保存phpinfo() 函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了缓冲区的控制,我们可以轻松的解决:

<;?php

ob_start(); 打开缓冲区

phpinfo(); 使用phpinfo函数

$info=ob_get_contents(); 得到缓冲区的内容并且赋值给$info

$file=fopen(‘info.txt‘,‘w‘); 打开文件info.txt

fwrite($file,$info); 写入信息到info.txt

fclose($file); 关闭文件info.txt

?>;

用以上的方法,就可以把不同用户的 phpinfo 信息保存下来,这在以前恐怕没有办法办到!其实上面就是将一些“过程”转化为“函数”的方法!

或许有人问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的 php 语法加亮显示就和这个有关(php 默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次调用都显示恐怕会很浪费cpu,如果论坛将语法加亮函数显示的结果用控制缓冲区的方法保留了会大大提升性能)。

可能现在大家对 ob_start() 的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌握了使用 ob_start() 的要点。

<;1>;.使用 ob_start 打开 browser 的 cache,这样可以保证 cache 的内容在你调用flush(),ob_end_flush()(或程序执行完毕)之前不会被输出。

<; 2>;.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用 header,setcookie 以及session,这是 ob_start 一 个很大的特点;也可以使用 ob_start 的参数,在 cache 被写入后,然后自动运行命令,比如 ob_start(‘ob_gzhandler‘);而我们最常用的做法是用 ob_get_contents() 得到 cache 中的内容,然后再进行处理.

<;3>;.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完毕后的自动输出。当然,如果你用的是 ob_get_contents(),那么就要你自己控制输出方式了。

现在让我们看看能用ob系列函数做些什么

一、 静态模版技术

所谓静态模版技术就是通过某种方式,使得用户在 client 端得到的是由 php 产生的 html 页面。如果这个 html 页面不会再被更新,那么当别的用户再次浏览此页面时,程序将不会再调用 php 以及相关的数据库,对于某些信息量比较大的网站,例如新浪、网易、搜狐。类似这种的技术带来的好 处是非常巨大的。

php 的重载

php4 中已经有了重载的语法来建立对于外部对象模型的映射,就像 java 和 com 那样。php5 带来了强大的面向对象重载,允许程序员建立自定义的行为来访问属性和调用方法。

重载可以通过 __get, __set, and __call 几个特殊方法来进行。 当 zend 引擎试图访问一个成员并没有找到时,php 将会调用这些方法。

在例 6。14 中,__get 和 __set 代替所有对属性变量数组的访问。如果必要,你可以实现任何类型你想要的过滤。例如,脚本可以禁止设置属性值,在开始时用一定的前缀或包含一定类型的值。

__call方法说明了你如何调用未经定义的方法。你调用未定义方法时,方法名和方法接收的参数将会传给__call 方法,php 传递 __call 的值返回给未定义的方法。

listing 6.14 user-level overloading

<;?php

class overloader

{

private $properties = array();

function __get($property_name)

{

if(isset($this->;properties[$property_name]))

{

return($this->;properties[$property_name]);

}

else

{

return(null);

}

}

function __set($property_name, $value)

{

$this->;properties[$property_name] = $value;

}

function __call($function_name, $args)

{

print(";invoking $function_name()<;br>;n";);

print(";arguments: ";);

print_r($args);

return(true);

}

}

$o = new overloader();

invoke __set() 给一个不存在的属性变量赋值,激活__set()

$o->;dynaprop = ";dynamic content";;

invoke __get() 激活__get()

print($o->;dynaprop . ";<;br>;n";);

invoke __call() 激活__call()

$o->;dynamethod(";leon";, ";zeev";);

?>;

php 的绑定

除了限制访问,访问方式也决定哪个方法将被子类调用或哪个属性将被子类访问。函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定。

在计算机语言中有两种主要的绑定方式—静态绑定和动态绑定。静态绑定发生于数据结构和数据结构间,程序执行之前。静态绑定发生于编译期,因此不能利用任何运行期的信息。它针对函数调用与函数的主体,或变量与内存中的区块。因为 php 是一种动态语言,它不使用静态绑定。但是可以模拟静态绑定。

动态绑定则针对运行期产生的访问请求,只用到运行期的可用信息。在面向对象的代码中,动态绑定意味着决定哪个方法被调用或哪个属性被访问,将基于这个类本身而不基于访问范围。

public 和 protected 成员的动作类似于 php 的前几个版本中函数的动作,使用动态绑定。这意味着如果一个方法访问一个在子类中被覆写的类成员,并是一个子类的实例,子类的成员将被访问(而不是访问父类中的成员)。

看例子6。10。这段代码输出” hey! i am son。”因为当 php 调用 getsalutation, 是一个son的实例,是将 father 中的 salutation 覆写而来。 如果 salutation 是 public 的,php 将产生相同的结果。覆写方法的操作很类似。在 son 中,对于 identify 的调用绑定到那个方法。

即使在子类中访问方式被从 protected 削弱成 public,动态绑定仍然会发生。按照访问方式使用的原则,增强对于类成员的访问限制是不可能的。所以把访问方式从 public 改变成 protected 不可能进行。

listing 6.10 dynamic binding 动态绑定

<;?php

class father

{

protected $salutation = ";hello there!";; 问候

public function getsalutation()

{

print(";$this->;salutationn";);

$this->;identify();

}

protected function identify()

{

print(";i am father.<;br>;n";);

}

};

class son extends father

{

protected $salutation = ";hey!";; 父类中的 protected $salutation 被覆写

protected function identify() 父类中的 protected identify() 被覆写

{

print(";i am son.<;br>;n";);

}

};

$obj = new son();

$obj->;getsalutation(); 输出hey! i am son.

?>;

注: 在子类中没有覆写 getsalutation(),但实际上仍然存在一个 getsalutation()。这个类中的$salutation 和 identify()

与 son 子类的实例中的 getsalutation() 方法动态绑定,所以调用 son 的实例的 getsalutation() 方法,

将调用son类中的成员salutation及identify(),而不是父类中的成员 salutation 及 identify()。

private 成员只存在于它们所在的类内部。 不像 public 和 protected 成员那样,php 模拟静态绑定。 看例子 6。11。 它输出”hello there! i am father。”,尽管子类覆写了salutation 的值。 脚本将this->;salutation 和当前类 father 绑定。类似的原则应用于 private 方法 identify()。

listing 6.11 binding and private members

<;?php

class father

{

private $salutation = ";hello there!";;

public function getsalutation()

{

print(";$this->;salutationn";);

$this->;identify();

}

private function identify()

{

print(";i am father.<;br>;n";);

}

}

class son extends father

{

private $salutation = ";hey!";;

private function identify()

{

print(";i am son.<;br>;n";);

}

}

$obj = new son();

$obj->;getsalutation(); 输出hello there! i am father.

?>;

动态绑定的好处是允许继承类来改变父类的行为,同时可以保持父类的接口和功能。看例子 6。12。 由于使用了动态绑定,在 deleteuser 中被调用的 isauthorized 的 version 可以由对象的类型来确定。 如果是一个普通的 user,php 调用 user::isauthorized 会返回 false。如果是一个 authorizeduser 的实例,php 调用 authorizeduser::isauthorized,将允许 deleteuser 顺利执行。

haohappy 注:用一句话说清楚,就是对象类型与方法,属性绑定。 调用一个父类与子类中都存在的方法或访问一个属性时,会先判断实例属于哪种对象类型,再调用相应的类中的方法和属性。

listing 6.12 动态绑定的好处

<;?php

class user 用户

{

protected function isauthorized() 是否是验证用户

{

return(false);

}

public function getname() 获得名字

{

return($this->;name);

}

public function deleteuser($username) 删除用户

{

if(!$this->;isauthorized())

{

print(";you are not authorized.<;br>;n";);

return(false);

}

delete the user

print(";user deleted.<;br>;n";);

}

}

class authorizeduser extends user 认证用户

{

protected function isauthorized() 覆写isauthorized()

{

return(true);

}

}

$user = new user;

$admin = new authorizeduser;

not authorized

$user->;deleteuser(";zeev";);

authorized

$admin->;deleteuser(";zeev";);

?>;

为什么 private 的类成员模拟静态绑定? 为了回答这个问题, 你需要回忆一下为什么需要有 private 成员。什么时候用它们来代替 protected 成员是有意义的?

private 成员只有当你不想让子类继承改变或特殊化父类的行为时才用到。这种情况比你想像的要少。 通常来说,一个好的对象分层结构应当允许绝大多数功能被子类特殊化,改进,或改变—这是面向对象编程的基础之一。一定的情况下需要 private 方法或变量,例如当你确信你不想允许子类改变父类中的某个特定的部份。

与 asp 等价的 php 对象

1)写html

asp:response.write(str)

hp:print $str;

echo $str;

rint_r $debug_str;

2) form,cookie and querystring变量

asp:可以用request object.

hp:这些变量是自动提供的作为一个全局变量,如果在 php.ini 文件中这样配置的话:

variables_order=";egpcs";

register_globals=on

为了安全,我将不允许register_globals (设置它为off). 然后变量仅仅在数组中使用:

$http_post_vars,

$http_cookie_vars and $http_get_vars.

3)redirecting to another location

asp:response.redirect(url)

hp:header(";location: $url";);

4) cookie 处理

asp:response.cookies(cookiename) = newval

avar = request.cookies(cookiename)

hp:setcookie($cookiename, $newval);

$avar = $http_cookie_vars[$cookiename];

5)application变量

asp:application(appvarname)

hp:不提供,可以用数据库模拟

6)session 变量

asp:session(sessionname) = newval

avar = session(sessionname)

hp:在php4或以后的版本中, 我们确定变量作为一个 session 在 ession_register($sessionname), 然后,我们调用 session_start( ),在开始使用的 .php 页恢复 session 变量值。例如:

ession_register(‘avar‘);

$avar = 99;

ession_start();

rint $avar;

7)form 变量

asp:request.form(";formvar";)

request.querystring(";getvar";)

hp:$http_post_vars[";formvar";];

$http_get_vars[";getvar";];

get and post 变量可以交替的自动地修改到php变量,这是不安全地方法。

8)server 变量

asp:这有许多服务器变量,可以看asp文档. 一个例子:

request.servervariables(";http_host";)

hp:作为isapi模式, 服务器变量存储在$http_server_vars数组里。作为cgi, 它们存贮在环境变量里, 用$http_env_vars数组或getenv( ),可以得到。一个例子:

$http_server_vars[";http_host";]

using isapi module

$http_env_vars[";http_host";]

using cgi module

9)数据库访问

asp:一般用ado技术

hp:ado可以使用 adodb 库来模拟,这个库等价于ado。限制是,目前支持只读性光标和前滚光标。(注解)也可以直接调用 com 库。

10)buffering

asp:response.buffer = true

response.write(";abc";);

response.flush()

hp:ob_start();

rint ";abc";;

ob_end_ob_end_flush();

11) script timeout

asp:时间级是秒级:

server.scripttimeout(240)

hp:时间级是秒级:

et_time_limit(240);

使用 php 数组

php4.0 中共有超过 30 个新的数组相关函数。其中很多通用函数允许你检查给定数组中是否存在特定对象、对数组元素计数、增加或删除元素,或对元素排序。

如果你有很大的一个数组,而所要完成的仅是找出一个存在的给定值,你可以使用 in_array() 以返回true 或 false。如下代码将输出“not found in this array”——因为你将在 $namesarray 中寻找一个并不存在的“alber ”。

<;? $namesarray = array(";joe";, ";jane";, ";bob";, ";mary";, ";paul";, ";eddie";, ";john";);

$lookingfor = ";albert";;

if (in_array($lookingfor, $namesarray)) {

echo ";you‘ve found it!";;

} else {

echo ";not found in this array!";;

}

?>;

如果你改变了 $lookingfor 的值,将其变为“mary”,你将得到消息“you‘ve found it!”——因为“mary”是 $namesarray 的一部分。

如果希望对数组元素计数,你可以使用 count() 函数:

<;? $namesarray = array(";joe";, ";jane";, ";bob";, ";mary";, ";paul";, ";eddie";, ";john";);

$count = count($namesarray); ?>;

$count值将为7。

你可以对任何数组添加元素,无论是在已存在数组的开始或末尾。你也可以使用函数以创建一个包含两个或多个数组元素的新数组。合并时每个数组将按需要的顺序排列。如果你的数组已经有内部的排序,你需要对新的合并数组重排序。

让我们从对已存在数组的末尾增添元素开始,使用函数 array_push():

<;? * 创建原始数组 *

$fruitarray = array(";apple";, ";orange";, ";banana";, ";kiwi";, ";pear";);

* 加入到原始数组中 *

array_push($fruitarray, ";grape";, ";pineapple";, ";tomato";);

* 通过其键值列出每个元素*

while (list($key,$value) = each($fruitarray)) {

echo ";$key : $value<;br>;";;

}

?>;

这将显示:

0 : apple

1 : orange

2 : banana

3 : kiwi

4 : pear

5 : grape

6 : pineapple

7 : tomato

当你需要对数组开头添加元素时,代码非常类似。不同处只是函数名:array_unshift() 而不是array_push()。

<;? * 创建原始数组 *

$fruitarray = array(";apple";, ";orange";, ";banana";, ";kiwi";, ";pear";);

* 加入到原始数组中 *

array_unshift($fruitarray, ";grape";, ";pineapple";, ";tomato";);

* 通过其键值列出每个元素*

while (list($key,$value) = each($fruitarray)) {

echo ";$key : $value<;br>;";;

}

?>;

这将显示:

0 : grape

1 : pineapple

2 : tomato

3 : apple

4 : orange

5 : banana

6 : kiwi

7 : pear

函数 array_merge() 合并两个或更多的数组。

<;? * 创建原始数组 *

$fruitarray = array(";apple";, ";orange";, ";banana";, ";kiwi";, ";pear";);

<;? * 创建第二个数组 *

$vegarray = array(";carrot";, ";green beans";, ";asparagus";, ";artichoke";, ";corn";);

* 合并为一个数组 *

$goodfoodarray = array_merge($fruitarray, $vegarray);

* 通过其键值列出每个元素*

while (list($key,$value) = each($goodfoodarray)) {

echo ";$key : $value<;br>;";;

}

?>;

这将显示:

0 : apple

1 : orange

2 : banana

3 : kiwi

4 : pear

5 : carrot

6 : green beans

7 : asparagus

8 : artichoke

9 : corn

现在已经对数组进行了增加元素和合并,现在来练习删除元素函数。你可以使用函数 array_pop() 从一数组末尾删除一个元素。如果使用函数 array_shift(),则从一数组开头删除一个元素。而实际上当你从数组删除元素时,此元素对你而言仍然可用——当你从已存在的数组中对元素进行 pop 或 shift 时。

使用 array_pop() 函数从数组末尾删除一个值:

<;?

* 创建一数组*

$fruitarray = array(";apple";, ";orange";, ";banana";, ";kiwi";, ";pear";);

* 在末尾弹出某值 *

$popped = array_pop($fruitarray);

* 列出新数组内容,以及弹出的值*

while (list($key,$value) = each($fruitarray)) {

echo ";$key : $value<;br>;";;

}

echo ";<;br>;and finally, in $popped: $popped";;

?>;

这将显示:

0 : apple

1 : orange

2 : banana

3 : kiwi

and finally, in $popped: pear

next, delete an element from the end of an array: ???????????

下面,从数组末尾删除某值:

<;?

* 创建一数组*

$fruitarray = array(";apple";, ";orange";, ";banana";, ";kiwi";, ";pear";);

* 从数组头部移出某值 *

$shifted = array_shift($fruitarray);

* 列出新数组的内容以及移出的值*

while (list($key,$value) = each($fruitarray)) {

echo ";$key : $value<;br>;";;

}

echo ";<;br>;and finally, in $shifted: $shifted";;

?>;

这将显示:

0 : orange

1 : banana

2 : kiwi

3 : pear

and finally, in $shifted: apple

有很多函数可以帮助你对数组元素排序。但我将会演示基本的排序以帮助你了解其过程:

<;? * 创建原始数组 *

$fruitarray = array(";apple";, ";orange";, ";banana";, ";kiwi";, ";pear";);

* 排序 *

sort($fruitarray);

* 对其重设以正确从头到尾显示数组 *

* 通过其键值列出每个元素*

while (list($key,$value) = each($fruitarray)) {

echo ";$key : $value<;br>;";;

}

?>;

这将显示:

0 : apple

1 : banana

2 : kiwi

3 : orange

4 : pear

抱歉!评论已关闭.