第5章 Web交互编程   Web 应用程序的基本功能是与用户进行交互,获取并处理用户提交的数据。用户提 交数据的方法有 : ① 通过表单提交,如用户注册、用户登录、留言等都是通过表单提交信 息 ; ② 使用网址中的URL 参数发送数据给服务器。这些数据都是以HTTP 请求的方式 发送。Web 服务器必须能够获取用户通过浏览器发送来的数据,才能与用户进行交互。 5.1 接收浏览器数据 浏览器可以通过表单或URL 字符串向服务器发送数据,这些数据称为HTTP 请求信 息。PHP 提供了很多预定义的超全局变量,见表5.1,用来获取HTTP 请求信息,这些超全 局变量的数据类型均为数组。 表5.1 PHP的超全局变量及功能 超全局变量 $ _POST $ _GET $ _REQUEST $ _SERVER $ _SESSION $ _COOKIE $ _FILE $ _ENV 功  能 获取客户端以POST 方式发送的HTTP 请求信息 获取客户端以GET 方式发送的HTTP 请求信息 包含 $ _GET 、 $ _POST 和 $ _COOKIE 3 类数组中的信息 获取HTTP 请求中的环境变量信息 存储和读取为单个用户保存的信息 读取用户的Cookie 信息 获取通过POST 方式上传文件时的相关信息,为多维数组 获取服务器名称或系统shell 等与服务器相关的信息   说明 : 超全局变量表示该变量在一个文件的所有区域中都可使用,包括自定义函数内部。 5.1.1 使用 $ _POST[ ] 获取表单数据 用户在表单中输入数据后,可以单击“提交”按钮,将数据提交给服务器,由在服务器 端工作的PHP 程序接收和处理这些表单数据。  119 表单提交数据的方式分为GET 和POST 两种,在定义表单时,将method 属性设置为 GET 或不设置时,都会采用GET 方式提交;将method 属性设置为POST 时,则会采用 POST 方式提交。 使用GET 方式提交数据时,表单数据将通过URL 参数的形式发送给服务器,而使用 POST 方式时,数据不会出现在URL 参数中。 在PHP 中, $ _POST 数组用来获取使用POST 方式提交的表单数据,语法如下:   变量名= $ _POST["表单元素name 属性值"] 表示将获取的某个表单元素值(如一个文本框中的内容)保存到一个服务器端变量 中。例如, $ user = $ _POST[" user" ],其中$ user 是自定义的一个变量名称,而后面的 user 则是一个表单元素的名称(name 属性值),两者不是一回事。 在实际应用中,表单的HTML 代码和获取表单数据的PHP 程序既可以分别写在两个 文件中,也可以写在同一个文件中。 1. 使用两个网页文件 下面的例子用来获取用户登录时输入的用户名和密码。它使用了两张网页,其 中5.1.php 用来显示表单,是一个纯HTML 页面,5.2. php 用来接收并输出获取的表单 数据。 .....................清单5.1.php...........................................   
 用户名:  密码:  
.....................清单5.2.php...........................................    您输入的密码是:". $ PS; ?> 5.1.php 的运行结果如图5.1 所示,单击“登录”按钮,就会将表单数据提交给5.2. php,5.2.php 接收并显示数据,如图5.2 所示。 注意: 表单代码中有几个关键属性与接收表单数据的程序密切关联,如图5.3 所示。 获取表单 数据   120     图5.1 5.1.php的运行结果图5.2 5.2.php的运行结果 图5.3 表单代码中与接收数据密切相关的属性 说明 : ① 在5.1.php 中,<form> 标记的method 属性值为post,表示该表单提交数据时以 POST 方式提交。如果将其改为get,那么将以GET 方式提交,此时必须用 $ _GET[ ] 才 能获取表单数据。 ② <form> 标记的action 属性用来指定接收表单数据的文件,它的属性值可以是相对 URL 或绝对URL 。这里因为两个文件在同一个文件夹下,直接写文件名即可。由于只有 服务器端程序才能接收表单数据,因此该文件中必须含有PHP 代码。 ③ 5.1.php 中有 3 个表单元素 : 2 个文本框和 1 个 “ 提交 ” 按钮,通过表单元素的 name 属性值可以获取该表单元素中输入的内容 ( 即value 属性值) , 其中 $ _ POST ["userName" ]会返回第一个文本框中输入的值(文本框会将框中的内容作为其value 属 性值) , $ _POST["PS" ]会返回第二个文本框中输入的值。而“提交”按钮由于没有对其 设置name 属性,因此它的value 值不会发送给服务器。 ④ 在5.2.php 中也可以不将 $ _POST 的值赋给变量,而是直接使用。例如,echo " 您输入的用户名是: " . $ _POST [ " userName" ]。但为了方便引用,也为了能对获取 的值先进行一些检验处理 ( 如过滤非法字符或空格,本例省略) , 最好先用一个变量引 用它。 2. 使用一个网页文件 上述示例中的两个文件可以合并为一个文件。也就是说,网页可以将表单中的信息 提交给自身。这样做的好处是减少了网站内网页文件的数量。  121 实现的方法是: 设置<form>标记的action = " " 或action = " 自身文件名" ,然后将表单 代码和PHP 代码写在同一文件中,并判断只有在用户提交了表单后,才执行PHP 代码,代 码如下,运行结果如图5.4 所示。 .....................清单5.3.php...........................................   
 用户名:  密码:  
您输入的密码是:". $ PS;} ?> 图5.4 5.3.php 的运行结果 说明: (1) 本例中,将5.2. php 中的PHP 代码全部放在一个条件语句if (isset ( $ _POST[' denglu' ])) {…}中。它表示,如果用户单击了“登录” 按钮( $ _POST [' denglu' ]变量就会存在),才执行该条件语句中的内容: 获取表单数据并输出。因此,当用 户刚打开页面时,还没单击“提交”按钮,就不会执行条件语句中的内容,只会显示表单。 (2) 提交表单就会刷新一次网页,而刷新页面就会将页面中的所有代码重新执行一 次。因此,用户单击“提交”按钮后,5.3.php 的代码会从头到尾重新执行一遍。 想一想: 当用户输入信息后,5.3. php 同时显示了表单界面和获取的信息,如果只 希望输出获取信息,而不再显示表单,即和5.2. php 的运行结果一样,该怎么改5.3. php 呢? 3. 获取复杂一点的表单页面 下面是一个获取用户注册信息的例子,其中5.4.php 用来显示表单,5.5.php 用来获取 表单数据。请仔细体会获取单选框、复选框、下拉框和多行文本域等表单元素中内容的 方法。  122 .....................清单5.4.php...........................................      

新用户注册

  
  姓名:
  性别:
  爱好: 太极拳  音乐  旅游
  职业:
  个性签名:
        
.....................清单5.5.php...........................................      

  "; //根据单选框的值输出先生或女士   if ( $ Sex= ="0") echo "女士

";   echo "

您选择了". $ hobbynum."项爱好:

" ;   for( $ i=0; $ i< $ hobbynum; $ i++) //通过循环输出复选框的值     echo $ hobby[ $ i].'';   echo "
您的职业: " . $ career;   echo "
您的个性签名: " . $ intro;   //var_dump( $ _POST); //获取所有表单元素的值 ?>   

返回修改

5.4.php 的初始运行结果如图5.5 所示,单击“提交”按钮后效果如图5.6 所示。  123 图5.5 5.4.php 的初始运行结果     图5.6 5.4.php 单击“提交”按钮后 说明: (1) 对于单选框,两个单选框的name 属性值一样,就表示这是一组,只能选中一个。 (2) 对于复选框,3 个复选框的name 属性值相同,也表示是一组,但复选框可以选择 多个。如果选中多个,则多个复选框的值将保存在一个数组中,可以用循环语句输出所有 选中复选框的值。 (3) 总之,表单元素可分为两类: ①对于文本框、密码框、多行文本框这些需要用户 输入内容的, $ _POST[]获取的是用户输入的内容; ②对于单选框、复选框、下拉列表框、 隐藏域这些无需用户输入内容的, $ _POST[]获取的是选中项的value 值。因此,对第② 类表单元素必须设置value 属性值。 (4) 当多个复选框属于同一组时,对其name 属性值命名,一定要命名成数组的形 式,如name = " hobby[]" 。这样, $ _POST[" hobby" ]返回的结果才会是一个数组,可以 利用数组名加索引值取得其中某个复选框的value 值,例如$ _POST[" hobby" ][1]的值 为“旅游”。还可利用count()方法获得该数组中的元素总数,例如count( $ hobby)。 4. 对$ _POST 数组的深入认识 实际上, $ _POST 是一个数组,它保存了接收到的所有的表单元素值,而$ _POST [" Sex" ]是一个数组元素。可以在5.5.php 中添加一行代码:   var_dump( $ _POST); 则输出结果为   array(5) { ["name"] => string(6) "张三丰" ["Sex"] => string(1) "1" ["hobby"] => array(2) { [0] => string(6) "太极拳" [1] => string(4) "旅游" } ["career"] => string(6) "医疗业" ["intro"] => string(10) "千杯不醉!" } 可见,该数组中数组元素的索引值为表单元素的name 属性值,数组元素的值为表单 元素的value 属性值。因此,可以用数组元素(如$ _POST[" name 属性值" ])获取对应表 单元素的value 属性值。 $ _POST 数组元素的索引一定要加引号,如$ _POST[" Sex" ],不加引号虽然不会出 错,但运行效率会大大降低,原因请看3.5.1 节中“创建数组的注意事项”。  124 5.1.2 使用$ _GET[]获取表单数据 如果表单是以GET 方式提交的,即method 属性值为get(或没有设置),则必须用 $ _GET[]数组获取表单中的数据。下面将5.1. php 修改为以GET 方式提交数据 (5.6.php),将5.2.php 修改为使用$_GET[]获取数据(5.7.php)。代码如下,运行结果类 似于图5.1 和图5.2。 .....................清单5.6.php...........................................   
 用户名:  密码:  
.....................清单5.7.php...........................................    您输入的密码是:". $ PS; ?> GET 方式与POST 方式提交的区别在于: GET 方式会将表单中的数据以URL 字符 串的形式发送给服务器。例如,当单击图5.1 中的“登录”按钮后,浏览器地址栏会显示:   http://localhost/5.7.php?userName=tang&PS=123 而以POST 方式提交,浏览器地址栏只会显示:   http://localhost/5.1.php 可见,POST 方式提交表单比GET 方式提交表单更安全,不会泄露机密数据。并且, POST 方式发送的字节数没有限制。 5.1.3 使用$ _GET[]获取URL 字符串信息 URL 字符串又称为查询字符串,这些字符串信息总是以GET 方式提交给服务器,可 以使用$_GET[]方法获取URL 字符串信息。 1. URL 字符串 有些网页的URL 后面会接一些以“?”号开头的字符串,称为URL 字符串。例如:   http://ec.hynu.cn/otype.php?owen1=近期工作&page=2 其中,“?owen1 = 近期工作&page = 2” 就是一个URL 字符串,它包含2 个URL 变量  125 (owen1 和page),而“近期工作”和“2”分别是这两个URL 变量的值,URL 变量和值之间 用“ = ”号连接,多个URL 变量之间用“&”连接。 URL 字符串会连同URL 信息一起作为HTTP 请求数据提交给服务器端的相应文 件,例如上面的URL 字符串信息将提交给otype. php。利用$ _GET[]可以获取URL 字符串中变量的值。例如,在otype. php 中编写如下代码,就能获取到这些查询变量 的值。    2. 设置URL 字符串的方法 当网页通过超链接或其他方式从一张网页跳转到另一张网页时,往往需要在跳转的 同时把一些数据传递到第二张网页中。把这些数据作为URL 字符串附在超链接的URL 后,就可以在第二张网页中使用$ _GET[]获取URL 变量的值。例如:   查询结果第5 页 则在search. php 中就可用$ _GET[]获取第一张网页传递来的URL 变量的值。这是通 过超链接设置URL 字符串,第二种方法是在<form>标记的action 属性中设置。下面分别 举例介绍。 例5.1 在超链接中设置URL 字符串并获取,运行结果如图5.7 和图5.8 所示。 .....................清单5.8.php...........................................      .....................清单5.9.php...........................................   这是第一条新闻

";   elseif ( $ id= =2)     echo "

这是第二条新闻

";   elseif ( $ id= =3)     echo "

这是第三条新闻

";   else echo "

参数非法

"; ?> 获取URL 变量  126 图5.7 单击5.8.php 中的第二个超链接     图5.8 5.9.php 的运行结果 说明: ① 5.8.php 中的所有链接都链接到同一网页,只是设置了不同的URL 变量值,就可 以使5.9.php 根据不同链接传来的不同id 值显示对应的网页内容,实现了动态新闻网页 效果。 ② URL 变量中的数据都是字符串类型的值,因此,如果要对数值进行判断,最好先 转换为数值型,这样可防止非法用户手工在URL 后注入非法参数。 例5.2 在<form>标记的action 属性中设置URL 字符串。运行结果如图5.9 所示。.....................清单5.10.php...........................................          姓名:            '; ?> 图5.9 5.10.php 的运行结果 说明: 在<form>标记中,“action = " ?flag = 1" ”省略了文件名表示将表单提交给自身, 设置查询字符串flag = 1 用来判断用户是否单击了“提交”按钮,一旦单击了,则URL 地址 后会增加" ?flag = 1" ,因此可据此输出不同的内容。 3. 设置URL 字符串的方法总结 如果要设置URL 字符串,以便将URL 字符串中的信息传递给相应网页,有以下3 种 方法。 ① 在超链接的href 属性值中的URL 后添加URL 字符串; ② 在表单的action 属性值中的URL 后添加URL 字符串;   127 ③ 直接在浏览器地址栏中的网页URL 后手工输入URL 字符串。 显然,普通用户不会使用第③种方法设置URL 字符串,因此一般使用方法①或②诱 导用户将URL 变量传递给相关网页。 提示 : 表单如果设置为GET 方式提交,那么表单中的数据将转换成URL 字符串发 送给服务器。此时若在表单的action 属性值中也设置URL 字符串,那么将发生冲突, action 属性值中的URL 字符串将无效。因此,如果在action 属性值中有URL 字符串,则 表单只能用POST 方式提交,5.10.php 就是一个例子。 5.1.4 发送HTTP 请求的基本方法 浏览器向服务器发送HTTP 请求有两种方法 : 一种方法是在地址栏输入网址并回 车,这样将以GET 方式向服务器发送一个HTTP 请求;另一种方法是提交表单,如果设置 form 标记的method 属性为get,那么表单中的数据将以GET 方式发送给服务器;如果设 置form 标记的method 属性为post,那么数据将以POST 方式发送。对于GET 方式的 HTTP 请求,服务器端只有使用$_GET[ ] 才能获取其中的数据,而对于POST 方式的 HTTP 请求,服务器端只有使用$_POST[ ] 才能获取其中的数据,见表5. 2 。 表5.2 浏览器发送请求与服务器获取请求的方法 发送HTTP 请求发送请求的方式服务器获取请求的方法 输入网址(URL) GET 方式  $ _GET[ ] 提交表单 method = " get"   method = " post" POST 方式 $ _POST[ ]   一个HTTP 请求实际上是一个数据包,如果以提交表单形式发送HTTP 请求,则这个 数据包中含有表单数据,如果是GET 方式发送的请求,则包含了URL 字符串中的数据。 以5.1.php 和5.2.php 的执行过程为例,我们可以把浏览器发送的HTTP 请求数据包 想象成一辆卡车,它装载了用户在表单中填写的信息。当单击“提交 ” 按钮后,就会发送 HTTP 请求给服务器。这就好比这辆卡车载着货物(表单中的信息)从浏览器行驶到了服 务器。服务器此时可以使用 $ _POST[ ] 卸下卡车上的货物,保存到服务器端的变量中。 整个过程如图5.10 所示。 图5.10 浏览器发送HTTP 请求和服务器获取HTTP 请求内容的示意图