• 【设为首页】
  • 【收藏闪客居】
当前位置:主页>Flex>文章内容
  • 使用 PHP 和 Flex 构建仪表板
  • 来源:CSDN 作者:Jack Herrington 2008-07-10 【


使用 PHP 和 Flex 构建仪表板。xmlns:ilog="http://www.ilog.com/2007/ilog/flex" creationComplete="trafficReq.send()">xmlns:ilog="http://www.ilog.com/2007/ilog/flex" creationComplete="trafficRO.getTraffic.send()">我在这里展示的这些技术组合(PHP、 Flex、ILOG Elixir、AMFPHP 和 FlexLib)是很强大的。

作者 Jack Herrington 

使用 PHP Flex 构建仪表板

面对现实吧:将交互式图表和仪表板一起放在 web 上一向都很困难。当然,我们有一些用于 PHP 的图形数据库,但是要生成美观并且能与用户互动的界面仍然很困难,至少曾经是这样的。今天,我将展示如何一个工具组合为您创建交互式 3D,该组合使用 PHP 作为后端,使用 Adobe Flex 作为前端。现在,我们深入讲解一下这个问题。首先,需要一些数据。因此,我合并了一个叫做 traffic 的简单数据库,其中有一个名为 traffic 的列表,表中列出了页面浏览数以及每天的页面浏览数。清单 1 中列出了简单的 MySQL 构架。

清单 1. traffic.sql
 
DROP TABLE IF EXISTS traffic;
 
CREATE TABLE traffic (
       day DATE,
       users INT,
       views INT,
       pages INT,
       xmlpages INT
);

 

有五个字段:示例日期、登录用户数、页面浏览数、真实页面提供数和 XML 页面数。(我已经将这些字段整理出来:您可以使用任何需要的字段。)现在,为了显示数据,我在表中填充了一些内容。为了做到这一点,我运行了如清单 2 所示的 loader.php 脚本。

清单 2. loader.php
 
<?php
require_once("MDB2.php");
 
$dsn = 'mysql://root@localhost/traffic';
$mdb2 =& MDB2::factory($dsn);
 
$dsth =& $mdb2->prepare( "DELETE FROM traffic" );
$dsth->execute( array( ) );
 
$sth =& $mdb2->prepare( "INSERT INTO traffic VALUE (?,?,?,?,?)" );
 
$users = 100;
$views = 10000;
$pages = 5000;
$xmlpages = 300;
for( $d = 1; $d <= 30; $d++ ) {
       $date = "2008-04-".$d;
       $sth->execute( array( $date, $users, $views, $pages, $xmlpages ) );
       $users += ( rand( 20, 100 ) - 30 );
       $views += ( rand( 200, 1000 ) - 300 );
       $pages += ( rand( 100, 500 ) - 150 );
       $xmlpages += ( rand( 60, 300 ) - 90 );
}
?>

 

此 脚本连接到数据库,删除表中当前的所有数据,随机生成一个月的数据值。为了确保图形不至于看起来跟信噪一样,我使用随机滚动类型,每次数据变化时将使用一 个随机量。并且权重一直上升(我是个乐观派)!现在,有了生成的数据,而且这些数据存在于数据库中,我需要获得数据的方法。我展示的第一种方法通过 XML 实现,该方法将使用清单 3 所示的 raffic.php 页面。

清单 3. traffic.php
 
<?php
require_once("MDB2.php");
 
$dsn = 'mysql://root@localhost/traffic';
$mdb2 =& MDB2::factory($dsn);
 
$dom = new DomDocument();
$dom->formatOutput = true;
 
$root = $dom->createElement( "traffic" );
$dom->appendChild( $root );
 
$sth =& $mdb2->prepare( "SELECT * FROM traffic ORDER BY day" );
$res = $sth->execute( $id );
while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC)) {
       $dn = $dom->createElement( "day" );
       $dn->setAttribute( 'day', $row['day'] );
       $dn->setAttribute( 'users', $row['users'] );
       $dn->setAttribute( 'views', $row['views'] );
       $dn->setAttribute( 'pages', $row['pages'] );
       $dn->setAttribute( 'xmlpages', $row['xmlpages'] );
       $root->appendChild( $dn );
}             
 
header( "Content-type: text/xml" );
echo $dom->saveXML();
?>

 

此页面使用 PEAR::MDB2 模块连接到数据库并提取所有数据。然后,它创建一个 DomDocument 对象,并为其添加数据。也许使用简单的 PHP 文本格式化构建 XML 会简单得多。但是我更喜欢使用 DomDocument 对象,因为这样代码比较易于阅读,并且不会出现 XML 编码问题。在命令行运行这个脚本,如下面所示:

% php Traffic.php
<?xml version="1.0"?>
<traffic>
  <day day="2008-04-01" users="100" views="10000" pages="5000" xmlpages="300"/>
  <day day="2008-04-02" users="97" views="10310" pages="5203" xmlpages="408"/>
  <day day="2008-04-03" users="90" views="10638" pages="5254" xmlpages="453"/>
  <day day="2008-04-04" users="102" views="10932" pages="5271" xmlpages="578"/>
...
</traffic>

很好。现在我有了一个可以连接到 Flex XML 数据源。

构建 Flex 界面,版本 1

坦白地说:谁真的有时间或者有兴趣自己构建一个三维图形库呢?那么,我们使用一个现成的吧。我为此示例选择来自 ILOG Elixir 。这是一个商业产品,但是它有试用版,您可以免费下载使用。要构建 Flex 应用程序,首先要在 Adobe Flex Builder 版本 3 中创建一个 Flex 项目。基于 Web 浏览器的项目,还是基于 Adobe AIR 项目可以被使用,取决于您想使它出现在 web 上,还是出现在桌面上:这两者都可以。接下来,在 Project Properties 对话框中单击 Flex Build Path 选项卡。从中单击 Library Path,然后单击 Add SWC 将引用添加到 ILOG Elixir 库。这里有两个库:英语或日语的基本控制类和本地化库。(您的选择是后者。)结果如图 1 所示。

 1.向项目添加 Elixir 

 

连接到 Elixir 后,可以创建连接到 XML 数据集的 Flex 应用程序代码,并且以三维图形显示。代码如清单 4 所示。

清单 4. traffic.mxml
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
  xmlns:ilog="http://www.ilog.com/2007/ilog/flex" 
creationComplete="trafficReq.send()">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
 
private var trackPt:Point = null;
 
private function onTraffic( event:ResultEvent ) : void {
  var days:Array = [];
  for each( var day:XML in event.result..day ) {
    days.push( { day:day.@day.toString(),
      users:parseInt(day.@users),
      pages:parseInt(day.@pages),
      views:parseInt(day.@views),
      xmlpages:parseInt(day.@xmlpages) } );
  }
  chart.dataProvider = days;
}
private function onMouseUp( event:MouseEvent ) : void { trackPt = null; }
private function onMouseMove( event:MouseEvent ) : void {
  if ( trackPt == null ) return;
  chart.rotationAngle += ( event.localX - trackPt.x );
  trackPt = new Point( event.localX, event.localY );
}
private function onMouseDown( event:MouseEvent ) : void {
  trackPt = new Point( event.localX, event.localY );
}
]]>
</mx:Script>
<mx:HTTPService id="trafficReq" resultFormat="e4x" 
url="http://localhost/traffic/traffic.php" result="onTraffic(event)" />
<ilog:LineChart3D rotationAngle="10" width="100%" height="100%" id="chart" 
mouseDown="onMouseDown(event)"
  mouseUp="onMouseUp(event)" mouseMove="onMouseMove(event)" showDataTips="true">
<ilog:horizontalAxis>
<mx:CategoryAxis categoryField="day" displayName="Day" />
</ilog:horizontalAxis>
<ilog:series>
<ilog:LineSeries3D xField="day" yField="users" displayName="Users" />
<ilog:LineSeries3D xField="day" yField="pages" displayName="Pages" />
<ilog:LineSeries3D xField="day" yField="views" displayName="Views" />
<ilog:LineSeries3D xField="day" yField="xmlpages" displayName="XML Pages" />
</ilog:series>
</ilog:LineChart3D>
<mx:Legend dataProvider="{chart}"/>
</mx:Application>

 

这段代码首先对 trafficReq HTTPService 对象调用 send 方法。该服务指向提供 XML PHP 页面的 URL。返回 XML 时,将调用 onTraffic 方法。此方法将 XML 解析到准备用于文件末尾定义的图表对象的数据集。

我已经将图表定义为 LineChart 3D。有几个不同的选项:area chartscolumn chartsbar chartspie charts 和更多——所有图表都是二维或三维的。还有一些控件可以用于创建映射、树图、Gantt 图和各种形式的图。与 Elixer 下载一起提供的示例将让您大吃一惊。

回到代码上来,我已经添加了一些鼠标事件处理器,以处理图形向下、向上和移动(改变旋转角度)操作。这给用户提供了微微转动的能力。您可以使用那些方法改变视角,使客户可以从上向下观察,也可以直接从侧面观察。

Flex Builder 3 中启用这段代码,如图 2 所示。

 

不错吧?想想看,如果用它查看自己站点的一些真实数据,您将赢得什么。

现在,让我们进一步讨论一下 PHP Flex,简化数据传输。

使用 AMF 获得数据

Flash 的二进制数据传输格式叫做Action Message FormatAMF)。它允许 Flex Adobe Flash 应用程序使用调用(类似于标准方法调用)从服务器上收发整个对象。为了将其连接到 PHP 和虚设的数据集,我下载并安装了 AMFPHP。从中我将 traffic service 类添加到 AMFPHP 安装目录中的 services 目录。该服务的代码如清单 5 所示。

清单 5. TrafficService.php
 
<?php
require_once("MDB2.php");
include_once(AMFPHP_BASE . "shared/util/MethodTable.php");
class TrafficService
{
       function getTraffic()
       {
        $dsn = 'mysql://root@localhost/traffic';
        $mdb2 =& MDB2::factory($dsn);
        $sth =& $mdb2->prepare( "SELECT * FROM traffic ORDER BY day" );
        $res = $sth->execute( $id );
        $days = array();
        while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC)) { $days []= $row; }
        return $days;
       }
}

 

这段代码有些像 XML 示例中的代码,不同的地方在于这里不需要格式化数据。我将数据作为一个数组返回。

为了测试代码,我使用了 AMFPHP 随附的浏览器。如图 3 所示。

 3. 浏览 traffic AMF service

 

正如您所看到的,您可以调用 getTraffic() 方法,并且从数据库中获得所有记录,就像对象的ActionScript 数组一样。很清晰,很快。

连接到 AMFPHP

连接到 AMFPHP traffic service 需要对前面的示例进行几处小修改。如清单 6 所示。

清单 6. Traffic_ro.php
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
  xmlns:ilog="http://www.ilog.com/2007/ilog/flex" 
creationComplete="trafficRO.getTraffic.send()">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
 
private var trackPt:Point = null;
 
private function onTraffic() : void {
  chart.dataProvider = trafficRO.getTraffic.lastResult;
}
...
]]>
</mx:Script>
<mx:RemoteObject id="trafficRO"
  endpoint="http://localhost/amfphp/gateway.php"
  source="traffic.TrafficService" destination="traffic.TrafficService"
  showBusyCursor="true">
<mx:method name="getTraffic" result="onTraffic()" />
</mx:RemoteObject>
<ilog:LineChart3D ...>
...
</ilog:LineChart3D>
<mx:Legend dataProvider="{chart}"/>
</mx:Application>

 

HTTPService 已经使用 RemoteObject 代替。RemoteObject 引用了 AMFPHP 服务器,并定义了我想访问的方法。现在,onTraffic 方法将图表中的 dataProvider 字段设置为从服务器返回的数据中。当我在 Flex Builder 中运行这段代码时,视觉上的结果与最初示例的结果是一样的。不同的是这段代码更加简单,并且这种传输比使用 XML 更快、更小。为了增强 Flex 应用程序的功能,我添加了一个滑块,它只允许用户查看数据的一个子集,并且动态调整视图。新的代码如清单 7 所示。

清单 7. traffic_ro2.php
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
  xmlns:ilog="http://www.ilog.com/2007/ilog/flex" 
creationComplete="trafficRO.getTraffic.send()"
  xmlns:flexlib="flexlib.controls.*">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
 
private var trackPt:Point = null;
private var days:Array = [];
 
private function onTraffic() : void {
  days = trafficRO.getTraffic.lastResult as Array;
  dateRange.minimum = 0;
  dateRange.maximum = days.length;
  dateRange.values[0] = 0;
  dateRange.values[1] = days.length;
  chart.dataProvider = days;
}
private function onDateRangeChange() : void {
  chart.dataProvider = days.slice( dateRange.values[0], dateRange.values[1] );
}
...
]]>
</mx:Script>
<mx:RemoteObject id="trafficRO"
  endpoint="http://localhost/amfphp/gateway.php"
  source="traffic.TrafficService" destination="traffic.TrafficService"
  showBusyCursor="true">
<mx:method name="getTraffic" result="onTraffic()" />
</mx:RemoteObject>
<mx:VBox width="100%" height="100%">
<mx:HBox>
<mx:Label text="Date Range" />
<flexlib:HSlider id="dateRange" thumbCount="2" width="300"
liveDragging="true" change="onDateRangeChange()"
       snapInterval="1" />
</mx:HBox>
<ilog:LineChart3D ...>
...
</ilog:LineChart3D>
</mx:VBox>
<mx:Legend dataProvider="{chart}"/>
</mx:Application>

 

我添加了一个 HSlider 对象,在其顶部显示两个缩略图。发生改变时,它会调用 onDateRangeChange 方法,更新图表,使其只包含用户想看到的数据片段。这个 HSlider 类来自 FlexLib 库。FlexLib 是一个 Flex 类集,它增强并扩展了最初的 Flex 3 控制器的功能。在这种情况下,它允许用户通过单击两个缩略图之间的部分改变范围。

Flex Builder 3 中运行这段代码时,结果如图 4 所示。

 4. 带有日期范围选择器的远程对象图

 

在这种情况下,它只显示最近几天的数据值。但是可以通过调整左缩略图或右缩略图增加到想看到的天数数据值。

未来的方向

我在这里展示的这些技术组合(PHPFlexILOG ElixirAMFPHP FlexLib)是很强大的。尤其是 ILOG Elixir,它拥有一个了不起的可视化集合,几乎可以补充任何类型的结构化数据,并能使其更加美观。Elixir 的表现总是很好。如果您不想购买 Elixir,请查看内置于 Flex 中的图表控制器,或者在 Google 中搜索符合您需求的开源项目。

 

如果您想提出问题,请将问题发送到:jack@jackherrington.com.



上一篇:用FLEX实现屏幕快照及下载   下一篇:Flex 与 Servlet 通讯(上)
  • 用户名:新注册) 密码: 匿名评论
  • 评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规)