通过 YQL 和 PHP 构建 Web 应用程序,第 1 部分

使用 PHP 和 YQL 来检索并合并来自多个 Web 服务的数据

雅虎查询语言(Yahoo! Query Language,YQL)为多个第三方 web 服务提供统一接口,允许您通过简单的、类似 SQL 的语法来搜索、添加、更新和删除数据。将 PHP 上强大的 XML 处理工具与 YQL 结合在一起,您就可以更容易地将数据从在线服务快速有效且不经 API 文档页面地添加到 web 应用程序。

Vikram Vaswani, 创始人, Melonfire

Vikram Vaswani 的照片Vikram Vaswani 是 Melonfire 的创始人和 CEO,该公司是一家专门研究开源工具和技术的咨询服务公司。他还著有 PHP Programming SolutionsHow to do Everything with PHP and MySQL 等著作。



2010 年 12 月 20 日

简介

今天,几乎每一个流行的网站都具有开发人员 API,允许 Web 应用程序程序员使用标准框架(如 REST 和 SOAP)访问和操纵数据。例如,Google 为了供人访问 Google 服务(如 Google Buzz、Google Docs 和 Google Calendar)而提供 Google Data API;Twitter 具有允许用户搜索和发布 tweet 的 REST API;Facebook 提供 Graph API 来管理用户配置文件和连接。

常用缩略语

  • API:应用程序接口
  • DOM:文档对象模型
  • ECS:电子商务服务
  • HTML:超文本标记语言
  • ISBN:国际标准书号
  • JSON:JavaScript 对象符号
  • RDBMS:关系数据库管理系统
  • REST:具象状态传输
  • RSS:聚合内容
  • SOAP:简单对象访问协议
  • SQL:结构化查询语言
  • URL:统一资源定位器
  • XML:可扩展标记语言

虽然这些 API 肯定会使您的生活更加精彩并为各种创新应用程序打开大门,但是这里也存在一些挑战。例如,一个关键的实现挑战是在不同站点的 API 之间缺乏统一性。有些网站使用 REST,而其他使用 SOAP;一些使用 Atom 来编码响应数据,而另一些则使用 RSS,还有一些则使用普通的 XML 或 JSON。因此,在您每次决定将新的 Web 服务集成到应用程序时,首先您必须进行相当数量的读取,然后进行相当数量的测试,以便在您开始集成以前全面把握服务 API 的技术性细节。

为解决这个问题,Yahoo! 的开发人员决定发明 Yahoo! 查询语言,其缩写 YQL 更广为人知。YQL 为多个 Web 服务 API 提供统一的、类似 SQL 的接口,这大大简化了集成第三方数据到 Web 应用程序的任务。在这个分为两个部分的文章中,我将向您介绍 YQL,说明如何可以将其与我的常用语言 PHP 组合使用来构建复杂的 Web 应用程序。


了解 YQL

如果您熟悉 SQL,则 YQL 对您来说就看上去很眼熟了。很简单,YQL 对待各个 Web 服务就仿佛它们是数据表一样,允许开发人员制定类似 SQL 的查询以便从其中提取信息。YQL 服务需要解析查询字符串,在远程服务上执行该字符串,并用标准 XML 或 JSON 格式返回结果。查询字符串本身将使用 REST 传递给 YQL 服务,作为一项 GET 请求。

要更好的了解此方法,请考虑一个简单的示例。假设您要搜索所有包含术语 “master chief” 的 Twitter。在一个非 YQL 的环境中,您通常要通过 Twitter Search API 来做这些,通过制定如下的请求:

http://search.twitter.com/search.atom?q=master%20chief&lang=en

反过来,Twitter Search API 发回一个 Atom 结果提要,如 图 1 中所示。

图 1. 来自 Twitter Search API 的搜索结果的 Atom 提要
来自 Twitter Search API “master chief” 搜索结果的 Atom 提要的屏幕截图

使用 YQL,您可以通过 YQL 查询访问 Twitter 数据表,从而简化操作,如下所示:

SELECT * FROM twitter.search WHERE q='master chief'

请注意,这几乎就是一个标准的 SQL 查询:关键词 SELECT 说明这是一个数据检索操作,关键词 FROM 指定数据源,WHERE 子句指定筛选器。在您提交此查询以后,YQL 返回一个标准 XML 或 JSON 文档,包含 Twitter 的查询结果,如 图 2 所示。

图 2. Twitter 数据表上的 YQL 查询结果
Twitter 数据表上 YQL 查询的 XML 结果屏幕截图

现在,跳到几天以前并且假设您决定为您的 Web 应用程序添加更多的数据。具体来说,假设您想使用 Twitter 搜索结果附带的地理编码信息来显示每一个发布源自的地理区域的地图。还假设您想将 Twitter 搜索结果与一系列有关搜索术语 “master chief” 的新闻标题结合在一起。

在一个非 YQL 环境中,在您可以完成此任务以前,您需要花费一些时间来阅读 Yahoo! Maps 和 Google News 的 API 文档。使用 YQL,则非常简单,就是添加一些查询:

SELECT * FROM google.news WHERE q="master chief"

SELECT * FROM maps.map WHERE latitude="XX" AND longitude="YY"

图 3图 4 展示了查询结果的屏幕截图。

图 3. Google News 数据表上的 YQL 查询结果
Google News 数据表上的 YQL 查询结果的屏幕截图
图 4. Yahoo Maps 数据表上的 YQL 查询结果
Yahoo Maps 数据表上的 YQL 查询结果的屏幕截图

34 中的查询结果清晰地表明 YQL 的最大好处就在于为第三方 Web 服务提供一个统一的接口。通过允许您使用通常理解的 SQL 语法查询第三方服务,YQL 可以节省您的时间和精力,并且更易于将来自不同来源的数据集成到一个 Web 应用程序中。选择 XML 或 JSON 作为输出格式的能力也非常有用,给您一定程度的灵活性且允许您使用服务器端编程(例如,PHP Perl)或客户端工具(例如,jQuery 或 mooTools)来访问和操纵结果数据。


使用 YQL 控制台

YQL 入门最简单的方式就是通过 YQL 控制台,一种允许您即时制定并测试 YQL 查询的互动式在线工具。YQL 控制台托管在 Yahoo! Developer Network 上且带有诊断工具、示例查询以及一系列可用的表。

要查看其如何工作,浏览到 YQL 控制台并将如下查询输入其中,以便马上获得一系列流行音乐专辑:

SELECT * FROM music.release.popular

在您提交表单时,查询字符串被作为 URL 编码的查询字符串提交给 YQL 服务。然后,YQL 服务会查找表定义,执行查询并返回结果。图 5 显示了 YQL 控制台中的输出。

图 5. YQL 互动式控制台上的查询输出
YQL 互动式控制台上的查询输出的屏幕截图

通过 PHP 使用 YQL

图 5 所示,YQL 可使用 XML 或 JSON 返回数据。在构建 PHP Web 应用程序时,XML 通常更加方便,因为 PHP 带有可被用于快速解析结果文档的内置 XML 处理扩展(SimpleXML、DOM 或者 XMLReader)。考虑到这一点,清单 1 将试图通过 PHP 和 SimpleXML 执行相同的查询:

清单 1. 通过 SimpleXML 处理 YQL 结果
<?php
// execute query
// get list of 15 most popular music releases
// retrieve result as SimpleXML object
$xml = simplexml_load_file('
  http://query.yahooapis.com/v1/public/yql?q=
  SELECT * FROM music.release.popular
');

// iterate over query result set
echo '<h2>Popular Music</h2>';
$results = $xml->results;
foreach ($results->Release as $r) {
  echo '<p>';
  echo '<a href="' . $r['url'] . '">' . $r['title'] . 
    '</a> (' . $r['releaseYear'] . ') - ';  
  echo '<a href="' . $r->Artist['url'] . '">' . $r->Artist['name'] . 
    '</a> <br/>'; 
  echo 'Current chart position: ' . $r->ItemInfo->ChartPosition['this'] . 
    ' / Last chart position: ' . $r->ItemInfo->ChartPosition['last']; 
  echo '</p>';
}  
?>

清单 1 开始先制定针对 YQL Web 服务的查询,向其传递在前面示例中使用的同一 URL 编码的查询字符串。此请求是通过 simplexml_load_file() 函数实现的,从而确保最终的 XML 文档可被自动解析并转换成 SimpleXML 对象。然后,脚本的其余部分会在 XML 文档的 <results> 节点上迭代,为每一个专辑打印标题、链接、作者以及当前图表位置。

图 6 显示了结果。

图 6. 通过 YQL 检索一系列流行音乐作品
通过 YQL 检索一系列流行音乐作品的屏幕截图

如果您使用 Zend 框架,您还可以使用 Zend_Rest_Client 组件访问 YQL Web 服务。清单 2 对其进行了说明,它产生与 清单 1 等同的输出。

清单 2. 通过 Zend 框架处理 YQL 结果
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');

// execute YQL query
// get list of most popular music releases
try {
  $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
  $client->q('SELECT * FROM music.release.popular');
  $result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
    echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

// iterate over query result set
echo '<h2>Popular Music</h2>';
foreach ($result->Release as $r) {
  echo '<p>';
  echo '<a href="' . $r['url'] . '">' . $r['title'] . 
    '</a> (' . $r['releaseYear'] . ') - ';  
  echo '<a href="' . $r->Artist['url'] . '">' . $r->Artist['name'] . 
    '</a> <br/>'; 
  echo 'Current chart position: ' . $r->ItemInfo->ChartPosition['this'] . 
    ' / Last chart position: ' . $r->ItemInfo->ChartPosition['last']; 
  echo '</p>';
} 
?>

Zend 框架的 Zend_Rest_Client 组件是专门为那些将 PHP 应用程序与基于 REST 的 Web 服务集成在一起的开发人员设计的。通过此客户端,您可以对 REST 服务端点执行 GET、POST、PUT 和 DELETE 响应。REST 响应将作为 Zend_Rest_Client_Response 对象的实例返回,从而更易于访问各个响应属性。

清单 2 首先加载 Zend 类库,然后初始化 Zend_Rest_Client 类的实例。此客户端用于初始化 YQL Web 服务端点的未验证的 GET 请求,如之前在 清单 1 中所做的。然后解析返回的 XML 文件并转换为 Zend_Rest_Client_Response 对象,之后可使用标准 foreach() 循环来处理该对象。请注意在使用 Zend_Rest_Client 对象时,对于 URL 编码的 YQL 查询来说以上操作不是必要的,因为该组件将在内部执行此步骤。


筛选并排序查询结果

与常规 SELECT 查询一样,YQL 允许您通过 WHERE 子句来筛选查询结果,指定所需字段,然后根据一个或更多字段来对结果排序。为了说明,请考虑如下针对一系列与搜索术语 “england” 匹配的 Flickr API 查询:

SELECT * FROM flickr.places WHERE query="england"

图 7 说明了对此查询的 YQL 响应。

图 7. 通过 YQL 从 Flickr 检索 “england” 的搜索结果列表
通过 YQL 从 Flickr 检索 “england” 的搜索结果列表的屏幕截图

清单 3 实际演示了此查询。

清单 3. 使用 WHERE 子句筛选 YQL 结果
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');

// execute YQL query
// get list of Flickr places matching search term
try {
  $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
  $client->q('SELECT * FROM flickr.places WHERE query="england"');
  $result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
    echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

// iterate over query result set
echo '<h2>Search Results</h2>';
echo '<table border=1>';
echo '<tr><th>Name</th><th>Latitude</th><th>
Longitude</th></tr>';
foreach ($result->place as $p) {
  echo '<tr>';
  echo '<td>' . $p . '</td>';  
  echo '<td>' . $p['latitude'] . '</td>';  
  echo '<td>' . $p['longitude'] . '</td>';  
  echo '</tr>';
}  
echo '</table>';
?>

图 8 显示了 清单 3 的格式化输出。

图 8. 通过 YQL 从 Flickr 检索 “england” 的格式化搜索结果列表
通过 YQL 从 Flickr 检索 “england” 的格式化搜索结果列表的屏幕截图

您可以使用 AND 和 OR 运算符添加附加筛选条件。对上一个查询进行修订,通过 timezone 进一步筛选结果:

SELECT * FROM flickr.places WHERE query="england" AND timezone LIKE "%europe%"

您可以将查询的输出仅限制为特定字段。在您只需要 Web 服务返回一小部分数据时,此方法非常有用,它也可以减少响应包的大小。下面是上面示例的一个修订版,它只检索每个记录的纬度、经度和名称:

SELECT latitude, longitude, content FROM flickr.places WHERE query="england"

YQL 也支持各种实用函数,这些函数可用于排序、计数以及消除结果集中的重复项。这些函数通常放在 YQL 查询字符串的后面,且使用管道符 (|) 分开。请看以下查询,它根据纬度对结果排序:

SELECT latitude, longitude, content FROM flickr.places 
  WHERE query="england" | sort (field="latitude")

您也可以应用惟一筛选器来从结果中剥离重复项,指定应该检查的字段:

SELECT * FROM flickr.places 
  WHERE query="england" | unique (field="timezone")

清单 4 将所有这一切放在一起构建了一个互动式查询工具,要求用户输入地名并返回可排序结果列表。

清单 4. 搜索地名
<html>
  <head></head>
  <body>  
    <form method="post" action="<?php echo htmlentities
    ($_SERVER['PHP_SELF']); ?>">
    Search term:
    <input type="text" name="q" />
    Sort results by:
    <select name="s">
      <option value="timezone">Time zone</option>
      <option value="latitude">Latitude</option>
      <option value="longitude">Longitude</option>
    </select>
    <input type="submit" name="submit" value="Search" />    
    </form>
    <?php
    // check if form is submitted
    // perform necessary validation (omitted for brevity)
    if (isset($_POST['submit'])) {
      // set up Zend auto-loader
      // load Zend REST client classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Rest_Client');
      
      // execute YQL query
      // get list of Flickr places matching search term
      // sort by requested field
      try {
        $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
        $client->q(
          'SELECT latitude, longitude, timezone, content FROM flickr.places 
            WHERE query="' . $_POST['q'] .'" | sort(field="' . $_POST['s'] . '")');
        $result = $client->get();
      } catch (Zend_Rest_Client_Exception $e) {
          echo "Client error: " . $e->getResponse();
      } catch (Exception $e) {
          echo "Error: " . $e->getMessage();
      }
      
      // iterate over query result set
      echo '<h2>Search Results</h2>';
      echo '<table border=1>';
      echo '<tr><th>Name</th><th>Timezone</th>
        <th>Latitude</th><th>Longitude</th></tr>';
      foreach ($result->place as $p) {
        echo '<tr>';
        echo '<td>' . $p . '</td>';  
        echo '<td>' . $p['timezone'] . '</td>';  
        echo '<td>' . $p['latitude'] . '</td>';  
        echo '<td>' . $p['longitude'] . '</td>';  
        echo '</tr>';
      } 
      echo '</table>';
    }
    ?>
  </body>
</html>

图 9 展示了运转中的 清单 4

图 9. 地名的互动式搜索和排序筛选器
基于清单 4 中代码的地名的互动式搜索和排序筛选器屏幕截图

有关 YQL 函数的完整列表,请查看 YQL 指南(参见 参考资料 获取链接)。


示例应用程序:按地点的天气预报

现在让我们使用迄今为止您所学到的知识,使用 PHP 构建一个简单的支持 YQL 的应用程序。清单 5 要求用户将他或她的地点输入到一个表单中;然后它通过 weather.bylocation 表连接到 Yahoo! Weather 服务并查询该地点的本地天气预报。请查看 清单 5 中的代码。

清单 5. 按地点检索天气预报
<html>
  <head></head>
  <body>  
    <form method="post" action="<?php echo htmlentities
    ($_SERVER['PHP_SELF']); ?>">
    Enter city name:
    <input type="text" name="city" />
    <input type="submit" name="submit" value="Get forecast" />    
    </form>
    <?php
    // check if form is submitted
    // perform necessary validation (omitted for brevity)
    if (isset($_POST['submit'])) {
      // set up Zend auto-loader
      // load Zend REST client classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Rest_Client');

      // execute YQL query
      // get Yahoo! Weather forecast for selected zip code
      try {
        $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
        $client->env('store://datatables.org/alltableswithkeys');  
        $client->q('SELECT * FROM weather.bylocation 
          WHERE location="' . $_POST['city'] . '"');
        $result = $client->get();
      } catch (Zend_Rest_Client_Exception $e) {
          echo "Client error: " . $e->getResponse();
      } catch (Exception $e) {
          echo "Error: " . $e->getMessage();
      }

      // process and print query results
      $data = $result->results->weather->rss->channel->item;
      echo '<h2>' . $data->title . '</h2>';
      echo $data->pubDate . '<br/>';      
      echo $data->description;
    }
    ?>
  </body>
</html>

在提交包含城市名称的 Web 表单以后,清单 5 使用 Zend_Rest_Client 组件发送 YQL 查询到天气服务。该查询使用 WHERE 子句来筛选 weather.bylocation 表的内容并检索指定邮政编码的天气预报。查询结果被格式化并显示在一个 HTML 页面。图 10 显示了该结果。

图 10. 通过 YQL 检索的城市天气预报
通过 YQL 检索的城市天气预报屏幕截图,显示了 2010 年 7 月 23 日印度孟买的天气预报

还要注意,清单 5 将一个新的变量添加到查询字符串 env。此变量是必要的,因为 weather.bylocation 数据表是所谓的 社区表,由社区进行维护而不是 Yahoo! 本身。因此,YQL 服务不能自动获知这个表定义的位置。Env 变量用于指定表定义文件的位置。在此例中,该位置是 YQL 网站的社区开放数据表,用作所有 YQL 社区表的存储库(参见 参考资料 获取链接)。


使用嵌套 YQL 查询

传统 RDBMS 的最大价值在于,它可以将单独的表联接在一起,从而创建其中所包含数据的不同视图。有关 YQL 最酷的事情之一就是它允许您通过 Web 服务做相同的事情。使用 YQL 查询,可以合并来自多个 Web 服务的数据,呈现新的和有用的第三方数据视图。

此功能的应用可能仅受限于您的创造性,一个简单的示例可以帮助阐明此功能的力量。请看 清单 6,它要求用户输入国家/地区名称,然后查询即将推出的 Web 服务,以便列出该国家/地区即将举办的活动。

清单 6. 按国家/地区搜索活动
<html>
  <head></head>
  <body>  
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
    Search for events in:
    <input type="text" name="country" />
    <input type="submit" name="submit" value="Search" />    
    </form>
    <?php
    // check if form is submitted
    // perform necessary validation (omitted for brevity)
    if (isset($_POST['submit'])) {
      // set up Zend auto-loader
      // load Zend REST client classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Rest_Client');

      // execute YQL query
      // get list of events in requested country
      try {
        $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
        $client->q(
          "SELECT * FROM upcoming.events 
            WHERE country_id IN 
              (SELECT id FROM upcoming.country 
                WHERE name = '" . ucfirst($_POST['country']) . "')");    
        $result = $client->get();
      } catch (Zend_Rest_Client_Exception $e) {
          echo "Client error: " . $e->getResponse();
      } catch (Exception $e) {
          echo "Error: " . $e->getMessage();
      }

      // iterate over query result set
      echo '<h2>Events in ' . ucfirst($_POST['country']) . '</h2>';
      foreach ($result->event as $e) {
        echo '<p>';
        echo '<a href="' . $e['url'] . '">' . $e['name'] . 
          '</a> <br/>';
        echo 'Starts: ' . date('d M Y', strtotime($e['start_date'])). '<br/>'; 
        echo !empty($e['end_date']) ?  'Ends: ' . 
          date('d M Y', strtotime($e['end_date'])) . '<br/>' : '';
        echo 'Location: ' . $e['venue_name'] . '<br/>';
        echo 'Address: ' . 
          sprintf('%s, %s', $e['venue_address'], $e['venue_city']) . '<br/>';
        echo $e['description'] . '<br/>';
        echo '</p>';
      } 
}
?>  
  </body>
</html>

清单 6 使用两个嵌套的 YQL 查询。内部查询访问 “upcoming.country” 数据表以便检索与用户输入的国家/地区字符串相对应的数字 ID。然后此数字 ID 被传递给外部查询,以便检索链接到此国家/地区 ID 的活动清单。

图 11 显示了结果示例。

图 11. 可按国家/地区搜索的即将举办的活动清单
可按国家/地区搜索的即将举办的活动清单屏幕截图,显示了在印度海德拉巴的活动

重要的是要注意在技术上这不是一个联接,而是一个子查询。在撰写本文时,YQL 还不允许您通过公用键(一个联接)来链接表,只允许您在一个查询(一个子查询)内使用另一个查询的结果。


示例应用程序:畅销书清单和价格

可以想见,使用简单的类似 SQL 的语法将来自多个 Web 接口的数据组合起来的能力对于 mashup 开发人员非常有用。因此,让我们来考虑另一个稍微复杂的应用程序:将来自纽约时报 畅销书清单的数据与来自 Amazon.com 数据库的价格信息合并,从而呈现流行图书、价格和其受欢迎程度的复合视图。

构建此应用程序的第一步是要检索纽约时报 畅销书的当前清单。YQL 可以通过其 nyt.bestsellers 表获得此信息,但是您需要一个有效的 API 键以便在此表上运行查询。假设您拥有此键(有关说明如何获得此键的链接,参见 参考消息),您可以使用类似下面的查询来检索 2010 年 7 月 21 日这一周的精装小说畅销书的当前清单:

SELECT * FROM nyt.bestsellers WHERE listname='Hardcover Fiction' 
AND date='2010-07-21' AND apikey='NYT-API-KEY'

图 12 显示了此查询的输出。

图 12. 通过 YQL 检索纽约时报 畅销书清单
通过 YQL 检索纽约时报畅销书清单的屏幕截图

请注意结果中的每一个记录都列出了该书的惟一 ISBN 号。这是应用程序的第二部分的重要信息,它需要查找 Amazon.com 上图书的价格。

从 Amazon.com 提取定价数据乍一看似乎是一个繁重的任务,但实际上,非常简单。通过其 Amazon ECS Web 服务,Amazon.com 对第三方开发人员公开其产品数据库(要获得链接和有关如何获得 API 键的信息,参见 参考资料)。YQL 包括一个 Amazon ECS 的数据表,从而可以通过以下查询检索特定 ISBN 的定价信息:

SELECT DetailPageURL, ItemAttributes, SalesRank, MediumImage FROM amazon.ecs 
WHERE AWSAccessKeyId='AWS-KEY' AND secret='AWS-SECRET-KEY' 
AND ResponseGroup='Medium' AND Operation = 'ItemLookup' 
AND ItemAttributes.Binding = 'Hardcover' AND ItemId = '1400065453'

图 13 显示了此查询的输出。

图 13. 通过 YQL 检索的来自 Amazon.com 的产品数据
通过 YQL 检索的来自 Amazon.com 的产品数据屏幕截图

应该明确的是可更容易地结合前面两个查询来产生所需的信息。清单 7 包含完整的脚本。在尝试以前,请记住您要用您自己的 API 键替换查询中的虚拟 API 键。

清单 7. 检索畅销书清单和价格
<html>
  <head>
    <style type="text/css">
    .item {
      float: left;
      width: 400px;      
      padding:10px;   
    }
    .cover {
      float:left; 
      padding: 5px;
      border: solid 1px black;      
    }
    .data {
      margin-left: 150px;
      font-weight: bolder;  
    }
    </style>
  </head>
  <body>
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');

// execute YQL query
// get list of NYT bestsellers
// retrieve image and price from Amazon.com
try {
  $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
  $client->env('store://datatables.org/alltableswithkeys');  
  $client->q(
    "SELECT DetailPageURL, ItemAttributes, SalesRank, MediumImage FROM amazon.ecs 
      WHERE AWSAccessKeyId='AWS-KEY' 
      AND secret='AWS-SECRET-KEY' 
      AND ResponseGroup='Medium' 
      AND Operation = 'ItemLookup' 
      AND ItemAttributes.Binding = 'Hardcover' 
      AND ItemId IN 
        (SELECT isbns.isbn.isbn10 FROM nyt.bestsellers 
          WHERE apikey='NYT-KEY' 
          AND listname='Hardcover Fiction' 
          AND date='2010-07-20') 
    | unique(field='ItemAttributes.Title')");    
  $result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
    echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

// iterate over query result set
echo '<h2>New York Times - Hardcover Fiction Bestsellers</h2>';
$count = 1;
foreach ($result->results->Item as $r) {
  echo '<div class="item">';
  echo '<img class="cover" src="' . $r->MediumImage->URL . '"/>';
  echo '<div class="data">';
  echo $count . '. ';
  echo '<a href="' . $r->DetailPageURL . '">' . 
    $r->ItemAttributes->Title . '</a>';
  echo ' - '. $r->ItemAttributes->Author . '<br/>';
  echo 'Amazon.com Sales Rank: ' . $r->SalesRank . '<br/>';
  echo 'Amazon.com Price: ' . 
    $r->ItemAttributes->ListPrice->FormattedPrice . '';
  echo '</div></div>';
  $count++;
}  
?>  
  </body>
</html>

清单 7 以 ISBN 键作为公分母组合前面两个查询,以便产生包含图书标题、作者、图像、价格以及销售队伍的复合结果。然后解析并处理此结果以便生成一个 HTML 页面(图 14)。

图 14. 通过 YQL 将畅销书清单与产品数据合并在一起
通过 YQL 将畅销书清单与产品数据合并在一起的屏幕截图

请注意在 清单 7 中,内部查询只专门检索畅销书清单上图书的 ISBN-10 号。因为此信息是树下的几个节点,所以点符号用于说明针对查询解析器的所需节点的确切层次位置。在对外部查询应用惟一筛选器时可使用类似的技术,点符号将用于说明筛选结果所依据的字段。


结束语

正如这些例子所展示的,YQL 对于 Web 应用程序开发人员来说是一个强大的工具:它对不同的 Web 服务提供统一的接口,从而可以使用标准的类似 SQL 的查询机制,可提高开发速度且需要更少的有关目标服务的信息。您可以通过 WHERE 子句筛选 YQL 结果,通过使用子选择来合并或 “混搭” 来自多个服务的数据。将 PHP 及其强大的 XML 处理工具添加进来,您就有了一个即便是最疲惫的 web 开发人员也会喜欢尝试的组合!

本文的示例仅仅触及到冰山的一角。通过 YQL 可以做的不止这些,还包括对结果集分页;从 RSS、Atom、XML 和 HTML 文档中提取数据;使用 CREATE 和 UPDATE 查询添加并修改数据。我将在本文的第二部分介绍更多内容,所以请您一定要尽快回来。

参考资料

学习

  • The YQL 指南:了解更多有关 YQL 的信息并通过类似 SQL 的命令访问 Internet 数据。
  • YQL 控制台:体验 YQL 查询。
  • YDN 论坛 > YQL:参与有关 YQL 开发的讨论。
  • Zend_Rest_Client 库:在可搜索的参考指南中阅读有关 Zend_Rest_Client 库的更多信息。
  • 社区 YQL 表:回顾开放式数据表的完整清单,描述了如何将 YQL 映射到 Internet 的任何 Web 服务或资源上。
  • Twitter 搜索 API:在公开 Twitter 数据 API 官方参考资料中了解更多信息。
  • 纽约时报 API:了解更多有关新闻、信息和数据来源的信息。请求 一个 API 键,然后开始行动。
  • Amazon.com 的 ECS Web 服务:寻找所有您需要的信息以便创建可集成 ECS 及诊断并解决任何问题的 Web 站点或应用程序。请求一个 API 键,然后开始编码。
  • 该作者的更多作品(Vikram Vaswani,developerWorks,2007 年 8 月 — 现在):阅读有关 XML、附加 Google API 和其他技术的文章。
  • developerWorks XML 专区:在 XML 专区获取提高您的专业技能所需的资源。
  • My developerWorks:个性化您的 developerWorks 体验。
  • IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 和相关技术的开发人员。
  • XML 技术库:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书。还可以阅读更多 XML 技巧 相关信息。
  • developerWorks 技术事件网络广播:随时关注这些活动中的技术。
  • developerWorks 播客:收听面向软件开发人员的有趣访谈和讨论。
  • developerWorks 按需演示:包括面向初学者的产品安装和设置演示,以及为经验丰富的开发人员提供的高级功能。

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML, Open source
ArticleID=604105
ArticleTitle=通过 YQL 和 PHP 构建 Web 应用程序,第 1 部分
publish-date=12202010