三、文件是我们的朋友
7^hwRZJ{ ?7eD<| 无论你在开发的网站规模的大小,都应该意识到代码重用的重要性,无论这些代码是HTML、还是PHP代码。例如,你必须至少每年改变一次包含版权信息的页脚,如果你的网站含有1000个页面,每年修改一次也是个很烦人的事儿。
Yw!(]8PYdU P}2waJe 在PHP中,至少有几个函数可以帮助你实现代码重用的目的,所使用的函数取决于你所重用的代码,主要的函数有:
2a,l;o$2& $~G=Hcl9 * include() and include_once()
^Gt9. * require() and require_once()
{y\5 9 include()函数包含并对给定的文件进行计算,例如:
Q>QES-.l include('/home/me/myfile');
l2.Lh<G jmkVolz 在include文件中的任何代码都在include()出现的代码范围内执行,你可以通过联合使用include()和fopen()在自己的服务器上包含静态文件,在另一台服务器上包含目标文件。
6@X j \v,mr| include_once()的功能与include()相同,二者之间的区别在于它会检查一个文件中的代码是否已经包含在现有的脚本中,如果代码已经存在,则不会再次包含它。
0*4h}t9j 4k6,pt" require()函数用给定文件的内容取代它本身,这一代替过程发生在PHP引擎编译代码期间,而不是在执行期间进行,它不象include()那样会首先进行计算。require()函数更多地用在静态元素中,而include()更多地用于动态元素中。与include_once()类似的是,require_once()将首先检查是否已经插入给定的代码,如果代码已经存在,就不再插入了。
QPZ|C{Ce FV];od&c 为也了解其内容,在版权信息、静态文字和其他不包含变量的元素或者依赖其他正在执行的脚本的元素中我更趋向于使用require函数。例如:
naaww ^{l^Z
+b. 9FKowF_8 ;*AKeI2 jWE?$r" [a lot of content]
FHv^^u'@ // insert copyright
H}f}Y8J{ require('/home/me/mycopyright');
FVo_=O) ?>
Z{p)rscX \|wUxijJ*, QVq+';cG jjTb:Z=.' 另一方面,我经常在文件的开始使用include()来控制许多的函数:
49Y_ze6L} $KAOJc4< //得到函数库
B{dR/q3;@ include('/home/me/myfunctions');
K:_5#!*^98 // do PHP things with my functions ?>
cZFG~n/ Z<A BK`rEO Q[Xh{B *?<ygzX [a lot of content]
7#G8qh< d:"#_ tpQ?E<O Oh]RIWL 下一个问题就该是“include和require文件在哪里?”,对这个问题简单的回答是,“系统中的任意地方。”如果你的代码中包含有带有用户名和口令的数据库连接,你肯定不会将它们都放在文档根目录中向所有的人都开放。
y<0RgG1qp N#!**Q 0 included或required文件可以在系统上的任何地方,只要PHP运行的系统上的用户可以访问这些文件即可,你可以使这些文件具有任何后缀,或者不使用后缀。
BK/~2u ) Z^b)KAk 使用include()和require()对在网站中的元素进行具体化是一种普遍的现象,并在需要对网站升级时,给你带来很大的方便。
'ai3f 4eh~/o&h 四、PHP和文件系统的维护
X
8#Uk} / k&dLg5O PHP中有许多与文件系统有关的函数,这些函数不仅可以打开文件,还可以显示目录中的内容、移动文件和其他一些功能,许多人甚至用PHP开发基于互联网的文件资源管理器。
z<h?WsL L';b908r2 关于文件路径的解释:在Windows中,可以在路径中使用/和符号,而在其他的操作系统中只能使用/符号。出于一致性的缘故,我们统一使用/符号。
O_bgrXg6x A6faRi703 下面的脚本样例可以显示一个目录清单,注释已经包含在代码中:
A-GU:B ~REP@!\r^ $dir_name = "/home/me/";
TTQ(\l4 /* 创建一个句柄,其值是打开一个给定目录的结果*/
D&C83^m $dir = opendir($dir_name);
1v2pPUH\ /* 建立一个文字块,用以放置列表元素(文件名字)*/
"u=U@1 ^ $file_list = "
qy$1+>f1 ";
]\ DIJ>JZ /* 使用一个while语句,读取已经打开的目录中的所有元素,如果文件的名字不是“.”或“..”,则显示列表中的名字*/
tY>_+)oi while ($file_name = readdir($dir)) {
7sglqf> if (($file_name != ".") && ($file_name != "..")) {
jph"94 $file_list .= "
;"T,3JQPn6 $file_name";
2"IsNbWV }
PS\n0 }
G1z0q3< B $file_list .= "
079mn/8; ";
tg|7\Z7i /*关闭打开的目录,结束PHP模块*/
hY5tBL closedir($dir);
,2*x4Gycb ?>
z!>
H^v @Y| % RX6s[uQ S1&Df%Ra Y[p Rk(2|I )Co&(;zf f0Zn31c^ z pV+W-j] Files in:
JA(M'&q4 KvtX>3#qM "H"4]m1Wc
YgfQ{3^I zhW.0:9
CR fJ8Q\lb<_ !c#~g0H+ A!n)Fpk
好了,我们已经得到了一个目录清单。需要注意的是,要读取一个文件(稍后我们将进行讲解)或目录的内容,PHP运行的系统上的用户必须至少有读取文件的权限。
S#g=;hD 下面是一个如何拷贝文件的例子:
g]a5%8*{ .Km6
(U $original = "/home/me/mydatabasedump";
>?yxig:_ $copied = "/archive/mydatabasedumo_1010";
9 U!-Zn! /* 使用copy()函数拷贝原始文件,如果拷贝没有完成则会显示一个错误信息*/
*B ]5K{N @copy($original, $copied) or die("Couldn't copy file.");
s>+,u7EV ?>
>||=# ; \
W.uV[\ 这个例子是一个文件备份系统的原型。在这段脚本运行时,它把文件拷贝到一个不同的位置进行保存。稍微修改一下守护程序,就可以在一天中你指定的时刻执行它,而无需用户的干预。
DuzJQSv Y%"73.x 假定你在系统上安装了Lynx,可以创建一个守护程序的条目访问这个文件,访问这个文件会运行这个脚本并建立一个拷贝文件,下面的例子将在上午5点钟运行这个脚本,然后关闭Lynx:
}+3v5Nz; 0 5 * * * [username] lynx -dump
http://localhost/copyfile.php 1>/dev/null 2>&1
p^/6Rb"e 如果运行的是CGI版本的PHP,可以跳过Lynx部分,而直接调用二进制文件:
#lo1GoL\ 0 5 * * * [username] php /path/to/copyfile.php 1>/dev/null 2>&1
\pJBBG Zwm2T3@e 五、丰富的数组函数
m
c q!_#{y qQ=\R1l
PHP 4.0中新添加了30个与组数有关的函数,其中一些常见的函数可以判断一个数组中是否包含某个元素,对一个数组中的元素进行计数,添加或删除数组中的元素或者对数组中的元素进行排序。
LkA_M'G U)B^R 如果有一个很大的数组,而你需要找出其中是否包含一个特定的元素,就可以使用in_array()。下面的例子将显示“Not found in this array”,因为在一个名字为$namesArray的数组中查找Albert,而在$namesArray数组中不存在这样一个元素。
a-(OAzQ_ E>2~cC* $lookingFor = "Albert";
hnD=DLW $ if (in_array($lookingFor, $namesArray)) {
<-avC/M$d echo "You've found it!";
/ltGSl } else {
Gj9WUv[P echo "Not found in this array!";
WK)2/$7@ }
v$_YZm{!< ?>
:^H#i:4 `zmjiC 如果把$lookingFor的值改为Mary,就会得到“You've found it!”的信息,因为Mary是$namesArray数组中的一个元素。
RV{'[8gM n(.U>_
P 如果要对一个数组中的元素个数进行计数,只要简单地使用count()函数即可:
@Fs2J_v n$z+g>~N $count = count($namesArray); ?>
BL?Bl&p( s+RSAyU 返回的$count的值为7。
M+ljg&fy p%?m|(4f 可以在一个数组的开头或结尾处添加元素,还可以使用array_merge()来建立一个包含二个或更多数组中元素的新数组,合并时,元素的顺序会按指定的顺序排列,如果原来的数组是被排过序的,在合并后需要对它重新排序。
co-dq\P J=@D]I*3 我们可以首先利用array_push()在数组的结尾处添加一个元素:
']cRSj. g[ dI% $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
m.0:R /* 向数组中添加元素 */
,rZp(moj array_push($fruitArray, "grape", "pineapple", "tomato");
"T+oXK\B /*显示每个元素及其序号*/
o1B8_$aYgc while (list($key,$value) = each($fruitArray)) {
.
v
L4@_ echo "$key : $value
G$T#ql ";
FvTc{"w / }
W!.vP~ > ?>
x.ZW%P1 LH_rc 运行上面的程序将得到下面的结果:
+#Q\;;FNP 0 : apple
X6`F<H` 1 : orange
&Bfgvws; 2 : banana
l*(Ml=
O{ 3 : kiwi
.W/#$s|X\ 4 : pear
N# ?}r>W3 5 : grape
.{}=!>U2 6 : pineapple
{P[>B}'rW 7 : tomato
hI Q 2s
~EJ+<[/ 如果需要在数组的开头添加元素,其代码与上面的代码差不多,唯一的不同之处是需要用array_unshift()代替array_push()。
DE659=Tq h|Z%b_a /* 建立一个数组*/
:l/?cV; $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
g(`m#&P>G /* 向数组中添加元素*/
LLlt9(^d array_unshift($fruitArray, "grape", "pineapple", "tomato");
}>T$2"pf /* 显示每个元素及其序号*/
R_|Sg while (list($key,$value) = each($fruitArray)) {
~0 5p+F) echo "$key : $value
riuG,$EX ";
Utv#E.VI }
:#I7);ol ?>
\4qwLM?E^ 运行上面的程序将得到下面的结果:
~,jBm^4 C[0*>W8o 0 : grape
byrK``f 1 : pineapple
dd{pF\a 2 : tomato
oI2YJ2?Je8 3 : apple
t!S ja 4 : orange
9+!1jTGSkf 5 : banana
w,/&oe5M+ 6 : kiwi
E` O@UW@ 7 : pear
C % d array_merge()函数可以把二个或更多的数组合并为一个数组。
vy&< O H,Ik&{@j $fruitArray = array("apple", "orange", "banana", "kiwi", "pear");
F[HMX4 /*/建立第二个数组*/
rQ+2 -|# $vegArray = array("carrot", "green beans", "asparagus", "artichoke", "corn");
8;vpa* /*把这二个数组合并为一个数组*/
o fw0_)!Q $goodfoodArray = array_merge($fruitArray, $vegArray);
~lSdWUk> /* 显示每个元素及其序号*/
uOU?-WtPz while (list($key,$value) = each($goodfoodArray)) {
WhY8#B'? echo "$key : $value
xP+HdA2X ";
|4lrVYG^K }
V <;vy&& ?>
H)u<$y!8 1+0DTqWz 运行上面的脚本将得到下面的结果:
>^\}"dEvr !rwe|"8m?u 0 : apple
&y~EEh| 1 : orange
E/[<} ./ 2 : banana
y;1
'hP& 3 : kiwi
s'Op|`&X 4 : pear
oI/jGyY; 5 : carrot
XX])B%* 6 : green beans
;uK">L[u' 7 : asparagus
pl.D
h 8 : artichoke
cI
g|sn 9 : corn
=%UX"K` $&