PHPずFlexを䜿甚したアプリケヌションの構築

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であなたに合ったオヌプン゜ヌスプロゞェクトを探しおください。

Source: https://habr.com/ru/post/J31595/


All Articles