### PHP 的十个高级技巧（中）

三、文件是我们的朋友
无论你在开发的网站规模的大小，都应该意识到代码重用的重要性，无论这些代码是 HTML、还是 PHP 代码。例如，你必须至少每年改变一次包含版权信息的页脚，如果你的网站含有 1000 个页面，每年修改一次也是个很烦人的事儿。
在 PHP 中，至少有几个函数可以帮助你实现代码重用的目的，所使用的函数取决于你所重用的代码，主要的函数有：
* include() and include_once()
* require() and require_once()
include()函数包含并对给定的文件进行计算，例如：
include('/home/me/myfile');
在 include 文件中的任何代码都在 include()出现的代码范围内执行，你可以通过联合使用 include()和 fopen()在自己的服务器上包含静态文件，在另一台服务器上包含目标文件。
include_once()的功能与 include()相同，二者之间的区别在于它会检查一个文件中的代码是否已经包含在现有的脚本中，如果代码已经存在，则不会再次包含它。
require()函数用给定文件的内容取代它本身，这一代替过程发生在 PHP 引擎编译代码期间，而不是在执行期间进行，它不象 include()那样会首先进行计算。require()函数更多地用在静态元素中，而 include()更多地用于动态元素中。与 include_once()类似的是，require_once()将首先检查是否已经插入给定的代码，如果代码已经存在，就不再插入了。
为也了解其内容，在版权信息、静态文字和其他不包含变量的元素或者依赖其他正在执行的脚本的元素中我更趋向于使用 require 函数。例如：
<HTML>
<HEAD><TITLE>Something</TITLE></HEAD>
<BODY>
[a lot of content]
<?
// insert copyright
require('/home/me/mycopyright');
?>
</BODY>
</HTML>
另一方面，我经常在文件的开始使用 include()来控制许多的函数：
<?
//得到函数库
include('/home/me/myfunctions');
// do PHP things with my functions ?>
<HTML>
<HEAD><TITLE>Something</TITLE></HEAD>
<BODY>
[a lot of content]
</BODY>
</HTML>
下一个问题就该是“include 和 require 文件在哪里？”，对这个问题简单的回答是，“系统中的任意地方。”如果你的代码中包含有带有用户名和口令的数据库连接，你肯定不会将它们都放在文档根目录中向所有的人都开放。
included 或 required 文件可以在系统上的任何地方，只要 PHP 运行的系统上的用户可以访问这些文件即可，你可以使这些文件具有任何后缀，或者不使用后缀。
使用 include()和 require()对在网站中的元素进行具体化是一种普遍的现象，并在需要对网站升级时，给你带来很大的方便。
四、PHP 和文件系统的维护
PHP 中有许多与文件系统有关的函数，这些函数不仅可以打开文件，还可以显示目录中的内容、移动文件和其他一些功能，许多人甚至用 PHP 开发基于互联网的文件资源管理器。
关于文件路径的解释：在 Windows 中，可以在路径中使用/和\符号，而在其他的操作系统中只能使用/符号。出于一致性的缘故，我们统一使用/符号。
下面的脚本样例可以显示一个目录清单，注释已经包含在代码中：
<? /*把要读取的目录的全路径名存入一个名字为$dir_name 的变量中。 */
$dir_name = "/home/me/";
/* 创建一个句柄，其值是打开一个给定目录的结果*/
$dir = opendir($dir_name);
/* 建立一个文字块，用以放置列表元素（文件名字）*/
$file_list = "<ul>";
/* 使用一个 while 语句，读取已经打开的目录中的所有元素，如果文件的名字不是“.”或“..”，则显示列表中的名字*/
while ($file_name = readdir($dir)) {
if (($file_name != ".") && ($file_name != "..")) {
$file_list .= "<li>$file_name";
}
}
$file_list .= "</ul>";
/*关闭打开的目录，结束 PHP 模块*/
closedir($dir);
?>
<!-- Start your HTML -->
<HTML>
<HEAD>
<TITLE>Directory Listing</TITLE>
</HEAD>
<BODY>
<!-- Use PHP to print the name of the directory you read -->
<P>Files in: <? echo "$dir_name"; ?></p>
<!-- Use PHP to print the directory listing -->
<? echo "$file_list"; ?>
</BODY>
</HTML>
好了，我们已经得到了一个目录清单。需要注意的是，要读取一个文件（稍后我们将进行讲解）或目录的内容，PHP 运行的系统上的用户必须至少有读取文件的权限。
下面是一个如何拷贝文件的例子：
<? /*把你要拷贝的原文件的全路径赋给一个名字为$original 的变量中，把拷贝的文件的全路径赋予一个名字为$copied 的变量中*/
$original = "/home/me/mydatabasedump";
$copied = "/archive/mydatabasedumo_1010";
/* 使用 copy()函数拷贝原始文件，如果拷贝没有完成则会显示一个错误信息*/
@copy($original, $copied) or die("Couldn't copy file.");
?>
这个例子是一个文件备份系统的原型。在这段脚本运行时，它把文件拷贝到一个不同的位置进行保存。稍微修改一下守护程序，就可以在一天中你指定的时刻执行它，而无需用户的干预。
假定你在系统上安装了 Lynx，可以创建一个守护程序的条目访问这个文件，访问这个文件会运行这个脚本并建立一个拷贝文件，下面的例子将在上午 5 点钟运行这个脚本，然后关闭 Lynx：
0 5 * * * [username] lynx -dump http://localhost/copyfile.php 1>/dev/null 2>&1
如果运行的是 CGI 版本的 PHP，可以跳过 Lynx 部分，而直接调用二进制文件：
0 5 * * * [username] php /path/to/copyfile.php 1>/dev/null 2>&1
五、丰富的数组函数
PHP 4.0 中新添加了 30 个与组数有关的函数，其中一些常见的函数可以判断一个数组中是否包含某个元素，对一个数组中的元素进行计数，添加或删除数组中的元素或者对数组中的元素进行排序。
如果有一个很大的数组，而你需要找出其中是否包含一个特定的元素，就可以使用 in_array()。下面的例子将显示“Not found in this array”，因为在一个名字为$namesArray 的数组中查找 Albert，而在$namesArray 数组中不存在这样一个元素。
<? $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_merge()来建立一个包含二个或更多数组中元素的新数组，合并时，元素的顺序会按指定的顺序排列，如果原来的数组是被排过序的，在合并后需要对它重新排序。
我们可以首先利用 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()函数可以从一个数组的开头删除一个元素。尽管使用 array_pop()或 array_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
我们再来讨论一个从一个数组的末尾删除元素的例子：
<?
/* 建立一个数组*/
$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