内容


用 PHP 构建基于 Ajax 的 Web 站点

用当今最新的框架构建站点

Comments

PHP 已经流行很多年了。PHP 通常作为服务器端脚本语言,用来快速开发基于 Web 的应用程序,而且效果很不错。实际上,一些最流行的 Web 项目(比如 PHP-Nuke、osCommerce 和 Joomla)都是用 PHP 开发的,它们至今仍然很兴旺。

Ajax 也已经出现了一阵子了,但是直到最近使用 Ajax 技术开发的 Web 站点才开始大量增加。Ajax 技术使 Web 站点或 Web 应用程序能够自动地与服务器通信,而不需要刷新整个页面。从本质上说,Ajax 的异步特性使客户机浏览器能够向服务器发送请求或调用服务器端的方法。在客户端,可以使用 JavaScript 代码处理服务器返回的结果,然后可以把任何输出合并到现有的前端 HTML 视图中,而不需要刷新页面。在使用 Ajax 时,实际上并不使用新的编程语言。实际上,只需组合使用现有技术。

PHP 和 Ajax 的组合提供一个强大的平台,可以用来创建具备健壮的特性的 Web 站点或 Web 应用程序。本文讨论 PHP 和 Ajax 的一些用途,研究如何在自己的 Web 应用程序中使用它们。在阅读本文之前,您应该充分理解 HTML 和 JavaScript 编程。您还应该熟悉 PHP 脚本编程语言,虽然也可以使用大多数其他脚本语言。

与服务器通信

在 Ajax 中客户机 / 服务器通信的关键是使用 JavaScript XMLHttpRequest对象。大多数浏览器都支持这个对象,包括 Windows®Internet Explorer 5.0 和更高版本、Safari 1.2、Mozilla Firefox、Opera 8 和更高版本以及 Netscape 7。为了解释传统客户机 / 服务器通信和基于 Ajax 的客户机 / 服务器通信之间的差异,下面举一个例子。按照传统方式,为了让客户机浏览器向服务器发送需要处理或存储在数据库中的内容,常常使用 POST方法把客户端上输入控件收集的内容发送到服务器。服务器使用 PHP(或其他脚本语言)处理这些内容,使用数据库读取或存储数据,最后返回嵌入在 HTML 代码中的结果。然后,浏览器处理 HTML 并向最终用户显示一个新页面。图 1 描述这个场景。

图 1. 提交数据并接收结果的传统过程
提交数据并接收结果的传统过程
提交数据并接收结果的传统过程

通过使用 Ajax,同样的过程在前端需要的时间更少。其基本思想是让用户感觉不必等待页面更新。实际上,通过使用 Ajax,可以用一个 HTML 页面构成整个 Web 应用程序,但是不建议这么做。按照传统方式,如果希望向服务器提交一个表单,就要设置表单的动作并把动作类型指定为 POST。在使用 Ajax 时,实际上并不向服务器直接提交表单,而是调用一个 JavaScript 函数。这个函数从表单收集数据并执行检验,然后使用 XMLHttpRequest把数据发送给一个服务器端函数。当结果返回客户机时,客户机处理结果并更新需要更新的页面部分。在这种情况下,页面 并不全部地刷新。因此,处理 HTML 所花费的时间更少,性能会更好。图 2 说明了使用 Ajax 更新页面与刷新整个页面之间的细微差别。

图 2. 提交数据并接收结果的 Ajax 过程
提交数据并接收结果的 Ajax 过程
提交数据并接收结果的 Ajax 过程

现在看看通过 JavaScript 代码与服务器进行通信所需的步骤。首先,定义表单的外观,见清单 1。

清单 1. HTML 表单
 <body> 
 My First Ajax Page 

 <form name="myForm"> 
 Press button to view server time: 
  <input type="button" value="Update"
  onClick="ajaxFunction();" /> 
 Server Time Is: <input type="text" name="time" /> 
 </form> 

 </body>

这个表单产生图 3 所示的输出。

图 3. HTML 表单的输出
HTML 表单的输出
HTML 表单的输出

这个表单没有做任何真正有用的事,但是它帮助您了解在自己的代码中的什么地方集成 Ajax。

请注意按钮上指定的 onClick事件。这个事件调用一个名为 ajaxFunction的 JavaScript 函数。这里就是 Ajax 中比较有趣的地方。在这个方法中,要执行几个步骤,本节会逐一解释这些步骤:

  1. 创建 XMLHttpRequest对象的实例。
  2. 连接要调用的服务器端服务。
  3. 告诉 Ajax 在服务器端代码执行完成并返回结果时应该调用哪个方法。
  4. 发送请求。
  5. 异步地响应。

创建 XMLHttpRequest 实例

需要创建 ajaxFunction并提供一个变量来容纳创建的 XMLHttpRequest对象。与任何 JavaScript 方法一样,按照清单 2 所示定义这个方法。

清单 2. ajaxFunction的定义
 function ajaxFunction() { 
  var xmlHttp = null; 
  . 
  . 
  . 
 }

大多数现代浏览器都支持 XMLHttpRequest对象。但是,Internet Explorer 6 等比较陈旧的浏览器要求创建一个 ActiveX 对象来执行异步的服务器调用。这会产生一个问题:必须判断正在运行代码的浏览器类型并创建适当的对象。JavaScript 代码通过它的 try/catch功能提供了一个解决方案。只需以正确的优先次序尝试创建对象,让 try/catch块处理其余的事情。清单 3 给出一个代码示例。

清单 3. 创建适当的对象
 function ajaxFunction() { 
  var xmlHttp=null; 
  
  try 
  { 
    // Firefox, Internet Explorer 7. Opera 8.0+, Safari. 
    xmlHttp = new XMLHttpRequest(); 
  } 
  catch (e) 
  { 
  // Internet Explorer 6. 
  try 
    { 
    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 
    } 
  catch (e) 
    { 
    try 
      { 
      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 
      } 
    catch (e) 
      { 
      return false; 
      } 
    } 
  } 
 }

可以看到,所有现代浏览器都支持创建 XMLHttpRequest对象。关于 Microsoft®是真正支持 XMLHttpRequest对象,还是使用一个 façade 包装 ActiveX 实现,还有一些争议。

打开服务器连接

在同一个 JavaScript 函数中,创建 XMLHttpRequest对象之后,使用 XMLHttpRequest对象的 open方法打开一个到服务器端脚本的连接。这个方法有两个必要参数和三个可选参数,见表 1。

表 1. open方法的参数
参数说明
method指定要使用的 HTTP 方法。有效值包括 GETPOSTPUTHEAD
url指定要调用的 XML 数据或服务器端 XML Web 服务的绝对路径或相对路径。为了防止跨站点脚本攻击,Ajax 请求针对的 URL 必须使用与包含 Ajax 请求的页面相同的协议、主机和端口。尽管一些浏览器可能允许任意的 URL,但是并非所有浏览器都支持这么做。如果需要跨站点通信,必须在服务器端使用 cURL 或其他方法进行处理。
async如果希望异步地向服务器发送请求,应该把这个参数设置为 true。true 值还要求设置 onreadystatechange属性,稍后讨论这个属性。把这个参数设置为 false 会禁止大多数浏览器接收任何进一步的用户输入。如果应用程序足够灵活,能够在执行后端操作的同时继续接收输入,那么最好异步地执行操作。
user指定一个用户名,用来在执行脚本之前对用户进行身份验证。只有在脚本要求用户身份验证的情况下,才需要这个参数。
password指定一个密码,用来在执行脚本之前对用户进行身份验证。只有在脚本要求用户身份验证的情况下,才需要这个参数。

对于这个示例,代码只需要执行一个 GET操作,向服务器上的一个脚本请求时间。还告诉 open方法我们希望异步地执行操作,见清单 4。

清单 4. open方法调用
 function ajaxFunction() { 
  
  . 
  . 
  . 
  xmlHttp.open("GET", "time.php", true); 

 }

告诉 Ajax 在服务器端代码执行完成时应该调用哪个方法

在使用 Ajax 调用服务器时,产生的响应是通过调用一个回调函数返回的。可以创建并命名一个函数,也可以创建无名的函数。无论是哪种情况,都需要设置 XMLHttpRequest对象的 onReadyStateChange属性,让它知道要使用的回调函数,见清单 5。

清单 5. 设置 onReadyStateChange属性
 function ajaxFunction() { 
  
  . 
  . 
  . 
  xmlHttp.onreadystatechange=function() { 
  	 if(xmlHttp.readyState==4) 
    { 
  		 // Get the data from the server's response. 
  	  document.myForm.time.value=xmlHttp.responseText; 
  	  xmlHttp=null; 
    } 
  } 
 }

可以看到,调用这个方法之后,它会检查 readyState,寻找有效值 4。共有五个有效状态,见表 2。

表 2. readyState的有效值
说明
0未初始化
1正在装载
2装载完成
3交互状态
4已经完成

这段代码的基本意思是,“如果状态指出操作已经完成,就进行处理”。当状态为已经完成时,下一步是用服务器响应更新需要更新的页面部分。这需要接收赋值给 responseText属性的值,这就是服务器响应。最后,通过把 XMLHttpRequest对象赋值为 null,停止这个对象。

发送请求

ajaxFunction还需要执行一个步骤,也就是把请求发送到服务器。这需要使用 XMLHttpRequest对象的 send方法。如果请求是异步的,这个方法会在发送请求之后立即返回。如果请求是同步的,这个方法在收到响应之后才会返回,这意味着 Ajax 函数会一直阻塞,直到这个方法返回。

这个方法有一个参数,可以把它设置为 null 或许多其他值。例如,可以传递一个 DOMDocument对象、InputStreamString。如果请求方法是 POST,这个值就用作 HTTP 请求体。完成的 ajaxFunction应该与清单 6 相似。

清单 6. 完成的 ajaxFunction
 function ajaxFunction() { 
 var xmlHttp=null; 
 
 try { 
   // Firefox, Internet Explorer 7. Opera 8.0+, Safari 
   xmlHttp = new XMLHttpRequest(); 
 } catch (e) { 
   // Internet Explorer 6. 
   try { 
     xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 
   } catch (e) { 
     try { 
       xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 
     } catch (e) { 
       alert("Your browser does not support AJAX!"); 
       return false; 
     } 
   } 
 } 
 xmlHttp.open("GET", "time.php", true); 
 xmlHttp.onreadystatechange=function() { 
   if(xmlHttp.readyState==4) { 
     // Get the data from the server's response. 
     document.myForm.time.value=xmlHttp.responseText; 
     xmlHttp=null; 
   } 
 } 
 xmlHttp.send(""); 
 }

异步地响应

因为 Ajax 在本质上是异步的,所以必须注意并发性并了解处理次序。在发出多个 Ajax 调用并以出乎意料的次序接收响应时,这尤其重要。一般假设次序是无法意料的。

有时候,服务器响应需要以 XML 文档的形式返回给客户机。在这些情况下,可以使用 XMLHttpRequest对象的 responseXML属性接收数据。清单 7 给出一个返回 XML 文档的 PHP 脚本示例。

清单 7. 返回 XML 文档的 PHP 代码
 <?php 

 $result = getRecordSet($_GET['query']; 

 echo '<?xml version="1.0" encoding="ISO-8859-1"?>' . 
  '<car>'; 

 while($row = mysql_fetch_array($result)) { 

  echo "<make>" . $row['make'] . "</make>"; 
  echo "<model>" . $row['model'] . "</model>"; 
  echo "<year>" . $row['year'] . "</year>"; 
  echo "<description>" . $row['description'] . 
	  "</description>"; 
 } 
 echo '</car>'; 
 ?>

这段代码创建一个 XML 文档(由 '<?xml version="1.0" encoding="ISO-8859-1"?>'表示),然后发送响应的其余部分。客户端代码必须先从 responseXML属性中取出 XML 文档,使用 Document Object Model(DOM)解析数据,然后通过修改页面上现有的适当字段在页面上显示数据。清单 8 演示这些步骤。

清单 8. 处理 XML 文档的 JavaScript 代码
 function stateChanged() {   
  if(xmlHttp.readyState==4)  { 
    xmlDoc = xmlHttp.responseXML;   
    document.getElementById("make").innerHTML = 
      xmlDoc.getElementsByTagName("make")[0].childNodes[0].nodeValue; 
    document.getElementById("model").innerHTML = 
      xmlDoc.getElementsByTagName("model")[0].childNodes[0].nodeValue; 
    document.getElementById("year").innerHTML = 
      xmlDoc.getElementsByTagName("year")[0].childNodes[0].nodeValue; 
    document.getElementById("description").innerHTML = 
      xmlDoc.getElementsByTagName("description")[0].childNodes[0].nodeValue; 
  } 
 }

用 JavaScript 框架扩展 Ajax

您可能会注意到,为了在前端实现 Ajax 功能,服务器端 PHP 代码并不需要任何特殊的东西。实际上,可以用任何语言编写服务器端脚本,只要能够从 Web 服务器调用它并把结果返回给客户机。但是,出于几个目的,希望扩展 Ajax 来实现其他功能。例如,许多库提供了外观更好的前端控件,可以实现 Web 2.0 所需的效果。这些库大多数是用 JavaScript 代码编写的,并提供了可以减少编写前端所需的 JavaScript 代码量的特性和 API。另外,这些库大多数使用 JavaScript Object Notation(JSON),这是一种目前在因特网上广泛使用的轻量数据交换格式。下面是可能对您有帮助的一些库:

  • Prototype
  • Script.aculo.us
  • Dojo
  • jQuery

Prototype

Prototype 提供用来开发动态 Web 应用程序的类驱动的 JavaScript 代码。另外,Prototype 框架还提供一个全局 Ajax 对象,这个对象使 Ajax 功能更容易编写、效果更好、更容易处理。另外,通过使用这个框架进行 Ajax 开发,就不再需要处理跨浏览器问题。只需在一次调用中指定目标 URL、HTTP 方法(POSTGET)和响应回调函数等等。

Script.aculo.us

Script.aculo.us 是另一个流行的 JavaScript 框架,它提供一些出色的用户界面控件。这个框架还提供了一些执行 Ajax 功能的控件。甚至还有一个 Google 风格的自动补齐文本控件,可以用它收集用户输入的文本。Ajax 功能允许轻松地指定查询的服务器端目标。产生的响应用来向最终用户显示服务器返回的字符串集。

Dojo

Dojo 工具集是一个开放源码的 JavaScript 和 Ajax 框架,它速度快和文件小(只有 25 KB),因此很受欢迎。在 Ajax 方面,Dojo 提供了用来发送和接收异步服务器调用和响应的 API。在服务器端不需要修改任何代码。对于任何 Ajax 调用,您的 PHP 代码仍然可以做出响应。

jQuery

jQuery 的优点是简化了在页面上搜索元素的机制,并支持在运行时动态地添加新函数、特性和格式。它还提供一些与众不同的 Ajax 特性,支持在 Web 页面上提供 Ajax 交互。

扩展 PHP 来执行 Ajax

既然了解了基本概念,现在就来讨论如何扩展 PHP 来支持 Ajax。从 PHP 的角度来看,扩展 Ajax 功能并不仅仅是重写 XMLHttpRequest(XHR)访问代码。这还涉及以更简单更直观的方式提供前端服务,然后通过它们访问用 PHP 编写的后端服务。应该包括从前端执行后端服务、访问数据库、执行后端网络服务等特性。我在市场上看到的一些框架允许开发人员用后端语言编写代码,然后由框架创建前端 JavaScript 代码。开发人员告诉框架必须调用哪些后端方法,框架就会用 JavaScript 代码编写前端 façade,这些代码可以分配 XHR 对象、发送请求、接收响应,然后把响应传递给您选择的函数,甚至把输出直接赋值给您选择的 HTML 元素。这种框架设计思想可以减少必须编写的 JavaScript 代码。希望为其提供函数的所有元素都可以被覆盖,可以把它们连接到在发生指定的前端事件时做出响应的后端方法。下面是值得研究的一些框架:

  • PHP AJAX
  • PHP-Ext
  • ExtPHP

PHP AJAX

PHP AJAX 允许开发人员用自己的类扩展 PHP 类。然后,只需在调用 PHP 文件时调用一个初始化方法,它会替您生成必需的前端 XHR 代码。前端事件必须调用一个与 PHP 类同名的 JavaScript 函数。代码与清单 9 相似。

清单 9. 用自己的 PHP 类扩展 PHP AJAX
 class ajax_app extends phpajax { 
 function input() { 
 } 
 function loading() { 
 } 
 function main() { 
 } 
 }

调用覆盖的方法执行 Ajax 生命周期中的各种任务。例如,如果在前端执行一个操作,就调用后端类的 main()方法处理这个操作。在前端收集的所有输入都传递给 input()方法。

PHP-Ext

PHP-Ext 提供一个支持 PHP 4 和 5 的库,这个库提供大量前端用户界面控件。这些控件的底层代码实际上是由 Ext JS 提供的,但这个框架的特色是开发人员不需要提供 JavaScript 来操作前端控件。相反,与控件的所有交互都是通过用 PHP 编写的后端服务来执行的。在需要时,根据指定的事件调用 PHP 代码。当发生指定的事件时,就会调用对应的 PHP 代码。按照这种方式,可以从 PHP 代码几乎直接地填写网格和其他控件的内容。

ExtPHP

用 PHP 编写的另一种 Ext JS 包装器是 ExtPHP(不要与前面提到的 PHP-Ext 混淆)。按照这个项目的开发负责人的说法,可以使用 ExtPHP 编写侵入式和非侵入式 JavaScript 代码,编程方式与使用 Ext JS 时相同。这个框架的优点是允许 PHP 编辑器探测未知的、拼写错误的或使用不当的方法,这样就不必在 Web 浏览器中调试 JavaScript 代码。ExtPHP 的设计思想是生成可以从 PHP 脚本调用的 PHP 类。在实例化一个对象时,会把对应的 JavaScript 代码存储在一个内部缓冲区中。如果调用一个对象的方法,代码也被添加到内部缓冲区中。准备好所有 JavaScript 代码之后,只需调用一个方法 jsrender()。还可以通过调用 ExtPHP 函数在输出中添加内容,这样就可以在输出中直接添加 JavaScript 代码。

结束语

本文介绍了如何编写基于 Ajax 的前端代码,以及如何把前端代码和后端 PHP 脚本结合起来。还介绍了一些最新的框架,可以使用这些框架大大加快 Ajax Web 应用程序的创建。通过结合使用这些框架、Ajax 和 PHP,可以编写出外观优美、功能丰富的 Web 应用程序。实际上,如果您掌握了这些新技术,就会觉得离不开它们了。


相关主题

  • 您可以参阅本文在 developerWorks 全球网站上的 英文原文
  • JavaScript.com是了解 JavaScript 代码和相关的新兴技术的出色资源。
  • PHP Ajax FrameworksWeb 站点提供了用来简化 PHP/Ajax 应用程序开发的框架列表,通过使用这些框架,您就不必亲自编写所有 Ajax JavaScript 代码。其中许多框架在后台工作,使您能够把精力集中在应用程序的核心上,而不必过多关注 Ajax 客户机 / 服务器通信所需的基础结构。
  • Ajax & PHP without using the XmlHttpRequest Object”(PHPit,2005 年 11 月)提出了一些非常好的想法,描述如何编写可以在不依靠 XMLHttpRequest对象的情况下使用 Ajax 概念的 PHP 代码。但是,这只能使用 GET方法,所以如果需要向服务器发送超过 500 字节的数据,就必须使用其他办法。
  • Ajaxian提供关于 Ajax 所有方面的资料。这是一个必须访问的 Web 站点。关于 Ajax 的任何内容都可以在这个 Web 站点上找到。无论您是使用 PHP 还是其他语言,这个站点都会有帮助。
  • Ajax 资源中心:developerWorks 上所有有关 Ajax 的问题都可以在这里找到解答。
  • 利用 developerWorks 的 Web 开发专区中的专业文章和教程提高您的 Web 开发技能。
  • 如果希望用一种出色的 API 或框架改进 JavaScript,Prototype是合适的选择。它扩展了 JavaScript 的功能。这个框架已经成为标准,其他 JavaScript 框架开发人员在构建新框架时使用它作为底层基本框架。实际上,script.aculo.us 就是在 Prototype 上构建的。
  • script.aculo.us库提供一些非常精美的用户界面控件。我的许多客户都非常欣赏这个既方便又小巧的库。
  • JSON是一种轻量的数据交换格式,既适合人阅读,也适合计算机解析。JSON 不但适合 JavaScript 代码,而且已添加到 PHP 语言 5.2.0 版
  • Ext JS是一种包含 Ajax 和用户界面组件的 JavaScript 框架。它与 Prototype、Yahoo UI 和 jQuery 相互协作。这个项目有商用和开放源码两种许可证。
  • Dojo通过一个简洁小巧的软件包提供 Ajax、事件、打包、基于 CSS 的查询等功能。
  • jQuery是一个 JavaScript 库,可以简化 HTML 文档导航、事件处理和动画。它还有一些 Ajax 功能,让开发人员可以轻松地在前端 HTML 中添加调用后端服务器脚本的 Ajax 逻辑。
  • PHP AJAX框架可以在调用 PHP 文件之后动态地生成所需的所有 JavaScript 代码。只需编写一个扩展 PHP Ajax 类的 PHP 类,编写在后端处理前端调用的方法。
  • PHP-Ext是一个基于 Ext JS 的开放源码部件库,它使开发人员可以编写 PHP 脚本而不必编写 JavaScript 代码。
  • 可以使用 ExtPHP库编写侵入式和非侵入式 JavaScript,编程方式与使用 Ext JS 时相同。

评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development, Open source
ArticleID=340476
ArticleTitle=用 PHP 构建基于 Ajax 的 Web 站点
publish-date=09232008