文章教程

第9章浏览器和输入输出

9/17/2020 9:34:15 PM 人评论 次浏览

第9章 浏览器和输入输出

在前几章中介绍了PHP这门语言的基本知识,关于什么是PHP,为何使用PHP,怎么使用PHP等。通过循序渐进的学习,相信读者现在已经对PHP有了一个基本的了解。从本章开始就进一步介绍PHP自带的函数。初学者对于函数越了解,就越能提高开发效率。

9.1 检测来访者的浏览器版本和语言

常常在浏览论坛的时候,看见很多人的个性签名上会显示来访者现在使用的是哪个版本的浏览器及语言。是否觉得它很神奇呢?其实PHP就能实现这个效果,而且使用方法也很简单。这节就介绍如何使用PHP来检测来访者的浏览器版本和语言。

要达到这个目的,需要检查用户的agent字符串,它是浏览器发送的HTTP请求的一部分。该信息是被存储在一个变量中的。在PHP语言中,变量总是以一个美元符号开头。

注意 $_SERVER是一个特殊的PHP保留变量,它包含了Web服务器提供的所有信息,被称为自动全局变量(或“超全局变量”)。这些特殊的变量是在PHP 4.1.0版本之后引入的。在这之前使用$HTTP_*_VARS数组,如$HTTP_SERVER_VARS。尽管现在已经不用了,但它们在新版本中仍然存在。

判断浏览器版本信息需要用到的变量是$_SERVER['HTTP_USER_AGENT'],可以使用如下代码显示该变量所包含的浏览器信息:

<?php echo $_SERVER['HTTP_USER_AGENT']; ?>

以上脚本的输出可能是:

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)

从输出的信息中可以得知访问者使用的是何种浏览器、何种操作系统等信息。比如这段输出字符中的“MSIE 8.0”就表示是Internet Explorer 8.0浏览器,“Windows NT 5.1”表示的是Windows XP操作系统。

判断客户端系统语言需要用到的变量是$_SERVER['HTTP_ACCEPT_LANGUAGE'],可以使用如下代码显示该变量所包含的浏览器信息:

<?php echo $_SERVER["HTTP_ACCEPT_LANGUAGE"]; ?>

以上脚本的输出可能是:

zh-cn,zh;q=0.5

其中的“zh-cn”表示简体中文。

有意思的是两个变量提供的信息,就可以使用PHP检测来访者的浏览器版本和语言。具体的实现如代码9-1所示。

代码9-1 检测来访者的浏览器版本和语言

<?php 
echo "<span class="kindle-cn-bold">判断浏览器类型</span><hr />"; 
 
echo "<span class="kindle-cn-bold">您当前使用的浏览器是:</span>"; 
if(strpos($_SERVER["HTTP_USER_AGENT"],"MSIE 8.0")) 
    echo "Internet Explorer 8.0"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"MSIE 7.0")) 
    echo "Internet Explorer 7.0"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"MSIE 6.0")) 
    echo "Internet Explorer 6.0"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"Firefox/3")) 
    echo "Firefox 3"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"Firefox/2")) 
    echo "Firefox 2"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"Chrome")) 
    echo "Google Chrome"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"Safari")) 
    echo "Safari"; 
else if(strpos($_SERVER["HTTP_USER_AGENT"],"Opera")) 
    echo "Opera"; 
else echo $_SERVER["HTTP_USER_AGENT"]; //输出浏览器类型 
 
echo "<br />"; 
echo "<br />"; 
 
echo "<span class="kindle-cn-bold">您当前使用的语言是:</span>"; 
//只取前4位,这样只判断最优先的语言。如果取前5位,可能出现en.zh的情况,影响判断 
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 4); 
if (preg_match("/zh-c/i", $lang)) 
    echo "简体中文"; 
else if (preg_match("/zh/i", $lang)) 
    echo "繁體中文"; 
else if (preg_match("/en/i", $lang)) 
    echo "English"; 
else if (preg_match("/fr/i", $lang)) 
    echo "French"; 
else if (preg_match("/de/i", $lang)) 
    echo "German"; 
else if (preg_match("/jp/i", $lang)) 
    echo "Japanese"; 
else if (preg_match("/ko/i", $lang)) 
    echo "Korean"; 
else if (preg_match("/es/i", $lang)) 
    echo "Spanish"; 
else if (preg_match("/sv/i", $lang)) 
    echo "Swedish"; 
else echo $_SERVER["HTTP_ACCEPT_LANGUAGE"]; //输出系统语言 
?>

代码中首先使用$_SERVER["HTTP_USER_AGENT"]来得到用户的agent信息,然后根据strpos()函数来判断信息中的浏览器类型。当判断浏览器语言时,使用$_SERVER["HTTP_ACCEPT_LANGUAGE"]来提取语言信息,用preg_match()正则匹配函数来判断语言类型。图9.1是使用IE浏览器浏览时的输出结果,图9.2是使用Firefox浏览器浏览时得到的结果。

010-01 011-02
图9.1 检测来访者的浏览器版本和语言1 图9.2 检测来访者的浏览器版本和语言2

9.2 处理表单提交的数据

动态网页核心的特点就是能动态响应客户端请求。那么表单就成为了动态网页与客户端交互的最重要的途径之一。本节内容就是介绍如何用PHP来处理表单提交过来的数据。

首先需要熟悉一下HTML语言中创建表单的相关标签,然后创建一个表单,把表单的action属性设为需要提交数据的PHP文件所在位置、method属性设为post。加入两个文本框,把其中一个文本框的name属性设为name,另外一个设置为age。创建完成后的表单代码大致如下所示:

<form action="__URL__" method="post"> 
    姓名: 
    <input type="text" name="name" /> 
    年龄: 
    <input type="text" name="age" /> 
    <input type="提交" /> 
</form>

当这段代码运行时,输入相关数据并单击“提交”按钮以后,表单中的数据就会被提交到服务端去。PHP提供$_POST自动全局变量用来接收客户端通过POST方式提交上来的数据。$_POST是一个数组,所以可以像数组一样提取其中的值。代码9-2是使用$_POST变量来接受提交上来的数据的例子。

代码9-2 处理表单提交的数据

<span class="kindle-cn-bold">处理表单提交的数据</span><hr /> 
<?php 
if(isset($_POST['submit'])) { //如果用户单击“提交”按钮,那么就开始处理
    echo "<span class="kindle-cn-bold">接收到的数据</span><br /><br />"; 
    echo "你好," . $_POST['name'] . "。"; 
    echo "<br />"; 
    echo "你现在有".$_POST['age']."岁了。"; 
 die(); //程序结束 
} 
?> 
<span class="kindle-cn-bold">表单内容</span> 
<form action="9-2.php" method="post"> 
    姓名: 
    <input type="text" name="name" /><br /> 
    年龄: 
    <input type="text" name="age" /><br /> 
    <input type="submit" name="submit" value="提交" /> 
</form>

该脚本进行的工作应该已经很明显了,这儿并没有其他更复杂的内容。PHP将自动设置$_POST['name']和$_POST['age']变量。在这之前使用了自动全局变量$_SERVER,现在引入了自动全局变量$_POST,它包含了所有的POST数据。

注意 示例中使用的表单提交数据的方法(method)是POST,服务器端使用$_POST变量来处理数据。如果使用了表单提交GET方法,那么表单中的信息将被储存到自动全局变量$_GET中,此时就需要使用$_GET变量来处理数据。如果并不关心请求数据的来源,也可以用自动全局变量$_REQUEST,它包含了所有GET、POST、Cookie和FILE的数据。

以上代码运行后,得到的结果如图9.3所示。在输入框中分别输入名字和年龄,然后单击“提交”按钮提交表单。服务器接收到提交上来的数据并进行处理后,得到如图9.4所示的结果。

010-01 011-02
图9.3 提交数据的表单 图9.4 处理表单提交的数据

9.3 上传文件处理

互联网的时代是一个信息分享的时代,互联网上除了必要的文字信息,还有许许多多的图片、视频、音乐、文档等信息。这些大大小小的信息文件,很多都是互联网用户通过表单上传上去的,有了这些内容后,互联网才会如此受欢迎,如此绚丽多彩。所以允许用户从表单上传文件是非常有用且重要的。

同提交文本数据一样,上传文件也需要先建立一个表单。下面就建立一个特殊的表单来支持文件上传,代码如下:

<!-- 表单中的enctype属性,必须和以下定义的一致 --> 
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE必须在所有input域的前面 --> 
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" /> 
    <!-- 上传文件的名称 --> 
    上传的文件: 
    <input name="userfile" type="file" /> 
    <input type="submit" value="上传文件" /> 
</form>

以上范例中的__URL__应该被换掉,指向一个真实的PHP文件。MAX_FILE_SIZE隐藏字段(单位为字节)必须放在文件输入字段之前,其值为接收文件的最大尺寸。这是对浏览器的一个建议,PHP也会检查此项。在浏览器端可以简单绕过此设置,因此不要指望用此特性来阻挡大文件。实际上,PHP设置中的上传文件最大值是不会失效的。但是最好还是在表单中加上此项目,因为它可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。

注意 要确保文件上传表单的属性是 enctype="multipart/form-data",否则文件上传不了。

当用户提交文件表单以后,服务器端就可以接收数据了。PHP提供一个全局变量$_FILES来处理这些信息,该数组包含所有上传的文件信息。以上范例中$_FILES数组的内容如下所示。假设文件上传字段的名称如上例所示,为userfile。名称可随意命名。

  • $_FILES['userfile']['name'] 客户端机器文件的原名称。
  • $_FILES['userfile']['type'] 文件的MIME类型,如果浏览器提供此信息的话。一个例子是“image/gif”。不过此MIME类型在PHP端并不检查,因此不要想当然地认为有这个值。
  • $_FILES['userfile']['size'] 已上传文件的大小,单位为字节。
  • $_FILES['userfile']['tmp_name'] 文件被上传后在服务端储存的临时文件名。
  • $_FILES['userfile']['error']和该文件上传相关的错误代码。此项目是在 PHP 4.2.0 版本中新增加的。

文件被上传后,默认地会被储存到服务端的默认临时目录中,除非php.ini中的upload_tmp_dir设置为其他的路径。服务端的默认临时目录可以通过更改PHP运行环境的环境变量TMPDIR来重新设置,但是在PHP脚本内部通过运行putenv()函数来设置是不起作用的。该环境变量也可以用来确认其他的操作也是在上传的文件上进行的。

对于PHP上传文件还需要讲解一个move_uploaded_file()函数,该函数使用的语法如下:

bool move_uploaded_file ( string filename, string destination )

本函数检查并确保由filename指定的文件是合法的上传文件(即通过PHP的HTTP POST上传机制所上传的)。如果文件合法,则将其移动为由destination指定的文件。如果filename不是合法的上传文件,不会出现任何操作,move_uploaded_file()将返回FALSE。如果filename是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file()将返回FALSE。此外还会发出一条警告。如果上传的文件有可能会造成对用户或本系统的其他用户显示其内容的话,这种检查显得格外重要。

注意 使用该函数时,如果目标文件已经存在,将会被覆盖。

代码9-3示范处理由表单提供的文件上传的过程,如下所示。

代码9-3 文件上传处理

<span class="kindle-cn-bold">上传文件处理</span><hr /> 
<?php 
if(isset($_FILES['userfile'])) { 
    $uploaddir = 'upload/';           //上传文件放置的路径 
    $uploadfile = $uploaddir . basename($_FILES['userfile']['name']); 
     
    echo '<pre>'; 
    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {//上传文件至指定目录 
        echo "文件上传成功!\n"; 
    } else { 
        echo "上传文件失败!\n"; 
    } 
     
    echo "这里是上传的一些信息:\n"; 
    print_r($_FILES);           //打印相关信息 
    print "&lg;/pre>"; 
    die(); 
} 
?> 
<span class="kindle-cn-bold">上传表单</span> 
<!-- 表单中的enctype属性,必须和以下定义的一致 --> 
<form enctype="multipart/form-data" action="9-3.php" method="POST"> 
    <!-- MAX_FILE_SIZE必须在所有input域的前面 --> 
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" /> 
    <!-- 上传文件的名称 --> 
    上传的文件: 
    <input name="userfile" type="file" /> 
    <input type="submit" value="上传文件" /> 
</form>

以上代码的过程是这样的,首先判断是否有文件上传,如果有则显示上传的表单,效果如图9.5所示。当选择了文件并提交上传时,使用move_uploaded_file()函数将上传的文件移到指定的目录完成上传,最后打印相关信息。效果如图9.6所示。

015-01

图9.5 文件上传表单

015-01

图9.6 文件上传处理结果

9.4 会话处理函数Session

在浏览购物网站时,当你选中一个商品后,商品会自动放入网站的购物车中,以便于与以后所选的商品一同结账,或者删除不需要的商品。更奇妙的是,如果没有做清空购物车的操作,那么下次再浏览这个网站的时候,会发现以前所选择的那些商品依然还在!

这个功能可以使用PHP的会话处理函数来实现,本节就来介绍一些关键的会话处理事务和函数。

9.4.1 开始会话

在把用户信息存储到session之前,首先必须启动会话。PHP提供session_start()函数来启动一个会话。该函数的使用语法如下所示:

bool session_start ( void )

函数session_start()创建一个新会话或者继续当前会话,这取决于是否拥有SID。因为该函数没有输入参数,所以要开始一个会话只需使用如下方式调用函数。

<?php session_start();?>
<html> 
<body></body> 
</html>

注意1 session_start()函数必须位于<html>标签之前,也就说该函数必须在任何输出之前调用。

常常写程序时不注意会多输入一个空格和回车,这时就会提示出错,这个现象时常发生。

注意2 无论结果如何,调用session_start()函数都会返回一个TURE,因此使用任何异常处理都不起作用。

Tips 可以启用配置指令session.auto_start,从而不必执行这个函数。但是这样一来,每个PHP页面执行的时候都会开始或继续一个会话。

上面的代码会向服务器注册用户的会话,以便可以开始保存用户信息,同时会为用户会话分配一个SID。

9.4.2 存储与读取会话

存储和读取session变量的正确方法是使用PHP的$_SESSION变量。$_SESSION是PHP提供的一个全局参数,用来存储和读取会话。

注意 在$_SESSION关联数组中的键名具有和PHP中普通变量名相同的规则,即不能以数字开头,必须以字母或下画线开头。

存储会话时,可以直接对这个全局数组进行如下所示的赋值。

$_SESSION[‘season’] = ‘秋天’

以上代码设置了一个键为“season”的会话元素,并设置它的值为“秋天”。当读取时,像读取数组元素的值一样,直接使用它的键值就能够取得。代码9-4和代码9-5一起展示如何存储并读取一个会话元素,如下所示。

代码9-4 存储会话

<?php 
if(isset($_POST['submit'])) { 
    session_start();       //建立一个会话 
    $_SESSION['season'] = $_POST['season'];   // 存储会话数据 
    header("Location: 9-5.php"); 
} 
?> 
<span class="kindle-cn-bold">存储会话</span> 
<hr/> 
选择需要设置的数据: 
<form id="form1" name="form1" method="post" action=""> 
    <select name="season" id="season"> 
        <option value="春天">春天</option> 
        <option value="夏天">夏天</option> 
        <option value="秋天">秋天</option> 
        <option value="冬天">冬天</option> 
    </select> 
    <br /><br /> 
    <input type="submit" name="submit" id="submit" value="提交" /> 
</form>

代码9-5 存储会话

<?php 
session_start();//发起或继续一个会话 
$season = $_SESSION['season'];//读取会话数据 
echo "<span class="kindle-cn-bold">读取会话</span><hr />";
switch($season) { 
    case '春天': 
        echo "现在是绿意盎然的 春天!"; 
        break; 
    case '夏天': 
        echo "现在是热情四溢的 夏天!"; 
        break; 
    case '秋天': 
        echo "现在是丰收果实的 秋天!"; 
        break; 
    case '冬天': 
        echo "现在是白雪皑皑的 冬天!"; 
        break; 
    default: 
        echo "对不起,会话中没有数据,或者不存在该会话。"; 
   
} 
?>

在代码9-4中首先使用session_start()函数创建一个会话,然后对提交的季节数据使用数组赋值的方式存储,最后使用header()函数直接跳转到开始。在代码9-5中,也同样需要使用session_start()函数发起一个会话。读取对应的会话信息后,使用switch()函数来判断并输出相应的信息。

通过以上代码,可以发现在PHP中对session的操作与对数组的操作基本是相同的。只不过需要注意的是,使用session前需要加一个session_start()函数来发起或者继续一个会话。

运行代码后,得到如图9.7所示的含有一个下拉列表和“提交”按钮的网页。选择其中一个数据并单击“提交”按钮后,跳转到如图9.8所示的页面。

010-01 011-02
图9.7 存储会话 图9.8 读取会话

9.4.3 销毁会话

当会话不再被使用的时候,就需要人为地销毁它。虽然PHP有自动销毁会话的功能,但这样做会使程序的效率降低。这时就可以使用unset()或session_destroy()函数。

在前一个章节中已经介绍过使用unset()函数来销毁一个数组中的元素,同样这个函数也能销毁一个会话中的元素。使用unset()函数释放指定的session变量的代码如下所示:

<?php 
unset($_SESSION['season']); 
?>

也可以通过session_destroy()函数彻底终结session:

<?php 
session_destroy(); 
?>

注意 session_destroy()将重置session,将失去所有已存储的session数据。

9.5 Cookie处理函数

cookie常用于识别用户。它是服务器留在用户计算机中的小文件。每当相同的计算机通过浏览器请求页面时,它同时会发送cookie。通过PHP,能够创建并取回cookie的值。cookie在Web开发中向来扮演着比较重要的角色,它是Web开发中历史悠久并且经常使用的技术之一,在PHP中体现得更为明显,在设计用户身份验证的系统中,往往都会使用cookie。PHP中可以通过函数方便地使用cookie,本节将介绍如何在PHP程序中使用cookie。

9.5.1 创建cookie

函数setcookie()可以在PHP程序中生成cookie。由于cookie是HTTP头标部分的内容,因此必须在输出任何数据之前调用setcookie(),这个限制和函数header()类似。函数setcookie()的语法如下所示。

bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure [, bool httponly]]]]]] )

setcookie共有6个参数。

  • name:表示cookie的名称。
  • value:表示该cookie的值,保存在客户端,因此不要保存敏感或机密的数据。这个参数为空字符串时,表示撤销客户端中该cookie的资料。
  • expire:表示该cookie有效的截止时间,即过期时间,该参数必须是整型。
  • path:表示该cookie有效的路径。
  • domain:表示该cookie有效的域名。
  • secure:表示在https的安全传输时才有效。

本函数除了第一个参数之外,其他参数都是可以省略的。下面的示例代码在客户端生成了一个名为testcookie、值为ilovephp的cookie。

<?php 
setcookie("testcookie", "ilovephp"); 
?>

使用函数setcookie()给一个cookie设定的值只能是数字或字符串,不能是数组或其他复杂的数据结构。

9.5.2 获取cookie

当cookie设置后,可以通过PHP预定义变量$_COOKIE来获取cookie。不过,只能在其他页面使用这个变量来获取设置过的cookie,因为在PHP中,被设置的cookie并不会在本页生效,除非该页面被刷新。代码9-6演示了设置一个cookie后,在页面打印出该cookie的值。

代码9-6 显示cookie的值

<?php 
setcookie("testcookie", "ilovephp"); 
echo "cookie's value: ".$_COOKIE['testcookie']; 
?>

这里之所以要刷新页面后才能看到cookie的值,是因为cookie的值不会在调用setcookie()之后立即出现在变量$_COOKIE中,而是在客户端再次请求该页面时,cookie随请求一起发送至服务器,这时cookie才能存入到变量$_COOKIE中。

下面的代码9-7生成数组cookie,这样可以设置多个cookie,并将其作为数组单元。提取cookie时,所有的值都放在一个数组中。

代码9-7 设置多个cookie

<?php 
//设置多个cookie, 存放在数组mycookie中 
setcookie("mycookie['three']", "cookiethree"); 
setcookie("mycookie['two']", "cookietwo"); 
setcookie("mycookie['one']", "cookieone"); 
//刷新页面后, 将所有cookie显示出来 
if(isset($_COOKIE['mycookie'])) 
{   
foreach ($_COOKIE['mycookie'] as $name => $value)
{ 
echo "$name : $value <br />\n"; 
} 
} 
?>

通过浏览器访问代码9-7所示的程序9-7.php,第一次会看到一个空白页面,然后刷新该页面,就会看到输出结果。这段代码通过循环,从变量$_COOKIE中取出了所有cookie。

9.5.3 cookie的有效期

cookie有生命周期,即cookie只在一段时间内是有效的。通常,当用户退出IE或者Mozilla浏览器时,cookie就会被删除。如果希望延长或者缩短cookie的有效期,可以向函数setcookie()传递第3个参数,来设置cookie的有效期。下面的示例代码演示了为cookie设置不同的失效时间。

setcookie('cookie_one','i_am_cookie1',time() + 60*60);         //设置cookie 1小时后失效 
setcookie('cookie_two','i_am_cookie2',time() + 60*60*24);      //设置cookie 1天后失效 
//设置cookie于2008年1月1日中午12点失效 
setcookie('cookie_three','i_am_cookie3',mktime(12,0,0,1,1,2008));

这个用来接收cookie失效时间的参数,是第7章介绍的UNIX时间戳,即一个秒数。因此才会像上述代码那样,通过计算得到cookie的失效时间。

如果未指定cookie的失效时间,或者指定为0,那么cookie将在会话结束时失效,通常是关闭浏览器后失效。如下代码设置了cookier的失效时间为0,即使用默认的失效时间。

setcookie('mycookie','delicious',0);

9.5.4 cookie的有效路径

通常,客户端的cookie只会回送给那些和设置这个cookie的程序在同一目录(或下级目录)的页面。例如,一个由http://www.somesite.com/index.php设置的cookie,会被所有到www.somesite.com请求回送至服务器,因为index.php在服务器的根目录下。而由http://www.somesite.com/users/list.php设置的cookie,随着请求,客户端的cookie会被回送到users目录下的其他页面,如可以将cookie回送到http://www.somesite.com/users/login.php,但不能回送至http://www.somesite.com/orders/info.php。

如果需要客户端的请求把cookie传回到不同的路径下,可以通过向函数setcookie()传入第4个参数,通过该参数设置cookie在服务器端的有效路径。最灵活的方式是,设置cookie的有效路径为/,它表示用setcookie()设置的cookie在整个服务器域名内有效。设置为/mypath/,那么,该cookie只在域名的/mypath/目录及其子目录下有效。下面的代码设置cookie的有效路径为一个指定的目录。

secookie('mycookie','delicious',0,'/ck_path/');

这样设置后,当请求/ck_path/目录下的页面或程序时,该cookie会被从客户端传回,而当请求/ot_path/时,该cookie不会从客户端传回至服务器。

9.5.5 删除cookie

在PHP程序中删除cookie比较简单,也是通过函数setcookie()完成。通过下面的代码就可以实现删除一个cookie。

setcookie('mycookie','');

这段代码通过将cookie的值设为空,来达到删除cookie的目的。如果设置cookie时,为函数setcookie()每个参数都提供了特定的值,那么在删除cookie时,仍然需要提供这些参数,以便PHP可以正确地删除cookie。

9.6 使用HTTP Header

标头(header)是服务器以HTTP协议传HTML资料到浏览器前所送出的字符串,在标头与HTML文件之间尚需空一行分隔。有关HTTP的详细说明,可以参考相关书籍或更详细的RFC 2068官方文件(http://www.w3.org/Protocols/rfc2068/rfc2068)。在PHP中送回HTML资料前,需要先传完所有的标头。

注意 传统的标头一定包含下面三种标头之一,并只能出现一次。

  • Content-Type: xxxx/yyyy
  • Location: xxxx:yyyy/zzzz
  • Status: nnn xxxxxx

在新的多型标头规格(Multipart MIME)中方可以出现两次以上。

PHP提供header()函数用来将HTML文档的标头以HTTP协议发送至浏览器,告诉浏览器该如何处理这个页面。该函数的语法如下所示。

header (string $str_header );

函数的参数$str_header是一个字符串,用来接收要发送的标头。事实上,这个函数还有两个可选参数,因为对初学者来说没有必要了解,这里不再赘述。

注意 在调用header()函数前不能有任何的输出,否则程序将会出错。

下面介绍函数header()的几个使用范例。

在PHP中,函数header()最常见的用法就是重定向。代码9-8实现将用户的访问重定向到一个示例网站。

代码9-8 使用header()函数重定向

<?php 
header('Location: http://www.example.com/');//重定向网站
die();//结束 
?>

如代码9-9所示,欲让用户每次都能得到最新的资料,而不是Proxy或cache中的资料,可以使用下列的标头。

代码9-9 使用header()函数重定向

<?php 
/告诉浏览器此页面的过期时间(用国际标准时间表示), 只要是已经过去的日期即可 
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");/  
//告诉浏览器此页面的最后更新日期(用国际标准时间表示)也就是当天, 目的就是强迫浏览器获取最新内容 
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");  
header("Cache-Control: no-cache, must-revalidate");//告诉浏览器不使用缓存 
header("Pragma: no-cache");//与以前的服务器兼容, 即兼容HTTP1.0协议 
?>

如果限制某一页面不能被用户访问,可以用代码9-10所示的程序,设置页面状态为404。

代码9-10 使用函数header()设置页面状态为“HTTP 404未找到文件”

<?php 
header("status: 404 Not Found"); 
?>

9.7 典型实例

【实例9-1】本小节将使用Cookie,实现用户认证的功能。关于Cookie的函数非常少,本实例中使用到的与Cookie有关的函数就是setcookie()。

setcookie()函数用于生成一个Cookie,并存储在客户端的计算机上,setcookie()有7个参数:

  • 第1个参数是必选参数,其值是Cookie的名称,即$_COOKIE单元的键名。在使用Cookie值时,大部分通过这个键名来实现。
  • 第2个参数是用于设置Cookie的值,也就是$_COOKIE单元的值。当这个参数为空时,设置的Cookie的值即为空。
  • 第3个参数用于设置Cookie的有效时间,其时间以秒为单位,清单6.1中的“time()+3600”的表达式,其作用是在当前时间上加上3600秒,即1个小时,来作为这个Cookie值的有效时间。
  • 第4个参数用于设置Cookie的有效目录,在同一个域名下,可以使用这个参数,使其值只在指定的目录下有效。
  • 第5个参数用于设置Cookie的作用域名,当用户访问参数指定的网站时,其Cookie值才有效。
  • 第6个参数用于设置是否使用加密方式传输Cookie值,默认值是FALSE。
  • 第7个参数用于设置是否只使用HTTP协议访问Cookie值,如果其值是1或TRUE,其他脚本语言,如JavaScript就不能访问这个Cookie,这个参数默认的值是FALSE。

代码9-11 使用Cookie实现用户认证

<?php 
//定义一个存储用户信息和用户样式的数组 
$users = array( 
    array("username"=>"tom","password"=>"1","style"=>"css1"), 
    array("username"=>"jake","password"=>"2","style"=>"css2"), 
    array("username"=>"seven","password"=>"3","style"=>"css3"), 
    array("username"=>"andy","password"=>"4","style"=>"css4"), 
    array("username"=>"king","password"=>"5","style"=>"css5"), 
    array("username"=>"robert","password"=>"6","style"=>"css6") 
); 
//定义一个函数,用于检查用户是否登录 
function is_login(){ 
    //使用global关键字,使用$users数组 
    global $users; 
    //把Cookie中的值赋予新变量 
    $u = $_COOKIE["username"];  //读取Cookie中保存的键名为username元素的值 
    $p = $_COOKIE["password"];  //读取Cookie中保存的键名为password元素的值 
    //遍历用户数组 
    foreach($users as $key=>$value){ 
        //比较Cookie中的值与用户数组中的值 
        if($value["username"]==$u and $value["password"]==$p){ 
            //如果Cookie中的值与用户数组中的值有一对是相等的,返回TRUE 
            return true; 
        } 
    } 
    //遍历完数组后,没有相等的值,返回FALSE; 
    return false; 
} 
//定义一个函数,设置用户登录后的Cookie 
function login(){ 
    global $users; 
    //把$_POST数组中的单元赋与新变量 
    $u = $_POST["username"];  //读取$_POST变量中保存的键名为username元素的值 
    $p = $_POST["password"];  //读取$_POST变量中保存的键名为password元素的值 
    //遍历用户数组 
    foreach($users as $key=>$value){ 
        //查找表单提交的变量,是否与用户数组中的一组值相等 
        if($value["username"]==$u and $value["password"]==$p){ 
            //如果表单提交的变量等于数组中的值,设置Cookie值,供is_login()函数检查 
            setcookie("username",$value["username"]); 
            setcookie("password",$value["password"]); 
            setcookie("style",$value["style"]); 
            //使用JavaScript显示登录信息,并转向用户页,本例为同一页 
            echo "<script>alert('登录成功!');</script>";  //显示登录成功信息 
            echo "<script>window.navigate('Ch09-1.php');</script>";  
            //使用JavaScript语言,跳转到其他页面 
            return true; 
        } 
    } 
    //遍历完数组后,没有相等的数组,显示登录错误信息,并转向其他页,本例为同一页 
    echo "<script>alert('用户名或密码错误!');</script>"; 
    echo "<script>window.navigate('Ch09-1.php');</script>"; 
    return false; 
} 
//定义一个函数,用于删除Cookie,完成注销工作 
function logout(){ 
    //消除相关Cookie的值 
    setcookie("username","");  //将Cookie中键名为username的元素的值设置为空 
    setcookie("password","");  //将Cookie中键名为password的元素的值设置为空 
    //显示注销成功信息 
    echo "<script>alert('注销成功!');</script>"; 
    echo "<script>window.navigate('Ch09-1.php');</script>"; 
} 
//定义一个用户登录表单,用于用户提交登录数据 
function loginTable(){ 
print<<<EOT 
<table width="300" border="0" cellspacing="0" cellpadding="0"> 
  <tr> 
    <td><form name="form1" method="post" action="?action=login"> 
      <table width="100%" border="0" cellspacing="0" cellpadding="0"> 
        <tr> 
          <td>用户名:</td> 
          <td><label> 
            <input name="username" type="text" id="username"> 
          </label></td> 
        </tr> 
        <tr> 
          <td>密码:</td> 
          <td><label> 
            <input name="password" type="password" id="password"> 
          </label></td> 
        </tr> 
        <tr> 
          <td colspan="2"><label> 
            <input type="submit" name="Submit" value="提交"> 
          </label></td> 
          </tr> 
      </table> 
        </form> 
    </td> 
  </tr> 
</table> 
EOT; 
} 
//根据外部变量,调用函数 
switch($_GET["action"]){   //获取$_GET变量中键名为action的值 
    case "login": 
        login(); 
    break; 
    case "logout": 
        logout(); 
    break; 
} 
?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose. dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=GB2312"> 
<title>用户登录</title> 
</head> 
<body> 
<?php 
if(is_login()){   //当is_login()函数返回true值时,显示登录成功信息 
?> 
<div class="css"> 你好:<?=$_COOKIE["username"];?>&nbsp;&nbsp;&nbsp;&nbsp;<a href='?action= 
logout'>注销</a></div> 
<div class='<?=$_COOKIE["style"]?>'>用户登录后,显示的内容.</div> 
<?php 
}else{  //当is_login()函数返回的值不是true值时,显示登录窗口 
    loginTable(); 
} 
?> 
</body> 
</html>

运行该程序后,运行结果如图9.9所示。

015-01

图9.9 程序运行结果

【实例9-2】Session是存在于服务器上的一小段文本,用于记录用户的相关信息。本实例将使用相关的Session函数实现在上一个实例中Cookie同样的功能。

本实例中使用到的与Session相关的只有session_start()函数,其作用是用于初始化Session数据,把服务器上的Session文本转化为系统变量。

Session的注册可以使用session_register()函数进行,本实例直接使用数组赋值的方法,向Session添加新元素,同样可以完成添加Session的功能。

代码9-12 使用Session函数实现用户认证

<?php 
//初始化Session数据 
session_start(); 
//定义一个存储用户信息和用户样式的数组
$users = array( 
    array("username"=>"tom","password"=>"1","style"=>"css1"), 
    array("username"=>"jake","password"=>"2","style"=>"css2"), 
    array("username"=>"seven","password"=>"3","style"=>"css3"), 
    array("username"=>"andy","password"=>"4","style"=>"css4"), 
    array("username"=>"king","password"=>"5","style"=>"css5"), 
    array("username"=>"robert","password"=>"6","style"=>"css6") 
); 
//定义一个函数,用于检查用户是否登录 
function is_login(){ 
    //使用global关键字,使用$users数组 
    global $users; 
    //把Session中的值赋予新变量 
    $u = $_SESSION["username"]; 
    $p = $_SESSION["password"]; 
    //遍历用户数组 
    foreach($users as $key=>$value){ 
        //比较Session中的值与用户数组中的值 
        if($value["username"]==$u and $value["password"]==$p){ 
            //如果Session中的值与用户数组中的值有一对是相等的,返回TRUE 
            return true; 
        } 
    } 
    //遍历完数组后,没有相等的值,返回FALSE; 
    return false; 
} 
//定义一个函数,设置用户登录后的Session 
function login(){ 
    global $users; 
    //把$_POST数组中的单元赋予新变量 
    $u = $_POST["username"]; 
    $p = $_POST["password"]; 
    //遍历用户数组 
    foreach($users as $key=>$value){ 
        //查找表单提交的变量,是否与用户数组中的一组值相等 
        if($value["username"]==$u and $value["password"]==$p){ 
            //如果表单提交的变量等于数组中的值,设置Session值,供is_login()函数检查 
            $username = $value["username"]; 
            $password = $value["password"]; 
            $style = $value["style"]; 
            $_SESSION["username"]=$username; 
            $_SESSION["password"]=$password; 
            $_SESSION["style"]=$style; 
            //使用JavaScript显示登录信息,并转向用户页,本例为同一页 
            echo "<script>alert('登录成功!');</script>"; 
            echo "<script>window.navigate('Ch09-2.php');</script>"; 
            return true; 
        } 
    } 
    //遍历完数组后,没有相等的数组,显示登录错误信息,并转向其他页,本例为同一页 
    echo "<script>alert('用户名或密码错误!');</script>"; 
    echo "<script>window.navigate('Ch09-2.php');</script>"; 
    return false; 
} 
//定义一个函数,用于删除Session,完成注销工作 
function logout(){ 
    //消除相关Cookie的值 
    session_unregister("username"); 
    session_unregister("password"); 
    session_unregister("style"); 
    //显示注销成功信息 
    echo "<script>alert('注销成功!');</script>"; 
    echo "<script>window.navigate('Ch09-2.php');</script>"; 
} 
//定义一个用户登录表单,用于用户提交登录数据 
function loginTable(){ 
print<<<EOT 
<table width="300" border="0" cellspacing="0" cellpadding="0"> 
  <tr> 
    <td><form name="form1" method="post" action="?action=login"> 
      <table width="100%" border="0" cellspacing="0" cellpadding="0"> 
        <tr> 
          <td>用户名:</td> 
          <td><label> 
            <input name="username" type="text" id="username"> 
          </label></td> 
        </tr> 
        <tr> 
          <td>密码:</td> 
          <td><label> 
            <input name="password" type="password" id="password"> 
          </label></td> 
        </tr> 
        <tr> 
          <td colspan="2"><label> 
            <input type="submit" name="Submit" value="提交"> 
          </label></td> 
          </tr> 
      </table> 
        </form> 
    </td> 
  </tr> 
</table> 
EOT; 
} 
//根据外部变量,调用函数 
switch($_GET["action"]){ 
    case "login": 
        login(); 
    break; 
    case "logout": 
        logout(); 
    break; 
} 
?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>用户登录</title> 
 
</head> 
<body> 
<?php 
if(is_login()){ 
?> 
<div class="css"> 你好:<?=$_SESSION["username"];?>&nbsp;&nbsp;&nbsp;&nbsp;<a href='?action=logout'>注销</a></div> 
<div class='<?=$_SESSION["style"]?>'>用户登录后,显示的内容.</div> 
<?php 
}else{ 
    loginTable(); 
} 
?> 
</body> 
</html>

运行该程序后,运行结果如图9.10所示。

015-01

图9.10 程序运行结果

在程序运行界面中输入用户名和密码,单击“提交”按钮,系统进行认证后,产生Session数据并显示用户登录后的界面,如图9.11所示。

015-01

图9.11 用户登录后界面

【实例9-3】Session的数据存储在服务器端,如果客户端需要读取一个对应的Session,就需要一个与Session对应的ID,这个ID存储在Cookie中,并保存在客户端的计算机上。

开发人员在使用Session进行用户认证或存储临时信息时,当用户跳转到其他页面时,会发生Session失效的问题。这主要是因为Session的ID没有被正确地传递。

影响Session的ID不能正常传递的原因有以下3个:

(1)客户端禁用了Cookie。

(2)浏览器出现问题,暂时无法存取Cookie。

(3)PHP.INI中的session.use_trans_sid = 0或者编译时没有打开--enable-trans-sid选项。

针对这3个原因找到解决方法,就可以有效地防止Session在页面跳转后失效。本实例代码主要介绍了,当Cookie失效,并且PHP.INI中的session.use_trans_sid = 0时,如何跨页传递Session。

代码9-13 跨页传递Session(1)

<?php 
//初始化Session数据 
session_start(); 
//定义一个Session 
$svalue = "Session数据"; 
session_register("svalue");     //添加一个Session变量 
$sid = session_id();           //使用session_id()函数,获取Session的ID值 
//使用GET方法传递Session的ID 
echo "<a href='get_session_id.php?sid=".$sid."'>转到下一页</a>"; 
//模拟Cookie进行Session的ID传递 
$fp = fopen("sid.txt","w");      //使用fopen()函数并以w模式,创建或打开一个名为sid.txt的文件 
fwrite($fp,$sid);              //将获取的Session的ID值,保存到打开的文件中 
fclose($fp);                 //关闭文件句柄 
?>

代码9-14 跨页传递Session(2)

<?php 
//使用GET方法取得SID, 
$sid = $_GET["sid"];        //获取以GET方法传递的Session的ID值 
//读取文件中的SID 
$fp = fopen("sid.txt","r");    //打开sid.txt文件 
$sid = fread($fp,8192);     //读取sid.txt文件中保存的内容 
fclose($fp);               //关闭文件句柄 
//根据SID初始化Session数据 
session_start($sid);    //根据Session的ID值,初始化Session数据 
echo $_SESSION["svalue"];//显示Session数据中的内容 
?>

9.8 小结

本章介绍了PHP中的几个超全局变量$_SERVER、$_POST、$_FILE,以及两种存储用户信息的机制,Cookie和Session。通过本章的学习,会使读者对页面信息的显示、提交和存储用户信息的机制有一个比较深刻的认识。其实不管是采用Session还是Cookie作为存储用户信息的载体,其关键是要用在合适的地方。有时也常常把两者结合起来使用。

9.9 习题

一、填空题

1. 设置Cookie变量A、B的值分别为2008、北京,代码是_____、_____。

2. 设置Cookie的3600秒后失效代码是__________。

3. 使用Session功能的方式有两种:第一种是_____,第二种是_____。

4. 服务器利用_____来区别不同的Session,用户可以通过_____函数查看。

5. 设定Cookie变量A的值为2008,失效时间为2008年12月31日前_____。

6. 创建Cookie的方式是_____。

7. 设置Session变量name、password的值分别为polp、123456,_____、_____。

8. 调用Cookie变量的方式是_____,调用Session的方式是_____。

二、选择题

1. 每个浏览器只能保存某个服务器上的Cookie数是( )。

A. 10
B. 20
C. 30
D. 40

2. Cookie最大长度是( )。

A. 2KB
B. 3KB
C. 4KB
D. 5KB

3. 能够注销变量的函数是( )。

A. Session start()
B. Session ragister()
C. session unregister()
D. session id()

4. 下列哪个变量会立即失效( )。

A. Setcookie(“A”,”10”,time()-3600);
B. Setcookie(“B”,”10”,time()+3600);
C. Setcookie(“C”,”10”,mktime(0,0,0,1,1,2010)
D. Setcookie(“D”,”0”,mktime(0,0,0,1,1,2009)

三、简答题

1. 阐述Cookie的作用。

2. 阐述调用Session的方法。

3. 试解释Cookie和Session的异同。

四、编程题

1. 创建一个登录页面,输入昵称和密码,将输入的昵称和密码通过另一个页面显示出来。

2. 编写程序查看浏览器Session id。

教程类别