📜 ⬆️ ⬇️

Build Applications with PHP and Flex

Build applications with PHP and Flex.



Let's face it: interactive graphics and control panels have always been difficult to use together in web applications. Of course, there are graphic libraries for PHP, but to get something really good looking and what the user could experiment with is very difficult. Or at least it was difficult yesterday. Today, I will show you how to use a combination of PHP as a backend and Adobe Flex as a frontend that will display an interactive 3D graph.

To get started, I need some data. Therefore, I will create a traffic database, it will have one traffic table, which will store data on page views and the like for each day. The MySQL schema is shown in Listing 1.

1. traffic.sql

DROP TABLE IF EXISTS traffic;

CREATE TABLE traffic (
day DATE,
users INT,
views INT,
pages INT,
xmlpages INT
);

')
There are five fields: date, number of users, number of page views, number of pages processed and number of XML pages. (Naturally, you can use any fields.) Now, in order to display something, I will fill the table with test data. To do this, I will run the loader.php script (Listing 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 );
}
?>


This script simply connects to the database, deletes all data from the table, and then fills it with random data for the month. So that the graphs do not look random, I use this method in which each successive number is shifted by a random value relative to the previous one. Thus, the graph always goes up.

Now that the data has been generated and stored in the database, I need a way to get it from there. The first way is via XML using the traffic.php page (Listing 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();
?>


This page connects to the database using PEAR :: MDB2, and gets all the data. Then a DomDocument object is created, and the data is added to it.

Yes, it may be easier to do without a DomDocument for creating XML. But I prefer to use it, because in this case the code is easier to read and, in addition, I have never had problems with XML encoding.

When I run the script from the command line, something like this happens:

% php Traffic.php
<?xml version="1.0"?>
/>
/>
/>
/>
...




Perfectly. Now I have data in XML that I can pass to Flex.

Creating an interface on Flex, version 1



Let's be honest: who has the time or desire to create a library for three-dimensional graphs? So let's use the existing one. I chose the ILOG Elixir library as an example. This is a commercial product, but it has a trial version, so you can download and experiment with it for free.

Building an application on Flex starts with creating a Flex project in Adobe Flex Builder version 3. Both browser-based projects and those based on Adobe AIR are available — it all depends on where you use them — both will work.

Then, I open the Project Properties dialog and click on the Flex Build Path tab. Here I choose the Library Path, and then click Add SWC to add the ILOG Elixir libraries. There are two of them: main classes and a localization library for English and Japanese. As a result, something like this should appear.



  Figure 1. Adding Elixir libraries to a project. 


Now the Elixir library is connected, and I can write code that will connect to my XML data and display them as a three-dimensional graph. This code is shown in Listing 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>


The code starts with calling the send method of the trafficReq object of the HTTPService component. This service points to a PHP page URL that returns data to XML. When data is received, the onTraffic method is invoked, which converts the XML into a data set that is ready for use in the chart object. This object is defined at the bottom of the file.

I defined the chart as LineChart 3D. Other options are possible: a chart with areas, histograms, pie charts, and many others, both two-dimensional and three-dimensional. There are also tools for creating maps, tree diagrams, Gantt charts, and other graphing methods. The examples that come with Elixir will amaze you.

Let's go back to the code. I added several mouse action handlers — clicks and moves, which change the angle of the graph. This gives users the opportunity to rotate the schedule a bit. You can use these methods to change the viewing angle so that the user can view from above or from the side.

When I run the code in Flex Builder 3, I see something like the following.


Not bad, right? Just think how it will look when you connect real data from your site.

Now, to learn a little more about PHP and Flex, let's simplify data transfer.

Receive data using AMF



Flash has a binary data transfer format called Action Message Format (AMF). It allows applications on Flex and Adobe Flash to send and receive entire objects from a server using calls that are similar to normal method calls. To connect the application with PHP and my test dataset, I downloaded and installed AMFPHP .

And I added the TrafficService class to the services folder in AMFPHP. You will see the code for this class in Listing 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;
}
}


This code is similar to the one that formed the XML, except that here I can not format the data. I just return the array.

To test the code, I use a browser that is included in AMFPHP.

  Figure 3. Viewing the AMF traffic service 


As you can see, you can call the getTraffic () method and return all records from the database as an array of ActionScript objects. Very simple, very fast.

Connect to AMFPHP



Connecting to the AMFPHP traffic service requires a slight change in the previous examples. They are shown in Listing 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 is replaced by RemoteObject, which refers to the AMFPHP server and defines the method I want to contact. And the onTraffic method now simply puts data received from the server into the dataProvider property of the chart object. When I run this code in Flex Builder, the result is the same as in the first example. The difference is that the code is now clearer, and the data transfer is faster and less than using XML. To improve the application a bit, I added a slider that allows the user to view only a specific data set and do it dynamically. The new code is shown in Listing 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>


I added a HSlider object with two sliders to the top of the page. When the sliders move, the onDateRangeChange method is called, which updates the graph and displays only data between two dates.

The HSlider class is in the FlexLib library . FlexLib is a set of Flex classes that enhance and extend the original Flex 3 tools. In this case, it allows you to select a range by moving the sliders with the mouse.

How this code works can be seen in Figure 4.

  Figure 4. Graph with selectable date range 


This figure shows only the data for the last several days. But I can add more data by moving the sliders left or right.

Where to go next


The combination of technologies that showed here - PHP, Flex, ILOG Elixir, AMFPHP and FlexLib - is very powerful. ILOG Elixir, in particular, has an amazing set of visualizations that will complement almost any structured data and make their presentation simply gorgeous. It can be said without exaggeration that making Elixir look bad is very difficult. If you don’t want to pay for Elixir, take a look at the graphing tools built into Flex or search Google for any open source projects that suit you.

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


All Articles