三、文件是我们的朋友
6nh!g <+ UEM~) 无论你在开发的网站规模的大小,都应该意识到代码重用的重要性,无论这些代码是HTML、还是PHP代码。例如,你必须至少每年改变一次包含版权信息的页脚,如果你的网站含有1000个页面,每年修改一次也是个很烦人的事儿。
4Gs#_|! yQE|FbiA 在PHP中,至少有几个函数可以帮助你实现代码重用的目的,所使用的函数取决于你所重用的代码,主要的函数有:
kcKcIn{ lo*OmAF * include() and include_once()
AE`X4 q * require() and require_once()
i2KN^"v?N include()函数包含并对给定的文件进行计算,例如:
'?dO[iQ$: include('/home/me/myfile');
D+ mZ7&L 2g~qVT, 在include文件中的任何代码都在include()出现的代码范围内执行,你可以通过联合使用include()和fopen()在自己的服务器上包含静态文件,在另一台服务器上包含目标文件。
RUqN,C,m5I &5puGnTZ include_once()的功能与include()相同,二者之间的区别在于它会检查一个文件中的代码是否已经包含在现有的脚本中,如果代码已经存在,则不会再次包含它。
VZo[\sWf ,Oa-AF/p require()函数用给定文件的内容取代它本身,这一代替过程发生在PHP引擎编译代码期间,而不是在执行期间进行,它不象include()那样会首先进行计算。require()函数更多地用在静态元素中,而include()更多地用于动态元素中。与include_once()类似的是,require_once()将首先检查是否已经插入给定的代码,如果代码已经存在,就不再插入了。
stuj,8 /5Aum?~ 为也了解其内容,在版权信息、静态文字和其他不包含变量的元素或者依赖其他正在执行的脚本的元素中我更趋向于使用require函数。例如:
eygmh aE +\g/KbV7 jGpSECs C(zgBk |f), dC [a lot of content]
Q ^X // insert copyright
|{W4JFKJ require('/home/me/mycopyright');
VuA7rIF$66 ?>
k7JE{(Ok
0$)s? \ q1ybJii "%fh`4y3\ 另一方面,我经常在文件的开始使用include()来控制许多的函数:
r09gB#K4 873$EiyXR //得到函数库
zQ3m@x include('/home/me/myfunctions');
+GCN63nX // do PHP things with my functions ?>
{hQ0=rv< XN9s!5A<L) Y~\71QE> HT&CbEa4' [a lot of content]
&
$E[l' uQh dg4 X[/>{rK 0VsQ$4'V^ 下一个问题就该是“include和require文件在哪里?”,对这个问题简单的回答是,“系统中的任意地方。”如果你的代码中包含有带有用户名和口令的数据库连接,你肯定不会将它们都放在文档根目录中向所有的人都开放。
?>c*[>LpZ x`T included或required文件可以在系统上的任何地方,只要PHP运行的系统上的用户可以访问这些文件即可,你可以使这些文件具有任何后缀,或者不使用后缀。
]<b$k Uytq,3Gj6 使用include()和require()对在网站中的元素进行具体化是一种普遍的现象,并在需要对网站升级时,给你带来很大的方便。
np2oXg% fkf69,+"] 四、PHP和文件系统的维护
V]I@&*O~r Gl8D
GELl; PHP中有许多与文件系统有关的函数,这些函数不仅可以打开文件,还可以显示目录中的内容、移动文件和其他一些功能,许多人甚至用PHP开发基于互联网的文件资源管理器。
R_9 &V!fl S(NH# ^ 关于文件路径的解释:在Windows中,可以在路径中使用/和符号,而在其他的操作系统中只能使用/符号。出于一致性的缘故,我们统一使用/符号。
t8X$M;$ LXYpP-E 下面的脚本样例可以显示一个目录清单,注释已经包含在代码中:
6v8HR}iK yg({g
" $dir_name = "/home/me/";
m$<LO%<~p /* 创建一个句柄,其值是打开一个给定目录的结果*/
HYVSi3[ $dir = opendir($dir_name);
^u'hl$`^ /* 建立一个文字块,用以放置列表元素(文件名字)*/
"XPBNv\>_ $file_list = "
,b[}22 ";
$!Z><&^/ /* 使用一个while语句,读取已经打开的目录中的所有元素,如果文件的名字不是“.”或“..”,则显示列表中的名字*/
l{b<rUh5W while ($file_name = readdir($dir)) {
s18o,Zs' if (($file_name != ".") && ($file_name != "..")) {
k=;>*:D% $file_list .= "
;:<z hO $file_name";
|;xm-AM4r }
A/5??3H }
fM,!9}< $file_list .= "
e7e6b-"_2 ";
<Z{pjJ/ /*关闭打开的目录,结束PHP模块*/
k(hYNmmo
j closedir($dir);
HI iMq'H^ ?>
#a1zk\R3 LX<arHz V~#e%&73FH W|@7I@@$" <JtH/oN Bmx+QO w2*.3I,~)B 1{6 BU! %8c
<C Files in:
V11(EZJ/j NUxOU>f OJ#ehw < j,<3[ W,sU5sjA D5]AL5=Xt2 -64@}Ts*? wVegr 好了,我们已经得到了一个目录清单。需要注意的是,要读取一个文件(稍后我们将进行讲解)或目录的内容,PHP运行的系统上的用户必须至少有读取文件的权限。
0|6]ps4Z7 下面是一个如何拷贝文件的例子:
~K'e}<-G feJzX*u $original = "/home/me/mydatabasedump";
9Z?P/
o $copied = "/archive/mydatabasedumo_1010";
M:t!g% /* 使用copy()函数拷贝原始文件,如果拷贝没有完成则会显示一个错误信息*/
l^`& Tnzv @copy($original, $copied) or die("Couldn't copy file.");
`Fn"%P! ?>
Q`?+w+y7 'iQ 这个例子是一个文件备份系统的原型。在这段脚本运行时,它把文件拷贝到一个不同的位置进行保存。稍微修改一下守护程序,就可以在一天中你指定的时刻执行它,而无需用户的干预。
&d,chb( ~nit~; 假定你在系统上安装了Lynx,可以创建一个守护程序的条目访问这个文件,访问这个文件会运行这个脚本并建立一个拷贝文件,下面的例子将在上午5点钟运行这个脚本,然后关闭Lynx:
?yAp&Ad 0 5 * * * [username] lynx -dump
http://localhost/copyfile.php 1>/dev/null 2>&1
'Cki"4%< 如果运行的是CGI版本的PHP,可以跳过Lynx部分,而直接调用二进制文件:
'u9,L FO 0 5 * * * [username] php /path/to/copyfile.php 1>/dev/null 2>&1
8H2zMIB 3k YVk 五、丰富的数组函数
N$'/J-^ q%H`/~AYM PHP 4.0中新添加了30个与组数有关的函数,其中一些常见的函数可以判断一个数组中是否包含某个元素,对一个数组中的元素进行计数,添加或删除数组中的元素或者对数组中的元素进行排序。
kg,t[Jl S8=Am7D]1 如果有一个很大的数组,而你需要找出其中是否包含一个特定的元素,就可以使用in_array()。下面的例子将显示“Not found in this array”,因为在一个名字为$namesArray的数组中查找Albert,而在$namesArray数组中不存在这样一个元素。
$ghAC yH`4sd $lookingFor = "Albert";
NO$n-<ag if (in_array($lookingFor, $namesArray)) {
( mV *7Z echo "You've found it!";
sb1Zm*m6 } else {
u_kcuN\Sq
echo "Not found in this array!";
ceiUpWMu, }
k8>(-W"A ?>
}s*H|z mT]+wi& 如果把$lookingFor的值改为Mary,就会得到“You've found it!”的信息,因为Mary是$namesArray数组中的一个元素。
8]SJ=c"}Xf woSO4e/ 如果要对一个数组中的元素个数进行计数,只要简单地使用count()函数即可:
v %?y5w p#14 $count = count($namesArray); ?>
bxxazsj^ ';H"Ye:D=7 返回的$count的值为7。
O
&/9wi>!q :ik$@5wp 可以在一个数组的开头或结尾处添加元素,还可以使用array_merge()来建立一个包含二个或更多数组中元素的新数组,合并时,元素的顺序会按指定的顺序排列,如果原来的数组是被排过序的,在合并后需要对它重新排序。
Z)V m,ng yQP!Vt^ 我们可以首先利用array_push()在数组的结尾处添加一个元素:
aJ!(c}N~97 xXa* d $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
S7|6dwQ& /* 向数组中添加元素 */
JA=9EnTU array_push($fruitArray, "grape", "pineapple", "tomato");
C-wwQbdG/ /*显示每个元素及其序号*/
m7~<z>5$ while (list($key,$value) = each($fruitArray)) {
0LX"<~3j echo "$key : $value
Sn o7Ru2 ";
/6?A#%hc }
,s=jtK ?>
/ 7i>0J] JPo.&5k 运行上面的程序将得到下面的结果:
n jfh4}g: 0 : apple
y#Cp Vm#!> 1 : orange
#F>7@N:5 2 : banana
^*6So3 3 : kiwi
os:/-A_m 4 : pear
] ^f7s36 5 : grape
8|-j]
6 : pineapple
gKp5* 7 : tomato
S%NS7$`a M-#OPj* 如果需要在数组的开头添加元素,其代码与上面的代码差不多,唯一的不同之处是需要用array_unshift()代替array_push()。
Lg;b17 y15 MWZ /* 建立一个数组*/
[>P9_zID $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
KC"# /* 向数组中添加元素*/
%1Ex{H hb array_unshift($fruitArray, "grape", "pineapple", "tomato");
7m4gGkX#r /* 显示每个元素及其序号*/
4yZ'+\ +I while (list($key,$value) = each($fruitArray)) {
E?VPCx echo "$key : $value
0r4,27w ";
R04%;p:k# }
k!&G; 6O- ?>
FJ/>=2^B 运行上面的程序将得到下面的结果:
Z$UPLg3=;_ 2&e2/KEWR 0 : grape
\+?>KpE,b 1 : pineapple
[RAzKzC\M 2 : tomato
Fi7G S; 3 : apple
rNi]|)-ET 4 : orange
$ 8"we 5 : banana
t:NYsL 6 : kiwi
tQ,,krw~ 7 : pear
(31ia"i% array_merge()函数可以把二个或更多的数组合并为一个数组。
c
`[,> |"K< $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
*Ce8(
"v, /*/建立第二个数组*/
1v<,nABuJ6 $vegArray = array("carrot", "green beans", "asparagus", "artichoke", "corn");
yN'<iTh /*把这二个数组合并为一个数组*/
`[OJ)tHE $goodfoodArray = array_merge($fruitArray, $vegArray);
cWNZ +Q8Y /* 显示每个元素及其序号*/
]JQ+*ZYUE while (list($key,$value) = each($goodfoodArray)) {
[lU0TDq echo "$key : $value
MD"a%H#p ";
NWSm }
)aV\=a |A ?>
T[~8u9/ A#b`{C~l 运行上面的脚本将得到下面的结果:
}\iH ~T6 P#0U[`ltK 0 : apple
pBZf=!+E 1 : orange
(0wQ [( 2 : banana
"e3T;M+ 3 : kiwi
i 4}4U 4 : pear
WxLmzSz{xD 5 : carrot
RJYB=y8l 6 : green beans
P"Scs$NOU? 7 : asparagus
zeC@!,lH 8 : artichoke
Z(|@C(IL0\ 9 : corn
mQbpv'N Mk3~%` 现在我们已经掌握了如何添加元素和合并数组,我们再来看看如何从一个数组中删除元素。从一个数组的末尾删除一个元素可以使用array_pop()函数,使用array_shift()函数可以从一个数组的开头删除一个元素。尽管使用array_pop()或 array_shift()从数组中删除了一个元素,你还可以把这个元素当作一个变量来使用。
`Kt]i5[ " wsfN \6e 使用array_pop()从一个数组的末尾删除一个元素:
zL^`r)H /*建立一个数组*/
Ky r3)1#J $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
O_E\(So /* 从数组的末尾删除一个元素*/
z1K}] z% $popped = array_pop($fruitArray);
7EfLd+ /* 显示删除后数组的内容和你删除的元素*/
=6sA49~M while (list($key,$value) = each($fruitArray)) {
+i\ +bR echo "$key : $value
A`#/:O4|f ";
7Gos-_s }
b0PQ;?R#V echo "
wt@Qjbqd8 and finally, in $popped: $popped";
LR(Q.x ?>
TKwMgC}<[ N!W# N$ 运行上面的脚本会得到下面的结果:
5xS
ze; 0 : apple
eU*0;# 1 : orange
>`0l"K< 2 : banana
:2Fy`PPab 3 : kiwi
Iu)76Y@=5= and finally, in $popped: pear
M%3P@GRg i[+cNJ|$B0 我们再来讨论一个从一个数组的末尾删除元素的例子:
A89n^@ #"T< mM7 /* 建立一个数组*/
Ej[:!L $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
Y , /*从一个数组的开始删除一个元素*/
1#Ls4+]5 $shifted = array_shift($fruitArray);
03%`ouf /* 显示删除后数组的内容和你删除的元素*/
7])cu>/ while (list($key,$value) = each($fruitArray)) {
8E/wUN,Lxj echo "$key : $value
Au=9<WB%H ";
Q#h*C
ZT }
`U.VfQR: echo "
\{GBaMwG~ and finally, in $shifted: $shifted";
vMlT ?>
3iKy> \ZOH3`vq 运行上述脚本会得到如下的显示结果:
+,g"8&> 0 : orange
K1_]ne)
1 : banana
mDCz=pk) 2 : kiwi
pxuZ=< 3 : pear
YKWiZ and finally, in $shifted: apple
dF`\ewRFn +A!E 6+' 另外还有几个函数可以对数组中的元素进行排序,但在这里我们将只简要介绍基本的排序函数,说明排序的过程:
fr19C%{ Li? _P5+a $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
xn&$qLB /* 对数组进行排序*/
@)IHd6 R sort($fruitArray);
qH8d3?1XO /*显示每个元素及其序号*/
|_}
LMkU) while (list($key,$value) = each($fruitArray)) {
,Fv8&tR echo "$key : $value
#^] v5s ";
4PcsU HR }
6-+q3#e ?>
N Dqvt$ C4].egVg 运行上述的脚本会得到如下的显示结果:
2!Gb4V O^2@9
w 0 : apple
/uNgftj 1 : banana
W5f|#{&L: 2 : kiwi
lQq&tz, 3 : orange
Eq\PSa=gz 4 : pear