三、文件是我们的朋友
;V(- ;O mG4myQ?$ 无论你在开发的网站规模的大小,都应该意识到代码重用的重要性,无论这些代码是HTML、还是PHP代码。例如,你必须至少每年改变一次包含版权信息的页脚,如果你的网站含有1000个页面,每年修改一次也是个很烦人的事儿。
XMb]&VvH nR)/k,3W 在PHP中,至少有几个函数可以帮助你实现代码重用的目的,所使用的函数取决于你所重用的代码,主要的函数有:
1e`/N+6u x`8rR;N! * include() and include_once()
rU?sUm,ch * require() and require_once()
.`Ey'T_ include()函数包含并对给定的文件进行计算,例如:
?sQOz[ig; include('/home/me/myfile');
;,T3C:S? tpe:]T/xh 在include文件中的任何代码都在include()出现的代码范围内执行,你可以通过联合使用include()和fopen()在自己的服务器上包含静态文件,在另一台服务器上包含目标文件。
*,$cW,LN 9(?9yFbj5 include_once()的功能与include()相同,二者之间的区别在于它会检查一个文件中的代码是否已经包含在现有的脚本中,如果代码已经存在,则不会再次包含它。
Cz=HxU80J )cA#2mlS'1 require()函数用给定文件的内容取代它本身,这一代替过程发生在PHP引擎编译代码期间,而不是在执行期间进行,它不象include()那样会首先进行计算。require()函数更多地用在静态元素中,而include()更多地用于动态元素中。与include_once()类似的是,require_once()将首先检查是否已经插入给定的代码,如果代码已经存在,就不再插入了。
Jy&O4g/'5 uq<kT [ 为也了解其内容,在版权信息、静态文字和其他不包含变量的元素或者依赖其他正在执行的脚本的元素中我更趋向于使用require函数。例如:
+We_[Re`< 0TA{E-A DBDHe-1[+ &YQ \l^L?69 [a lot of content]
r[xj,eIb // insert copyright
\_?A8F require('/home/me/mycopyright');
VwfeaDJw ?>
)eFXjnHN #clOpyT* Jt79M(Hp! ; MU8@?yN 另一方面,我经常在文件的开始使用include()来控制许多的函数:
C[f'1O7 Xup rl2+ //得到函数库
w,hl<=:(FB include('/home/me/myfunctions');
^mWOQ*zi; // do PHP things with my functions ?>
/Qh C9^[A4O@X! 3WdYDv]N}L \)Sa!XLfT [a lot of content]
+<5q8{]Pk , &>LBdG` %LBa;M H#pl&/+ 下一个问题就该是“include和require文件在哪里?”,对这个问题简单的回答是,“系统中的任意地方。”如果你的代码中包含有带有用户名和口令的数据库连接,你肯定不会将它们都放在文档根目录中向所有的人都开放。
g)7~vm2/, nx#0*r}5 included或required文件可以在系统上的任何地方,只要PHP运行的系统上的用户可以访问这些文件即可,你可以使这些文件具有任何后缀,或者不使用后缀。
NQQ+l0txI V+#Sb 使用include()和require()对在网站中的元素进行具体化是一种普遍的现象,并在需要对网站升级时,给你带来很大的方便。
zTtn`j$ p<b//^ 四、PHP和文件系统的维护
p=F!)TnJN BJGL &N PHP中有许多与文件系统有关的函数,这些函数不仅可以打开文件,还可以显示目录中的内容、移动文件和其他一些功能,许多人甚至用PHP开发基于互联网的文件资源管理器。
5,/rh,? 3m
RP.<= 关于文件路径的解释:在Windows中,可以在路径中使用/和符号,而在其他的操作系统中只能使用/符号。出于一致性的缘故,我们统一使用/符号。
*v1M^grKd 2aQR#lcv 下面的脚本样例可以显示一个目录清单,注释已经包含在代码中:
B|%(0j8 ,(d\! T/]' $dir_name = "/home/me/";
:
utY4 /* 创建一个句柄,其值是打开一个给定目录的结果*/
Jg3OMUt $dir = opendir($dir_name);
AY]dwKw /* 建立一个文字块,用以放置列表元素(文件名字)*/
-$W#bqvz^ $file_list = "
Co|3k:I 8 ";
0=N,y /* 使用一个while语句,读取已经打开的目录中的所有元素,如果文件的名字不是“.”或“..”,则显示列表中的名字*/
>eX&HS oy while ($file_name = readdir($dir)) {
GM&< ?K1 if (($file_name != ".") && ($file_name != "..")) {
HgH\2QL3& $file_list .= "
4n55{?Z $file_name";
j\W"P_ dpd }
e/+_tC$@p@ }
3khsGD@ $file_list .= "
l&rS\TCkp ";
ITcgpK6k /*关闭打开的目录,结束PHP模块*/
MBy0Ky closedir($dir);
k'O^HMAn! ?>
VaYL#\;c< Swugt"`nN f
uzz3# )`,||sQ f3,qDbQyJ >Z0F n xJCMxt2Y X[' VZz7 E
P1f6ps Files in:
71euRIW'5 Be~__pd nV/8u_ zK Rt\;PW 2~`lvx @9,=|kxK R]dN-'U N.\?"n 好了,我们已经得到了一个目录清单。需要注意的是,要读取一个文件(稍后我们将进行讲解)或目录的内容,PHP运行的系统上的用户必须至少有读取文件的权限。
jb0wP01R 下面是一个如何拷贝文件的例子:
T@K=
*p ~_l@
_P5yz $original = "/home/me/mydatabasedump";
-PfBL8 $copied = "/archive/mydatabasedumo_1010";
54[#&T$S /* 使用copy()函数拷贝原始文件,如果拷贝没有完成则会显示一个错误信息*/
z1dSZ0NoA @copy($original, $copied) or die("Couldn't copy file.");
e}@VR<h ?>
U.XvS''E G
=`-w 这个例子是一个文件备份系统的原型。在这段脚本运行时,它把文件拷贝到一个不同的位置进行保存。稍微修改一下守护程序,就可以在一天中你指定的时刻执行它,而无需用户的干预。
fU/&e^,
's O|Sbe%[*wW 假定你在系统上安装了Lynx,可以创建一个守护程序的条目访问这个文件,访问这个文件会运行这个脚本并建立一个拷贝文件,下面的例子将在上午5点钟运行这个脚本,然后关闭Lynx:
}kJfTsFS 0 5 * * * [username] lynx -dump
http://localhost/copyfile.php 1>/dev/null 2>&1
n ~c<[ 如果运行的是CGI版本的PHP,可以跳过Lynx部分,而直接调用二进制文件:
;Dh\2! sr 0 5 * * * [username] php /path/to/copyfile.php 1>/dev/null 2>&1
z@bq*':~J ++9?LH4S4 五、丰富的数组函数
DIsK+1 m1pge4* PHP 4.0中新添加了30个与组数有关的函数,其中一些常见的函数可以判断一个数组中是否包含某个元素,对一个数组中的元素进行计数,添加或删除数组中的元素或者对数组中的元素进行排序。
u{|
Q[hf[ PjwDth
A1 如果有一个很大的数组,而你需要找出其中是否包含一个特定的元素,就可以使用in_array()。下面的例子将显示“Not found in this array”,因为在一个名字为$namesArray的数组中查找Albert,而在$namesArray数组中不存在这样一个元素。
QoLp$1O(y d_v]mfUF $lookingFor = "Albert";
ko-3`hX` if (in_array($lookingFor, $namesArray)) {
[j3-a4Wu echo "You've found it!";
$,Eb(j } else {
e0s* echo "Not found in this array!";
9Wu c1# }
pyHU+B ?>
3o_)x _\/KI
/ 如果把$lookingFor的值改为Mary,就会得到“You've found it!”的信息,因为Mary是$namesArray数组中的一个元素。
mS$9D{ [zC1LTXe 如果要对一个数组中的元素个数进行计数,只要简单地使用count()函数即可:
CdEQiu EF>vu+YK $count = count($namesArray); ?>
]|JQH IOfxx>=3 返回的$count的值为7。
_h6j, ) <QuIX A 可以在一个数组的开头或结尾处添加元素,还可以使用array_merge()来建立一个包含二个或更多数组中元素的新数组,合并时,元素的顺序会按指定的顺序排列,如果原来的数组是被排过序的,在合并后需要对它重新排序。
V8w7U:K 8+f{ / 我们可以首先利用array_push()在数组的结尾处添加一个元素:
rt rPRR\:" Sb4^*
$uz $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
0sMNp /* 向数组中添加元素 */
hD>]\u array_push($fruitArray, "grape", "pineapple", "tomato");
0Cg}yy Oz /*显示每个元素及其序号*/
h 8%(,$* while (list($key,$value) = each($fruitArray)) {
&9+]{jXF echo "$key : $value
ZZs@P#] ";
us5<18M5 }
Fe[)-_%G ?>
h6CAd-\x\ %`EyG 运行上面的程序将得到下面的结果:
^4 MJ 0 : apple
-(dtAo6 1 : orange
Wtwo1pp 2 : banana
pD@:]VP 3 : kiwi
|2Vhj<6 4 : pear
]KQv]' 5 : grape
9T\uOaC" 6 : pineapple
@$Xl*WT7 7 : tomato
VGYx( k~0#Iy_{M 如果需要在数组的开头添加元素,其代码与上面的代码差不多,唯一的不同之处是需要用array_unshift()代替array_push()。
r* q cv{icz,%w /* 建立一个数组*/
3u 'VPF2 $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
7"_m?c8 /* 向数组中添加元素*/
zb]e{$q2C array_unshift($fruitArray, "grape", "pineapple", "tomato");
QkFB\v /* 显示每个元素及其序号*/
aZ,j1j0p while (list($key,$value) = each($fruitArray)) {
-lY,lC>{ echo "$key : $value
m
>Rdsn~l ";
A_!N,<- }
'^n,)oA/G ?>
.Ei#mG-=}& 运行上面的程序将得到下面的结果:
}WA= !.G knDT 0 : grape
cMfJq}C< 1 : pineapple
3jqV/w[- 2 : tomato
#0"Pd8@ 3 : apple
e**<et. 4 : orange
*g*~+B
: 5 : banana
\y(ZeNs 6 : kiwi
Z<jC,r 7 : pear
%A3ci[$g array_merge()函数可以把二个或更多的数组合并为一个数组。
2/iBk'd B:>>D/O $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
?NVX# t' /*/建立第二个数组*/
qEvbKy} $vegArray = array("carrot", "green beans", "asparagus", "artichoke", "corn");
Zv0'OX~8i /*把这二个数组合并为一个数组*/
{'-^CoR $goodfoodArray = array_merge($fruitArray, $vegArray);
%{|67h /* 显示每个元素及其序号*/
zH13~\ while (list($key,$value) = each($goodfoodArray)) {
6Y%{ YQ}s| echo "$key : $value
2@6Qifxd@ ";
Ueu~803~ }
Lp7h'|]u ?>
h+c9FN i*]$_\yl" 运行上面的脚本将得到下面的结果:
HEk{!Y ,rNv} 0 : apple
Ihd{tmr< 1 : orange
o(gV;>I 2 : banana
vn+~P9SHQ 3 : kiwi
~<Z7\yS) 4 : pear
.T1n"TfsGO 5 : carrot
)GKY#O09x9 6 : green beans
wpI"kk_@@ 7 : asparagus
pkE4"M!3= 8 : artichoke
UL.YDU) 9 : corn
AZE DC~ 1}|B" 现在我们已经掌握了如何添加元素和合并数组,我们再来看看如何从一个数组中删除元素。从一个数组的末尾删除一个元素可以使用array_pop()函数,使用array_shift()函数可以从一个数组的开头删除一个元素。尽管使用array_pop()或 array_shift()从数组中删除了一个元素,你还可以把这个元素当作一个变量来使用。
T8BewO=} I vX+yU 使用array_pop()从一个数组的末尾删除一个元素:
~_F <"40 /*建立一个数组*/
+w2 ` $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
l*z+<c6$_ /* 从数组的末尾删除一个元素*/
\>tx:;D3 $popped = array_pop($fruitArray);
C)mR~Ey /* 显示删除后数组的内容和你删除的元素*/
KTE X] while (list($key,$value) = each($fruitArray)) {
V6bjVd9|Z echo "$key : $value
#=T^XHjQ ";
#0f6X,3 }
2xBYJoF( echo "
]-sgzM]q and finally, in $popped: $popped";
^&lkh@Y1q ?>
p4@0[z' cl'wQ1<:
运行上面的脚本会得到下面的结果:
'si{6t| 0 : apple
GP(ze-Yp 1 : orange
#0:rBKm, 2 : banana
/?1^&a 3 : kiwi
[a!)w@I: and finally, in $popped: pear
]m :Y|,:6 n= q7*<l 我们再来讨论一个从一个数组的末尾删除元素的例子:
6@;sOiN+ ,FwJ0V /* 建立一个数组*/
uE}$ZBiq $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
X>i{288M3 /*从一个数组的开始删除一个元素*/
tZY6{,K%4 $shifted = array_shift($fruitArray);
;YZ'd"0v /* 显示删除后数组的内容和你删除的元素*/
C^fn[plL while (list($key,$value) = each($fruitArray)) {
&
h\!#X0 echo "$key : $value
*mz-g7 ";
!E6QED" }
N<O<wtXIj echo "
iB}*<~`.Eg and finally, in $shifted: $shifted";
KJv[z ?>
F+]cFx,/ Ri>ZupQ6 运行上述脚本会得到如下的显示结果:
bs'hA@r 0 : orange
XM) 1 : banana
WIN3*z7oW 2 : kiwi
as(Zb*PdH 3 : pear
4>Y*owa4 and finally, in $shifted: apple
9TZ 6c eVzZfB-=4} 另外还有几个函数可以对数组中的元素进行排序,但在这里我们将只简要介绍基本的排序函数,说明排序的过程:
r%9=75HA Wjli(sT#- $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
$|N\(}R /* 对数组进行排序*/
? ph>:M sort($fruitArray);
ovZ!} /*显示每个元素及其序号*/
)|GYxG;8C while (list($key,$value) = each($fruitArray)) {
~|S}$|Mi50 echo "$key : $value
F#~*j ";
?1**@E0 }
'A9Z (( ?>
>IipWTVo< 9TbbIP1 运行上述的脚本会得到如下的显示结果:
T@Z-;^aV RWFvf 0 : apple
PU4-}!K 1 : banana
LKA/s ~G 2 : kiwi
pjma<^|F 3 : orange
[@2$W?0i 4 : pear