内容


DB2 和开放源代码,第 1 部分

在 Linux 上使用 Google Maps API、DB2/Informix 和 PHP 创建地图

一副图片能够表达 1000 多个单词所描述的意思,您需要的只是一个 Web 浏览器

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: DB2 和开放源代码,第 1 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:DB2 和开放源代码,第 1 部分

敬请期待该系列的后续内容。

创建地图

当前的信息爆炸已经促使许多新技术产生了,以帮助消化所有这些上千兆字节的数据。当要尽力吸收太多的信息时,多数人们对图形方式表示的数据处理得很好。地理数据(在本例中是来自 US Census)能够借助于 Google Maps 代替传统的地理信息系统(GIS)而被可视化地表示出来。 搜索 “google maps” 时,会出现 6900 万多条搜索记录,为什么还要使用这篇文章呢?这篇文章专注于使用 PHP、Informix、DB2 和 Linux。此外,这里提供的代码很清晰,是由年仅 14 岁的程序员提供的。(请参阅 “参考资料”,获得更多由该作者撰写的文章。)

文章中的示例基于人口普查的数据。搜索屏幕提供了一个表单用以输入邮政编码。结果页面显示了所选择的邮政编码以及相邻邮政编码地区的人口密度,这个相邻邮政编码带有有颜色的 “push pins”。通过左键单击、拖动鼠标动作可以移动地图,通过地图左上角的缩放控件能够改变地图的比例。

清单 1 显示了进行一些清理和数据清除之后的一些示例。数据库模式显示在 清单 2 中。

清单 1. 示例数据
state         AL
zip           35004
longitude     -86.502492000000
latitude      33.6063790000000
population    6998
housingunits  2815
sqmeters      49387881
state         ME
zip           03901
longitude     -70.845590000000
latitude      43.2901600000000
population    6338
housingunits  2406
sqmeters      96091016
state         WA
zip           98001
longitude     -122.26608100000
latitude      47.3037220000000
population    25771
housingunits  9158
sqmeters      46475168
清单 2. 数据库模式
Column name          Type                                    
state                char(2)   
zip                  char(5)  
longitude            decimal(16) 
latitude             decimal(16)
population           integer   
housingunits         integer  
sqmeters             int8

图 1 展示了搜索页,它是用户碰到的第一个页面。

图 1. 首先加载的页面
首先加载的页面
首先加载的页面

用户输入一个邮政编码,就会显示出结果,如 图 2 所示。这副地图上,不同的人口密度具有不同的有色指示符。右边显示的文本表示地图上显示的邮政编码。左上角的缩放控件能够改变地图的比例。信息窗口显示了 02222 邮政编码的详细信息。

图 2.针对邮政编码 02222 的搜索结果页面
搜索后的页面
搜索后的页面

架构概述

因此,您如何根据搜索条件从数据库表中得到结果记录,并得到图 1 和图 2 那样的显示屏幕呢? 数据源和 Google Map API 结合在一起被称做一个 “mashup”(Wikipedia.org) 或者 Web 应用程序的混合。图 3 展示了服务器架构。

这里真正有趣的概念就是不同数据源在浏览器上的集成。在客户浏览器上能承载的数据大小的限制对于这种方法的成功至关重要。一旦客户很想得到大量的数据,网络限制和客户处理器的速度就会很大地挫伤用户的积极性。

图 3. 带注释的地图架构
架构
架构

此架构非常简单。来自浏览器的请求传向 Apache Web 服务器。请求的 PHP 页面包括 HTML 和 JavaScript。JavaScript 调用 Google Map 服务器后,组合的页面就会出现(如 图 1 所显示)。当向搜索字段输入某一个邮政编码后,一个请求就传向一个使用 PHP ODBC 与后台 Informix 数据库连接的 Web 服务器。

本文中的代码示例说明了如何使用 Informix 数据库。请参阅 “DB2 和 开放源代码:用 DB2、PHP 和 Linux 实现 Web 投票”(developerWorks,2004 年 8 月),了解知如何配置 DB2 与 PHP 一起工作。

页面需要的数据从数据库中检索出来。push pin 颜色方案基于色谱显示人口密度。选择人口范围以便得到每个地区近似的人口数量。

请参阅有关本文中所提供的代码和代码中的注释的讨论,获得有关架构如何工作的额外信息。

组件

Ajax/JavaScript 和 Google API

Google API、JavaScript 和 Ajax 构成了大部分应用程序。Google Maps API 需要一个特定于某个 Web 站点的某个目录的密钥。为了得到一个密钥,您必须登录 www.google.com/apis/maps 并单击 “Sign up for a Google Maps API key”。这个 API 引入了许多有用的功能,其中包括 Ajax HttpRequest 类和事件处理程序控件。Google 为 api 提供了很好的文档,这些文档能够在 www.google.com/apis/maps/documentation/ 上找到。Ajax 仅仅是对 JavaScript 和 XML 组合的富有想像力的缩写词。通过调用 Ajax,解析由 PHP 返回的 HTML,正如您将在下面要看到的,您就不必刷新用户浏览器了。

尽管并非所有的浏览器都会支持 JavaScript 和 Google API,但是,绝大多数都会支持,包括 Mozilla Firefox 和 Internet Explorer 6。此外,一些老的浏览器可能不会支持当前使用的一些 CSS。

Apache、PHP 和 ODBC

中间层服务器提供 Web 页面、运行时环境和数据库访问。Apache 服务器比较有名,根据最新统计数字,有 70% 的 Internet 站点选用 Apache 服务器。Apache 支持插件模块,我们的服务器也使用 mod_php 来提供 PHP 运行时环境。您能够通过在命令行中使用 php 命令来执行 php 脚本的一些简单测试。当 php 代码需要执行并被发送到请求浏览器时,就有了 Apache 和 mod_php 的用武之地。

数据库访问组件 ODBC 已经遭受到性能上的尴尬。早期发布的 ODBC 比较慢。现在的实现已经大大改善,提供了较好的性能。使用 ODBC 使系统间的可移植性得到大大提高。有许多库文件能够支持对 DB2 或 Informix 的本地访问,而这是特定于数据库客户机 API 的。

Informix/DB2

从 IBM Web 站点:

  • DB2 家族:数据库管理系统,能够提供灵活并且有成本效益的数据库平台,以构建健壮的随需应变的业务应用程序。
  • Informix 家族:针对事务集中的环境提供高级应用程序性能。

(我使用 Informix 已经多年了,我可以证明它在数据仓库/决策支持系统方面做得很好。)

文章 “DB2 和 开放源代码:用 DB2、PHP 和 Linux 进行 Web 投票” 从 DB2 引用了大量的示例,所以,这里是来自 Informix 的示例。如果您在用 DB2 完成这个示例时有任何困难,请参考由该作者所写的其他文章(参阅 “参考资料”)。

代码

我们的代码包含 3 个页面:

  1. 主页面,附带有地图,用 HTML/JavaScript 编写而成。
  2. 一个 PHP 脚本,返回以 XML 语言表示的邮政编码的经度/纬度。
  3. 另一个 PHP 脚本,返回以 XML 语言表示的地图边界内关于邮政编码的数据。

我们首先来看用户还从来没有见过的两个组件,这两个组件是 PHP 脚本,由 JavaScript 调用,与数据库交互,并返回 XML:

清单 3. PHP 代码,取得给定邮政编码的经度/纬度
<?php
header("Content-Type: text/xml");
echo"<?xml version=\"1.0\"?>";
$newloc=$_GET[location];
//connect to db2/informix database
        //connect vars
        $dbname="census";
        $username="informix";
        $password="useyourown";
        // odbc_pconnect returns 0 if the connection attempt fails
        // otherwise it returns a connection ID used by other ODBC functions
//                echo ( "attempt connect.....\n " );
        $conn = odbc_pconnect ( $dbname, $username, $password );
        if ( $conn == 0 ) {
                echo ( "Connection to database failed." );
                //If connection failed, show what the error message was:
                $sqlerror = odbc_errormsg ( $conn );
                die($sqlerror);
        }
        $sql = "select longitude,latitude,zip from census_data where zip = '$newloc'";
        $locResult=odbc_exec($conn,$sql);
        $locData=odbc_fetch_object($locResult);
        echo "\n<Results>";
        if($locData->latitude !=""){
        echo "\n\t<Zip>";
        echo "\n\t\t<Latitude>$locData->latitude</Latitude>";
        echo "\n\t\t<Longitude>$locData->longitude</Longitude>";
        echo "\n\t</Zip>";}
        echo "\n</Results>";
?>

您也许注意到到了,这段代码连接到一个名为 census 的 ODBC 数据源。该系统是使用 Informix 和 unixODBC 配置的。有关如何设置系统的一个较好的教程能够在 unixODBC Web 站点上找到(请参阅 “参考资料”)。但是,这个脚本能够很容易地转换成 DB2。“Connecting PHP applications to IBM DB2 Universal Database”(developerWorks,2001 年 7 月)讨论了如何设置 DB2 与 PHP 交互。

清单 3 中的代码的输出将会返回一段格式优美的 XML 源代码,这段代码在 Zip 标记中有 LatitudeLongitude 标记,这些标记都在 Results 标记中。它会根据 URL 中的值搜索数据库。如果没有找到任何结果,Results 标记内就不会有 Zip 标记。您还将会在第二段 PHP 脚本中看到更具有实际作用的 Results 标记。

清单 4 是该脚本的示例输出,使用 02222(Boston,MA)作为邮政编码。

清单 4. longitude/latitude 脚本的示例输出
<?xml version="1.0"?>
<Results>
	<Zip>
		<Latitude>42.367797</Latitude>
		<Longitude>-71.062829</Longitude>
	</Zip>
</Results>

这段脚本只会被主页面的 JavaScript 调用一次。因为它以 XML 语言返回正确的标题(由 header() 函数输出),这段 XML 代码能够被内置在 Google Maps API 中的 XML 解析器所解析。(您将会在后面的 清单 6 中看到这些。)

清单 5. PHP 代码,检索关于用户屏幕中的邮政编码的数据
<?php
header("Content-Type: text/xml");
echo"<?xml version=\"1.0\"?>";
//$newloc=$_GET[location];
//connect to db2/informix database
        //connect vars
        $dbname="census";
        $username="informix";
        $password="useyourown";
        //odbc_pconnect returns 0 if the connection attempt fails
        // otherwise it returns a connection ID used by other ODBC functions
//                echo ( "attempt connect.....\n " );
        $conn = odbc_pconnect ( $dbname, $username, $password );
        if ( $conn == 0 ) {
                echo ( "Connection to database failed." );
                //If connection failed, show what the error message was:
                $sqlerror = odbc_errormsg ( $conn );
                die($sqlerror);
        }
        $sql = "select * from census_data where longitude > '$_POST[left]' 
		and longitude < '$_POST[right]' 
		and latitude > '$_POST[bottom]' 
		and latitude <'$_POST[top]'";
        $locResult=odbc_exec($conn,$sql);
        echo "\n<Results>";
        while($locData=odbc_fetch_object($locResult))
        {
        echo "\n\t<Zip>";
        echo "\n\t\t<Code>$locData->zip</Code>";
        echo "\n\t\t<State>$locData->state</State>";
        echo "\n\t\t<Latitude>$locData->latitude</Latitude>";
        echo "\n\t\t<Longitude>$locData->longitude</Longitude>";
        echo "\n\t\t<Population>$locData->population</Population>";
        echo "\n\t\t<Housing>$locData->housingunits</Housing>";
        echo "\n\t\t<Area>$locData->sqmeters</Area>";
        echo "\n\t</Zip>";
        }
        echo "\n</Results>";
?>

这段脚本返回的 XML 代码大致上基于第一个脚本 —— 它会有个根标记 Results,就像您在第一个脚本中看到的一样。但是这段脚本通常会返回多个 Zip 标记。对于由该数据源返回的每行数据,while 循环将会在该行做为一个对象被调用,并且输出一个所有数据都在数据库中的 Zip 标记(请参阅 清单 1)。

这段代码最重要的部分就是 SQL 查询 —— 在 清单 6中,Ajax 将会切换为 POST,而不是 GET(正如在 清单 3 中看到的),并且传送 4 个变量:leftrightbottomtop。这些变量以经度/纬度定义为地图可见部分的边界。通过查询数据库,并请求这些精确边界内的邮政编码,您就可以避免使用不必要的带宽,降低服务器的负荷,且也有助于缩短响应时间。

清单 6 中的代码由三个部分组成:

  1. CSS
  2. <div> 标记
  3. JavaScript 和很少的 PHP 代码

第一部分是一个嵌入在 <head> 标记中的级联样式表(css)。其边界由 <style type="text/css"></style> 标记定义。css 定义了将会在 <div> 标记中使用的类,以创建页面的外观。如果没有 css,页面中就不会有颜色,页面的布局看起来就会很松散,页面的组织也很不美观。

主体标记中的下一部分是:构造块 <div> 标记,它用于容纳布局、信息和搜索工具。由于 JavaScript 的工作方式,<div> 标记对于容易更新的页面来说工作得非常好。

最后一部分是最重要的:JavaScript。正如上文所提到的,JavaScript 中包含很少的几个部分:

  • 搜索方法
  • 控制 LOADING.. 符号的方法
  • 解析 XML 并将标记加入地图中的方法
  • 几个创建图标的 PHP for 循环
  • 当搜索按钮被按下或表单被提交时触发的方法

除了所有这些之外,具有最重要功能的方法就是用来解析 XML 的方法。它们创建一个新的 GXmlHttp.create(); 函数,该函数是一个内置在 Google Maps API 中的 HttpRequest 类。这不仅仅是用于更新地图的控制中心,也是大多数 Ajax 应用程序的控制中心。(但是,并非所有的 Ajax 应用程序都使用 Google Maps HttpRequest 类。)

当该请求发送到 PHP 文件,并且收到 XML 之后,代码就会搜寻并寻找所有的 Zip 标记。当找到一个结果,程序就会将一个标记添加到地图里面。程序也必须添加一个事件监听器来处理事件 —— 在本例中是某人单击标记。与 HttpRequest 一样,这个事件监听器函数也内置在 Google Maps API 中。

地图的另一个重要部分是用于监听地图移动的所有方法完成之后初始化的事件监听器。它会查看缩放级别,判断级别是否超过或低于 6 级(为了避免太多的带宽和太慢的响应时间),然后将更新地图和侧栏,或者是告诉用户他/她已经缩小得太多了。

结束语

地理数据显示的可能性只受您的想像力限制。本文的示例基于 US Census 数据。这里展示的架构和方法能够应用于您所选择的任何数据。我们希望您能够发觉本文对您很有用,也希望您愿意根据自己创建 mashups 的经验提出反馈意见。


下载资源


相关主题


评论

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management, Open source, Linux
ArticleID=107265
ArticleTitle=DB2 和开放源代码,第 1 部分: 在 Linux 上使用 Google Maps API、DB2/Informix 和 PHP 创建地图
publish-date=03022006