PHPとFlexを使用してアプリケーションを作成します。
それに直面しましょう:インタラクティブなグラフとコントロールパネルは、Webアプリケーションで一緒に使用することは常に困難でした。 もちろん、PHP用のグラフィカルライブラリもありますが、本当に見栄えの良いものや、ユーザーが実験できるものを得るのは非常に困難です。 または、少なくとも昨日は困難でした。 今日は、PHPをバックエンドとして使用し、Adobe Flexをフロントエンドとして使用して、インタラクティブな3Dグラフを表示する方法を示します。
開始するには、いくつかのデータが必要です。 そのため、トラフィックデータベースを作成します。このデータベースには、毎日のページビューなどに関するデータが格納される1つのトラフィックテーブルがあります。 MySQLスキーマをリスト1に示します。
1. traffic.sql
DROP TABLE IF EXISTS traffic;
CREATE TABLE traffic (
day DATE,
users INT,
views INT,
pages INT,
xmlpages INT
);
5つのフィールドがあります:日付、ユーザー数、ページビュー数、処理されたページ数、およびXMLページ数。 (当然、任意のフィールドを使用できます。)ここで、何かを出力するために、テーブルにテストデータを入力します。 これを行うには、loader.phpスクリプトを実行します(リスト2)。
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 );
}
?>
このスクリプトは、単にデータベースに接続し、テーブルからすべてのデータを削除してから、その月のランダムデータを入力します。 グラフがランダムに表示されないように、後続の各数値が前の数値に対してランダムな量だけシフトされる方法を使用します。 このようにして、チャートは常に上がります。
データが生成されてデータベースに保存されたので、そこからデータを取得する方法が必要です。 最初の方法は、traffic.phpページを使用してXMLを使用することです(リスト3)。
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オブジェクトが作成され、データが追加されます。
はい、DomDocumentなしでXMLを作成する方が簡単かもしれません。 しかし、この場合はコードが読みやすく、さらに、XMLエンコーディングに問題がなかったため、使用することを好みます。
コマンドラインからスクリプトを実行すると、次のようなことが起こります。
% php Traffic.php
<?xml version="1.0"?>
/>
/>
/>
/>
...
素晴らしい。 これで、Flexに渡すことができるXMLのデータができました。
Flexバージョン1でのインターフェイスの作成
正直に言うと、3次元グラフ用のライブラリを作成する時間や意欲があるのは誰ですか? それでは、既存のものを使用しましょう。 たとえば、ILOGのElixirライブラリを選択しました。 これは商用製品ですが、試用版があるため、無料でダウンロードして試用できます。
Flexでのアプリケーションの構築は、Adobe Flex Builderバージョン3でFlexプロジェクトを作成することから始まります。ブラウザープロジェクトとAdobe AIRベースのプロジェクトの両方が利用できます。
次に、[プロジェクトプロパティ]ダイアログを開き、[Flexビルドパス]タブをクリックします。 ここで[ライブラリパス]を選択し、[SWCの追加]をクリックしてElixir ILOGライブラリを追加します。 それらの2つ:メインクラスと英語と日本語のローカライズライブラリ。 その結果、このようなものが表示されるはずです。
図1.プロジェクトへのElixirライブラリーの追加。
これでElixirライブラリが接続され、XMLデータに接続して3次元グラフとして表示するコードを作成できます。 このコードをリスト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>
コードは、HTTPServiceコンポーネントのtrafficReqオブジェクトのsendメソッドを呼び出すことから始まります。 このサービスは、XMLでデータを返すPHPページのURLを指します。 データが受信されると、onTrafficメソッドが呼び出され、XMLがチャートオブジェクトで使用可能なデータセットに変換されます。 このオブジェクトは、ファイルの下部で定義されます。
グラフをLineChart 3Dとして定義しました。 他のオプションも可能です。エリア、ヒストグラム、円グラフなど、2次元と3次元の多くのグラフ。 マップ、ツリー図、ガントチャート、およびその他のグラフ作成方法を作成するためのツールもあります。 Elixirに付属する例はあなたを驚かせるでしょう。
コードに戻ります。 マウスアクションのいくつかのハンドラーを追加しました。クリックと移動は、グラフの回転角度を変更します。 これにより、ユーザーはチャートを少し回転させることができます。 これらの方法を使用して、ユーザーが上または横から見ることができるように視野角を変更できます。
Flex Builder 3でコードを実行すると、次のようなものが表示されます。
悪くないよね? サイトの実際のデータを接続したときの外観を考えてください。
ここで、PHPとFlexについてもう少し学ぶために、データ転送を単純化しましょう。
AMFを使用したデータの取得
Flashには、Action Message Format(AMF)と呼ばれるバイナリデータ転送形式があります。 FlexおよびAdobe Flash上のアプリケーションは、通常のメソッド呼び出しと同様の呼び出しを使用して、サーバーからオブジェクト全体を送受信できます。 アプリケーションをPHPとテストデータセットに接続するために、 AMFPHPをダウンロードしてインストールしました 。
また、AMFPHPのservicesフォルダーにTrafficServiceクラスを追加しました。 リスト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. AMFトラフィックサービスの表示
ご覧のとおり、getTraffic()メソッドを呼び出して、データベースからすべてのレコードをActionScriptオブジェクトの配列として返すことができます。 非常にシンプルで非常に高速です。
AMFPHPに接続する
AMFPHPトラフィックサービスに接続するには、前の例で若干の変更が必要です。 それらをリスト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を使用するよりも高速で少なくなることです。 アプリケーションを少し改善するために、ユーザーが特定のデータセットのみを表示して動的に実行できるようにするスライダーを追加しました。 新しいコードをリスト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>
ページの上部に2つのスライダーを持つHSliderオブジェクトを追加しました。 スライダーが移動すると、onDateRangeChangeメソッドが呼び出され、チャートが更新され、2つの日付の間のデータのみが表示されます。
HSliderクラスはFlexLib ライブラリにあります。 FlexLibは、元のFlex 3ツールを強化および拡張するFlexクラスのセットで、この場合、マウスでスライダーを動かして範囲を選択できます。
このコードの仕組みを図4に示します。
図4.日付範囲を選択したグラフ
この図は、過去数日間のデータのみを示しています。 しかし、スライダーを左右に動かすことで、さらにデータを追加できます。
次に行く場所
ここに示されているテクノロジー(PHP、Flex、ILOG Elixir、AMFPHP、FlexLib)の組み合わせは非常に強力です。 特に、ILOG Elixirには、ほぼすべての構造化データを補完し、プレゼンテーションを単純に素晴らしいものにする素晴らしい視覚化セットがあります。 エリクサーの見栄えを悪くすることは非常に難しいと言っても過言ではありません。 Elixirに支払いたくない場合は、Flexに組み込まれているグラフ作成ツールに注意を払うか、Googleであなたに合ったオープンソースプロジェクトを探してください。