### 实例学习 PHP 之程序基础篇

3 PHP 实践
PHP 的许多特点与其他软件或者工具有关。利用迄今为止我们所学到的 PHP 知识，我们可以试着建立一个简单交互的网站。利用这一过程我们又可以学到不少东西。好吧，我们现在开始专注于一个典型个人网站的建设。
3.1 计划一个站点
一般一个个人站点包括一个欢迎页面、一个留言本页面、一个书签链接页面、一个计数器、联系信息，甚至还有照片集和一些音乐文件等等。让我们从一个标题页面、一个联系信息页面和一个简历页面开始。我们同样需要标准的通用的页面头部和底部。
标题页面--front.html
这里我们有一个非常简单的 html 文件：
<HTML>
<HEAD>
<TITLE>
我的个人主页--欢迎
</TITLE>
</HEAD>
<BODY>
<H1>
我的个人主页
</H1>
<H2>
欢迎
</H2>
<HR>
<P>
欢迎来我的寒舍，虽然这里现在暂时还没有什么。
</P>
<P>
不过我希望马上就可以多起来。
</P>
<HR>
<P ALIGN="CENTER">
<SMALL> <I>
Copyright ? 我自己，1999
</I> </SMALL>
</P>
</BODY>
</HTML>
联系信息页面--count.html
同样我们又有了一个简单页面：
<HTML>
<HEAD>
<TITLE>
我的个人主页--联系信息
</TITLE>
</HEAD>
<BODY>
<H1>
我的个人主页
</H1>
<H2>
联系信息
</H2>
<HR>
<P>
你可以通过 1-800-PHP-INFO 联系我
</P>
<HR>
<P ALIGN="CENTER">
<SMALL> <I>
Copyright ? 我自己，1999
</I> </SMALL>
</P>
</BODY>
</HTML>
3.2 HTML 到 PHP
从上面你可以看出，每个页面有相同的头部和底部。像上面那样每个页面都写入相同的信息在工作量少的时候还可以，但是想象一下当有 100 多页面且你需要全部更改其头部或底部时你要花费多大精力？一页一页的手工更改是一件多么冗长无趣的事情啊！所以我们应该为这些页面编写 PHP 的头部和底部文件，之后我们只要在每个 HTML 页面中引用它们就行了。我们将把这些 include 文件放在一个叫 include 的子目录下。下面我们就把这些站点的通用内容写进文件中。
全站通用变量设定：common.inc
<?
// 全站通用变量
$MyEmail = "phptalk@tnc.org";
$MyEmailLink = "<a href=\"mailto:$MyEmail\">$MyEmail</a>";
$MyName = "PHP Talk";
$MySiteName = $MyName."'s Home Page";
?>
通用页面头部：header.inc
<?
// 定义通用页面头部
?>
<HTML>
<HEAD>
<TITLE>
<? echo "$MySiteName - $title"; ?>
</TITLE>
</HEAD>
<BODY>
<H1>
<? echo "$MySiteName"; ?>
</H1>
<H2>
<? echo "$title"; ?>
</H2>
<HR>
通用页面底部：footer.inc
<?
// 通用页面底部
?>
<HR>
<P ALIGN="CENTER">
<SMALL> <I>
Copyright ? by
<? echo "$MyName ($MyEmailLink)"; ?>
, 1999
</I> </SMALL>
</P>
</BODY>
</HTML>
新的页面 front.php3：
<?
include("include/common.inc");
$title = "Welcome";
include("include/header.inc");
?>
<P>
欢迎来我的寒舍，虽然这里现在暂时还没有什么。
</P>
<P>
不过我希望马上就可以多起来。
</P>
<?
include("include/footer.inc");
?>
新的 cont.php3：
<?
include("include/common.inc");
$title = "Contact Information";
include("include/header.inc");
?>
<P>
你可以通过 1-800-PHP-INFO 联系我
</P>
<?
include("include/footer.inc");
?>
现在你就可以猜出这样安排的好处了。如果你想改动页面的头部或者底部，你只需要改动相应的文件就可以了。如果你要修改你的 e-mail 地址甚至你的名字，只要修改 common.inc 文件就行了。另外值得注意的是你可以把具有任何文件名或者文件扩展名的文件包含进你的文件中，你甚至可以包含其他站点上的文件。
3.3 计数器
让我们在首页上加上一个计数器。这个例子已经被讲过多次了，但是还是有利于演示怎样读写文件以及创建自己的函数。counter.inc 包含以下代码：
<?
/*
││ 一个简单的计数器
*/
function get_hitcount($counter_file)
{
/* 将计数器归零
这样如果计数器还未被使用，初始值将是 1
你当然也可以把初始值设成 20000 来骗人咯
*/
$count=0;
// 如果存放计数器文件已经存在，读取其中的内容
if ( file_exists($counter_file) )
{
$fp=fopen($counter_file,"r");
// 我们只取了前 20 位，希望你的站点不要太受欢迎啊
$count=0+fgets($fp,20);
// 由于函数 fgets()返回字符串，我们可以通过加 0 的方法将其自动转换为整数
fclose($fp);
// 对文件操作完毕
}
// 增加一次计数值
$count++;
// 将新的计数值写入文件
$fp=fopen($counter_file,"w");
fputs($fp,$count);
fclose($fp);
# 返回计数值
return ($count);
}
?>
然后我们更改 front.php3 文件以显示这个计数器：
<?
include("include/counter.inc");
// 我把计数值放在文件 counter.txt 中，读出并输出
printf ("<CENTER><B>%06d</B></CENTER> <BR>
\n",
get_hitcount("counter.txt"));
include("include/footer.inc");
?>
看看我们的新 front.php3
3.4 反馈表单
让我们再添加一个反馈表单以便你的浏览者填写并 e-mail 给你。举例来说我们用一种很简单的方法实现它，我们只需要两个页面：一个为浏览者提供输入表单；一个获得表单数据并处理、mail 给你。
PHP 中获取表单数据是很简单的。当一个表单被发送后，表单中所包含的各个元素被赋上了相应的值，而这样就可以像引用一般变量一样使用了。
<FORM name="myform" ACTION="process_form.php3" METHOD="POST">
<INPUT TYPE="TEXT" NAME="mytext" VALUE="Some Value">
</FORM>
在 process_form.php3 中，变量$mytext 就被赋予了输入的值--非常简单！同样的，你可以从列表框、多选框、单选框、按钮等表单元素中取得变量值。你唯一要做的就是为表单中的每一个元素取名以便将来可以引用。
根据这个方法，我们可以生成一个简单的包含三个元素的表单：姓名、e-mail 地址和留言。当浏览者发送表单后，处理该表单的 PHP 页面（sendfdbk.php3）读取数据，检查姓名是否为空，最后将数据 mail 给你。
表单：form.php3
<?
include("include/common.inc");
$title = "Feedback";
include("include/header.inc");
?>
<P>
<FORM ACTION="sendfdbk.php3" METHOD="POST">
<INPUT TYPE="text" NAME="name" value="Your name"
SIZE="20" MAXLENGTH="30">
<INPUT TYPE="text" MAXLENGTH="40" WIDTH="20"
value="Your Email" NAME="email">
<BR>
<TEXTAREA ROWS="7" COLS="40" NAME="comment">
Your feedback on my home page.
</TEXTAREA>
<BR>
<INPUT TYPE="submit" VALUE="Send Feedback!">
</FORM>
</P>
<?
include("include/footer.inc");
?>
处理表单：sendfdbk.php3
<?
include("include/common.inc");
$title = "Feedback";
include("include/header.inc");
if ( $name == "" )
{
// 现在我很讨厌匿名的留言！
echo "Duh ? How come you are anonymous?";
}
elseif ($name == "Your name")
{
// 这个浏览者真是不想透露姓名啊！
echo "Hello ? <B>Your name</B> is supposed to be replaced with
your actual name!</B>";
}
else
{
// 输出一段礼貌的感谢语
echo "
Hello, $name.
<BR>
Thank you for your feedback. It is greatly appreciated.
<BR>
Thanking you
<BR>
$MyName <BR>
$MyEmailLink
";
// 最后 mail 出去
mail($MyEmail, "Feedback.","
Name : $name
E-mail : $email
Comment : $comment
");
}
include("include/footer.inc");
?>
3.5 简单的站内搜索引擎
PHP 可以调用外部程序。在 Unix 环境下我们可以利用程序 grep 实现一个简单的搜索引擎。我们可以做的稍微复杂一些：使用一个页面既输出一个表单供用户输入搜索字串又输出查询结果。
<?
include("include/common.inc");
$title = "Search";
include("include/header.inc");
?>
<P>
<FORM ACTION="<? echo "$PHP_SELF"; ?>" METHOD="POST">
<INPUT TYPE="text" NAME="searchstr" value="<?
echo "$searchstr"; ?>"
SIZE="20" MAXLENGTH="30">
<INPUT TYPE="submit" VALUE="Search!">
</FORM>
</P>
<?
if ( ! empty($searchstr) )
{
// empty()用来检查查询字串是否为空
// 如果不为空，调用 grep 查询
echo "<HR>\n";
// 调用 grep 对所有文件进行大小写非敏感模式的查询
$cmdstr = "grep -i $searchstr *";
$fp = popen( $cmdstr, "r" ); // 执行命令并输出管道
$myresult = array(); // 存储查询结果
while( $buffer = fgetss ($fp, 4096))
{
// grep 返回这样格式： 文件名：匹配字串出现行数
// 因此我们利用函数 split()分离处理数据
list($fname, $fline) = split(":",$buffer, 2);
// 我们只输出第一次匹配的结果
if ( !defined($myresult[$fname]))
$myresult[$fname] = $fline;
}
// 现在我们将结果存储在数组中，下面就可以处理并输出了
if ( count($myresult) )
{
echo "<OL>\n";
while(list($fname,$fline) = each($myresult))
echo "<LI>
<A HREF=\"$fname\">$fname</A> : $fline </LI>\n";
echo "</OL>\n";
}
else
{
// 如果没有查询结果
echo "Sorry. Search on <B>$searchstr</B>
returned no results.<BR>\n";
}
pclose($fp);
}
?>
<?
include("include/footer.inc");
?>
注释：
PHP_SELF 是 PHP 内建的变量。包含当前文件名。
fgets()按行读取文件，最多 4096（指定）字符长度。
fgetss()与 fgets()相似，只是解析输出的 HTML 标记。
split()有一个参数是 2，因为我们只需要把输出分成两部分。另外需要省略":"。
each()是一个数组操作函数，用来更方便的遍历整个数组。
popen()、pclose()与 fopen()、fclose()的功能很相似，只是增加了管道处理。
请注意以上的代码并不是实现一个搜索引擎的好办法。这只是有助于我们更好学习 PHP 而举出的一个例子而已。理想的情况是你应该建立一个包含关键字的数据库然后进行搜索。