<p> 随着 Internet 应用程序开发人员之中不断有人创建和采用 PHP,使得它获得了不断发展而且并入了很多有用的标准。PHP 刚刚向 PHP V5.2 中添加了 JavaScript Object Notation (JSON) 扩展,以前该扩展只可用作附加框架类。这次添加为 PHP 开发人员在使用 JSON 开发 Ajax 应用程序时提供了更好的支持。本文是 “PHP V5.2 中的新增功能” 系列(共五部分)的第 3 部分,将展示如何有效地使用此应用程序,并且在阅读完本文后,您将可以熟练地将内置 JSON 扩展与 PHP 结合使用来开发 Ajax 应用程序。</p><p> Ajax 入门</p><p> Ajax 作为一种创建功能全面的 Web 应用程序的优秀方法,借助 XML 的力量将数据表单和功能分离,打破了 Web 浏览器的规则和限制,使 Internet 的整体速度获得了提升。Ajax 的主要限制包括在 JavaScript 中处理 XML。XML 的优势同样也使自己变得十分复杂。在您确保了 XML 文档的格式正确无误并且设置了错误处理之后,仍必须把 XML 置入某种 JavaScript 可用的对象中。把 XML 整合到应用程序中以供使用并不像听起来那么简单。</p><p> 由于 XML 不是 JavaScript 本来就有的,因此我们最好使用 XML 的固有语言,例如 PHP 和被转换为 JavaScript 的固有格式的简单数据。</p><p> 我们遇到的另一个问题是不总是希望或需要在把数据装入 Ajax 应用程序之前将数据转换为 XML。然而,在 Ajax 开发人员可以使用我们提供的数据之前,我们需要遵守标准。一旦我们在 PHP 代码中创建了对象,我们可以将其序列化,并导出到应用程序的 Ajax 部分中,处理并取回。</p><p> JSON</p><p> JSON 是一项旨在允许中间件创建使用 JavaScript 固有格式的对象的协议。它最强大的属性是它是一种轻量级协议。简单处理 RSS 聚合或 recipe 列表时,您不需要在 JavaScript 中使用 XML 的全部功能。不需要验证格式或确保严格的数据键入。我们可以跳过与处理 XML 相关的大量工作,即使术语 Ajax 包括 XML。为了编写更简练的代码,您可以使用 JSON 来简化过程。让我们来看一个显示来自 RSS 摘要数据库应用程序的数据的简单 XML 文档示例。</p>
<p> </p>
<p> 清单 1. XML 格式示例<code>Listing 1 - XML Format Example<br /><?xml version="1.0" ?><br /><root><br /> <feed><br /> <id>21</id><br /><url>www.blah.com/story1.html</url><br /> <title>JSON is sweeping AJAX world</title><br /> <viewed>FALSE</viewed><br /></feed><br /><feed ><br /> <id>22</id><br /><url> www.blah.com/story2.html</url><br /> <title>JSON is great</title><br /> <viewed>FALSE</viewed><br /></feed><br /></root></code></p><p> 要获得此 XML 文档,我们需要访问数据库,取出相关数据,并使用 PHP 在此 XML 文档中设定格式。虽然 Ajax 可以利用 XML,但是在大多数情况下都是不必要的。控制结构所需的负载带宽量对于只需共享一些链接的简单应用程序来说完全没必要。此外,我们必须递归处理 MySQL 结果,删除非法字符以及逐位构建我们的 XML 文档。</p><p> JSON 在这种情况下将提供帮助,因为我们可以使用 json_encode() 把任何 PHP 对象序列化,使该对象转换为 JSON 协议字符串,以供 Ajax 应用程序读取。这要比创建 XML 文档便捷得多,因为我们只需把 MySQL 结果直接传给函数。由于 MySQL 结果是以联合数组的形式传入的,因此没有任何中间步骤。</p><p> 让我们来看一看如果把以上 XML 文档转换为 JSON 对象会发生什么情况(参见清单 2)。目前,数据库和数据格式都是任意的;我们将在稍后的部分中了解它们的实际情况。</p><p> 清单 2. 把 XML 转换为 JSON 的 PHP 示例<code><?php<br />//we assume that $results is the result of an SQL query but we will construct it now<br />$results = array("21" => array("url" => "www.blah.com/story1.html",<br />"title" => "JSON is sweeping AJAX world",<br />"viewed" => FALSE), "22" => array("url" => "www.blah.com/story2.html",<br />"title" => "JSON is great", "viewed" => FALSE));<br />//we now have a populated array object in $results resembling a possible MySQL result<br />$jsonObject = json_encode($results);<br />echo $jsonObject;<br />?></code></p>
<p> </p>
<p> 全部都能理解么?结果没有使用递归。没有添加标记。只需将其传入 json_encode() 函数,然后它将从另一端作为 JSON 序列化对象传出。参见清单 3 以查看新对象。</p><p> 清单 3. JSON 序列化的 XML 对象示例<code>{"21":{"url":"www.blah.com/story1.html","title":"JSON is sweeping AJAX<br />world","viewed":false},"22":{"url":"www.blah.com/story2.html",<br />"title":"JSON is great","viewed":false}}</code></p><p> 我们有了一个包含数组对象并且以 JSON 格式序列化的字符串。关于此字符串需要注意几点:encode 函数已经自动把正斜杠转义为反斜杠,并且变量类型都是可以标识的,这取决于我们是否使用引号。由于数组中的 ID 号都使用了引号,因此那些 ID 号都被识别为字符串。布尔型 false 元素都被保留为布尔型。</p><p> 现在我们已经序列化了对象,我们可以在 Ajax 应用程序的任意数目的 JSON 函数中使用它。</p><p> 编码和解码</p><p> 有两个函数用于 JSON:encode 和 decode。像您想象的一样,第一个函数将把任意类型的数据对象转换为一组序列化数据,以供 JavaScript 处理。第二个函数将把序列化数据解码,并将其转换为基本 PHP 对象或联合数组。我们已经见过使用 json_encode() 的示例,因此让我们来看一看 json_decode()。</p><p> 清单 4. json_decode() 的示例<code><?php<br />$jsonObject = '{"21":{"url":"www.blah.com/story1.html","title":"JSON is sweeping AJAX<br />world","viewed":false},"22":{"url":"www.blah.com/story2.html","title":"JSON is<br />great","viewed":false}}';<br />$decodedObject = json_decode($jsonObject);<br />$decodedArray = json_decode($jsonObject, true);<br />print_r($decodedObject);<br />echo "<br><br>";<br />print_r($decodedArray);<br />?></code></p>
<p> </p>
<p> 如上,我们有一个 PHP 脚本,该脚本将获取 $jsonObject 并将其解码回 PHP 固有对象。我们进行了两次解码。第一次,使用未经修改的用法,这将得到 stdClass 的对象;第二次,使用布尔型参数来创建联合数组。</p><p> 清单 5. 清单 4 的输出<code>stdClass Object ( [21] => stdClass Object ( [url] => www.blah.com/story1.html [title] =><br />JSON is sweeping AJAX world [viewed] => ) [22] => stdClass Object ( [url] =><br />www.blah.com/story2.html [title] => JSON is great [viewed] => ) )<br />Array ( [21] => Array ( [url] => www.blah.com/story1.html<br />[title] => JSON is sweeping AJAX world [viewed] => )<br />[22] => Array ( [url] => www.blah.com/story2.html [title] =><br />JSON is great [viewed] => ) )</code></p><p> 我们看到两个对象,使用 print_r() 列出。</p><p> 从数据库到 JSON</p><p> 在建议的 Ajax 应用程序中,我们的项目经理希望使用来自另一个应用程序提供的数据库的数据。存储 Web 服务器的 MySQL 数据库中选定 RSS 摘要结果的 RSS 聚合器将经常检查并更新 RSS。要阅读 RSS,我们的应用程序将要求使用 Ajax 接口。作为专业的后端程序员,我们将专注于从数据库中获得数据,并将其转为 JSON 格式。我们将把 Ajax 留给专家,但是我们必须把 Ajax 准备好以供专家们处理。</p><p> 首先,我们将设置 MySQL 数据库来存储 RSS 摘要信息,然后插入若干条记录以准备开始。然后,我们将编写一个 PHP 脚本,该脚本将进入数据库并为基于 JSON 的应用程序检索一些记录以供使用。</p><p> 设置</p><p> 我们需要设置 MySQL 数据库并插入一些简单记录以供我们提取。为便于使用示例,我们将使用数据库名 “RSS_AGG”(参见清单 6)。由于大多数主要关系数据库管理系统(Relational Database Management System,RDBMS)从一开始就支持 PHP,因此在选择数据库时,PHP 具有极大的灵活性。一些 RDBMS 不支持 PHP,但是很多这样的 RDBMS 可以通过抽象类或扩展来提供 PHP 支持。我使用了 MySQL,但是可以任意采用这段代码来支持您选择的数据库。</p>
<p> </p>
<p> 清单 6. feeds 表和两条记录的 SQL<code>CREATE TABLE 'feeds' (<br /> 'id' int(11) NOT NULL auto_increment,<br /> 'url' text NOT NULL,<br /> 'title' text NOT NULL,<br /> 'viewed' tinyint(1) NOT NULL,<br /> PRIMARY KEY ('id')<br />) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;<br />INSERT INTO 'feeds' ('id', 'url', 'title', 'viewed') VALUES<br />(1, 'www.blah.com/story1.html', 'JSON is sweeping AJAX world', 0),<br />(2, 'www.blah.com/story2.html', 'JSON is great', 0);</code></p><p> 我们现在有一个可以通过 PHP 脚本访问的数据库。至于所有数据库交互,我们需要设置数据库连接并提取数据。</p><p> 清单 7. output.php<code><?php<br />$username="username";<br />$password="password";<br />$database="rss_agg";<br />$sql="SELECT * FROM `feeds`";<br />mysql_connect(localhost, $username, $password);<br />mysql_select_db($database) or die("Unable to select database");<br />$result = mysql_query($sql);<br />mysql_close();<br />?></code></p><p> 在输出脚本的开头,我们只是创建变量来存储可以访问位于本地主机的数据库的用户名和密码。我们选择了数据库,命名为 rss_agg,并编写了一条十分简单的 SELECT 语句从 feeds 表中检索所有记录。接下来的三行将使用连接凭证来发起一个与数据库的连接,然后选择数据库。如果出于某种原因这个过程没有发生,我们将看到 “Unable to select database” 结果。最后,我们将检索 SQL 语句的结果并关闭数据库连接。</p>
<p> </p>
<p> 编码为 JSON</p><p> 需要先把 MySQL 结果转换为可用的 PHP 对象,然后才能把 MySQL 结果转换为 JSON 字符串。我们可以通过把它转为一个数组来完成以上操作。</p><p> 清单 8. 带有 JSON 代码的 output.php<code><?php<br />$username="root";<br />$password="";<br />$database="rss_agg";<br />$sql="SELECT * FROM `feeds`";<br />$encodable = array();<br />mysql_connect(localhost, $username, $password);<br />mysql_select_db($database) or die("Unable to select database");<br />$result = mysql_query($sql);<br />while($obj = mysql_fetch_object($result))<br />{<br />$encodable[] = $obj;<br />}<br />$encoded = json_encode($encodable);<br />echo $encoded;<br />mysql_close();<br />?></code></p><p> 我们已经创建了一个数组对象来存储 json_encode() 可以读取和转换为 JSON 字符串格式的结果信息。while 语句将逐个遍历结果查询的每个元素并逐行构建 $encodable 数组。此对象完成后,我们只需通过 json_encode() 运行它并生成 $encoded 对象。现在,可以将此信息回转给浏览器,用来自对象的数据来响应请求的 JavaScript。请求 JavaScript 应用程序现在有一个完全相同的 PHP 对象副本,并使用 JavaScript 天生就能理解的方法列举了该副本。</p><p> 结束语</p><p> JSON 是一种有用的、轻量级协议,现在可用于 PHP V5.2,它可以轻松地实现从 PHP 应用程序中提取出数据,并将其放入 Ajax 应用程序的过程。相应地,PHP 中的 JSON 同样也是轻量级且十分有用的,只包含两个易于使用的函数。使用这些函数,我们可以转换和导出对象结构,还可以使用 json_encode() 使来自 PHP 数据库连接的数据可用于 Ajax 应用程序。在 Ajax 应用程序中处理完数据后,可以将数据返回 PHP 脚本并用 json_decode() 重新创建可用的对象数据结构。当把数据返回到 PHP 后,我们可以将其存储到数据库中,或使用 PHP 提供的众多选择中的任何其他数据处理方法。</p>