三、文件是我们的朋友
3#LlDC_WC Ouk^O}W6 无论你在开发的网站规模的大小,都应该意识到代码重用的重要性,无论这些代码是HTML、还是PHP代码。例如,你必须至少每年改变一次包含版权信息的页脚,如果你的网站含有1000个页面,每年修改一次也是个很烦人的事儿。
Vr3Zu{&2 KjD/o?JUr 在PHP中,至少有几个函数可以帮助你实现代码重用的目的,所使用的函数取决于你所重用的代码,主要的函数有:
{&&z-^ ?g_3 [Fk * include() and include_once()
W: z6Koc0 * require() and require_once()
'TTLo|@"- include()函数包含并对给定的文件进行计算,例如:
G<L;4nA) include('/home/me/myfile');
{5Q!Y&N.% E^B'4 在include文件中的任何代码都在include()出现的代码范围内执行,你可以通过联合使用include()和fopen()在自己的服务器上包含静态文件,在另一台服务器上包含目标文件。
L^1NY3=$ (>LF(ll include_once()的功能与include()相同,二者之间的区别在于它会检查一个文件中的代码是否已经包含在现有的脚本中,如果代码已经存在,则不会再次包含它。
?tWaI{95I Yj&F;_~ require()函数用给定文件的内容取代它本身,这一代替过程发生在PHP引擎编译代码期间,而不是在执行期间进行,它不象include()那样会首先进行计算。require()函数更多地用在静态元素中,而include()更多地用于动态元素中。与include_once()类似的是,require_once()将首先检查是否已经插入给定的代码,如果代码已经存在,就不再插入了。
)v'WWwXY> 0_jf/an,% 为也了解其内容,在版权信息、静态文字和其他不包含变量的元素或者依赖其他正在执行的脚本的元素中我更趋向于使用require函数。例如:
\[;0KV_ )*$lp'~7N O%\*@4zM fBU`k_ 0Um2DjTCG [a lot of content]
d-oMQGOklb // insert copyright
!Jo_"#5 require('/home/me/mycopyright');
]vAz ?>
t*p71U4+I tR#OjkvX '+@=ILj> akmkyrz '& 另一方面,我经常在文件的开始使用include()来控制许多的函数:
#$.;'#u'so ]_)yIi" //得到函数库
CXH&U@57{ include('/home/me/myfunctions');
bTI|F]^! // do PHP things with my functions ?>
?e%ZOI lt/1f{v[: 1y:-N6 W8G,=d}6 [a lot of content]
FUiRTRIYe Pd8![Z3 8=!D$t\3 0-B5`=yU 下一个问题就该是“include和require文件在哪里?”,对这个问题简单的回答是,“系统中的任意地方。”如果你的代码中包含有带有用户名和口令的数据库连接,你肯定不会将它们都放在文档根目录中向所有的人都开放。
XgZD%7 4j* included或required文件可以在系统上的任何地方,只要PHP运行的系统上的用户可以访问这些文件即可,你可以使这些文件具有任何后缀,或者不使用后缀。
u2tfF !hm]fh_j 使用include()和require()对在网站中的元素进行具体化是一种普遍的现象,并在需要对网站升级时,给你带来很大的方便。
y#`tgJ: qv-8)MSr 四、PHP和文件系统的维护
m&d|t>3< @="Pn5<]C PHP中有许多与文件系统有关的函数,这些函数不仅可以打开文件,还可以显示目录中的内容、移动文件和其他一些功能,许多人甚至用PHP开发基于互联网的文件资源管理器。
___~D
dq Mc) }\{J 关于文件路径的解释:在Windows中,可以在路径中使用/和符号,而在其他的操作系统中只能使用/符号。出于一致性的缘故,我们统一使用/符号。
aEB_#1 <;lkUU(WT2 下面的脚本样例可以显示一个目录清单,注释已经包含在代码中:
[|v][Hwv L7l
FtX+b $dir_name = "/home/me/";
t^&Cxh /* 创建一个句柄,其值是打开一个给定目录的结果*/
.7J#_*NV $dir = opendir($dir_name);
RTYvS5G /* 建立一个文字块,用以放置列表元素(文件名字)*/
<3nMx^ $file_list = "
)Om*@;r( ";
~-k9%v` /* 使用一个while语句,读取已经打开的目录中的所有元素,如果文件的名字不是“.”或“..”,则显示列表中的名字*/
jVi) Efy while ($file_name = readdir($dir)) {
td$E/h=3 if (($file_name != ".") && ($file_name != "..")) {
IYv`IS" $file_list .= "
X;$+,&M" $file_name";
_T60;ZI+^ }
'B|JAi? }
6%' QjwM_ $file_list .= "
MxKS4k ";
$z6_@`[ /*关闭打开的目录,结束PHP模块*/
GblA9F7 closedir($dir);
Y/F6\oh ?>
KR}?H#% 9+|$$) KM,\ Cp\6W[2+B poE0{HOU ~g91Pr #<fRE"v:Q ZtNN<7 (g]!J_Z" Files in:
8\^R~K`sY Xg6Jh`` 9X6h Ov@gh
kr }CSDV9).S
1~gnc|? l$KA)xbI t9lPb_70 好了,我们已经得到了一个目录清单。需要注意的是,要读取一个文件(稍后我们将进行讲解)或目录的内容,PHP运行的系统上的用户必须至少有读取文件的权限。
FaAC&F@u 下面是一个如何拷贝文件的例子:
MpT8" /.]A Q0sI(V# $original = "/home/me/mydatabasedump";
hgG9m[?K $copied = "/archive/mydatabasedumo_1010";
:
$1?i) /* 使用copy()函数拷贝原始文件,如果拷贝没有完成则会显示一个错误信息*/
8S
TvCH"Z_ @copy($original, $copied) or die("Couldn't copy file.");
"x0^#AVg ?>
b/K PaNv [jQp~&nY 这个例子是一个文件备份系统的原型。在这段脚本运行时,它把文件拷贝到一个不同的位置进行保存。稍微修改一下守护程序,就可以在一天中你指定的时刻执行它,而无需用户的干预。
&u."A3( `7E;VL^Y1 假定你在系统上安装了Lynx,可以创建一个守护程序的条目访问这个文件,访问这个文件会运行这个脚本并建立一个拷贝文件,下面的例子将在上午5点钟运行这个脚本,然后关闭Lynx:
T=DbBy0- 0 5 * * * [username] lynx -dump
http://localhost/copyfile.php 1>/dev/null 2>&1
^dWa;m]l 如果运行的是CGI版本的PHP,可以跳过Lynx部分,而直接调用二进制文件:
jVe1b1rt~3 0 5 * * * [username] php /path/to/copyfile.php 1>/dev/null 2>&1
bL`TySX LENq_@$ 五、丰富的数组函数
bIDj[-CDG _;S-x PHP 4.0中新添加了30个与组数有关的函数,其中一些常见的函数可以判断一个数组中是否包含某个元素,对一个数组中的元素进行计数,添加或删除数组中的元素或者对数组中的元素进行排序。
>NV@R& zaIKdI'/e 如果有一个很大的数组,而你需要找出其中是否包含一个特定的元素,就可以使用in_array()。下面的例子将显示“Not found in this array”,因为在一个名字为$namesArray的数组中查找Albert,而在$namesArray数组中不存在这样一个元素。
fUWG*o9 ,Zx0%#6 $lookingFor = "Albert";
z_$% -6 if (in_array($lookingFor, $namesArray)) {
Y(ykng echo "You've found it!";
3DX*gsx( } else {
^CYl\.Y@ echo "Not found in this array!";
Qp5VP@t }
;+R&}[9,A) ?>
ma]F7dZ5 ZDJ`qJ8V 如果把$lookingFor的值改为Mary,就会得到“You've found it!”的信息,因为Mary是$namesArray数组中的一个元素。
,Fl)^Gl8? gx/,)> E. 如果要对一个数组中的元素个数进行计数,只要简单地使用count()函数即可:
=ZznFVJ`={ 2QcOR4_V $count = count($namesArray); ?>
&J]K3w1p
J[|y:N 返回的$count的值为7。
y-b%T|p9 1s&zMWC 可以在一个数组的开头或结尾处添加元素,还可以使用array_merge()来建立一个包含二个或更多数组中元素的新数组,合并时,元素的顺序会按指定的顺序排列,如果原来的数组是被排过序的,在合并后需要对它重新排序。
z|J_b"u4 HVCe;eI 我们可以首先利用array_push()在数组的结尾处添加一个元素:
eb\K "ec" tKuwpT1Qc $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
"S]0 /* 向数组中添加元素 */
9<?M8_ array_push($fruitArray, "grape", "pineapple", "tomato");
oSKXt}sh /*显示每个元素及其序号*/
2RX;Ob_ while (list($key,$value) = each($fruitArray)) {
}-{H Y echo "$key : $value
8NJqV+jn)t ";
oCv.Ln1;Z }
{w O|)| ?>
m])y.T iq8<ov
运行上面的程序将得到下面的结果:
;4\2.*s 0 : apple
ub0.J#j@ 1 : orange
?zMHP#i 2 : banana
<NY^M! 3 : kiwi
`$IK`O 4 : pear
fplo w 5 : grape
Et_bH%0 6 : pineapple
Lg+Ac5y}` 7 : tomato
+) om^e@. H|<[YYk 如果需要在数组的开头添加元素,其代码与上面的代码差不多,唯一的不同之处是需要用array_unshift()代替array_push()。
;8&3 dm] NiEUW.0 /* 建立一个数组*/
RLXL& $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
,-LwtePJ0 /* 向数组中添加元素*/
NA`SyKtg_ array_unshift($fruitArray, "grape", "pineapple", "tomato");
Q8tL[>Xt /* 显示每个元素及其序号*/
>>)b'c while (list($key,$value) = each($fruitArray)) {
O63<AY@ echo "$key : $value
2wg5#i ";
)EuvRLo{S7 }
uAq~=)F>, ?>
ua$GNm 运行上面的程序将得到下面的结果:
x+:UN'"r mDABH@R 0 : grape
{4}yKjW%z 1 : pineapple
n,(sBOQ 2 : tomato
>8^
$ [}w 3 : apple
X7MM2V 4 : orange
bo>*fNqAIy 5 : banana
{6|G@""O 6 : kiwi
On:il$MU 7 : pear
u%KTNa0 array_merge()函数可以把二个或更多的数组合并为一个数组。
y2dCEmhY D/xbF` $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
TER=*"! /*/建立第二个数组*/
(t
K||*u $vegArray = array("carrot", "green beans", "asparagus", "artichoke", "corn");
3S@7]Pg /*把这二个数组合并为一个数组*/
(`>+zT5aH $goodfoodArray = array_merge($fruitArray, $vegArray);
z,
)6"/; /* 显示每个元素及其序号*/
7kLz[N6Ll while (list($key,$value) = each($goodfoodArray)) {
6vo;!V6 echo "$key : $value
Qj.#)R ";
%nZo4hnr$r }
6I4\q.^qw ?>
qJs<#MQ2 #U4F0BdA 运行上面的脚本将得到下面的结果:
r'r%w#=`t :{v#'U/^ 0 : apple
4jMFr, 1 : orange
6 7.+
.2 2 : banana
(zYtNLoFx 3 : kiwi
{X+3;&