Building Applications with PHP and Flex

Original author: Jack Herrington
  • Transfer

Creating applications using PHP and Flex.



Let's face it: interactive graphs 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 something that the user could experiment with is very difficult. Or at least it was difficult yesterday. Today, I will show 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 in which data about pageviews and the like for each day will be stored. 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 output something, I will fill the table with test data. To do this, I will run the loader.php script (Listing 2). This script simply connects to the database, deletes all data from the table, and then fills it with random data for a month. So that the graphs do not look randomly, I use a method in which each subsequent number is shifted by a random amount relative to the previous one. In this way, the chart always goes up. Now that the data is generated and stored in the database, I need a way to get it out of there. The first way is through XML using the traffic.php page (Listing 3).

Листинг 2. loader.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 );
}
?>






Листинг 3. traffic.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 receives all the data. Then a DomDocument object is created and the data is added to it.

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

When I run the script from the command line, something like this happens: Fine. Now I have data in XML that I can pass to Flex.

% php Traffic.php

/>
/>
/>
/>
...






Creating an interface on Flex, version 1



Let's be honest: who has the time or the desire to create a library for three-dimensional graphs? So let's use an existing one. I chose for example the Elixir library from ILOG . 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 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 select Library Path, and then click Add SWC to add the Elixir ILOG 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 the project.


Now the Elixir library is connected, and I can write code that will connect to my XML data and display it as a three-dimensional graph. This code is shown in Listing 4. The code begins by invoking the send method of the trafficReq object of the HTTPService component. This service points to the URL of a PHP page that returns data in XML. When the data is received, the onTraffic method is called, which converts the XML into a set of data that is ready for use in the chart object. This object is defined at the bottom of the file.

Листинг 4. traffic.mxml


xmlns:ilog="http://www.ilog.com/2007/ilog/flex" creationComplete="trafficReq.send()">

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 );
}
]]>


mouseUp="onMouseUp(event)" mouseMove="onMouseMove(event)" showDataTips="true">

















I defined 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.

Back to the code. I added several handlers for mouse actions - clicks and moves that change the angle of rotation of the graph. This gives users the opportunity to rotate the chart a bit. You can use these methods to change the viewing angle so that the user can look 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 about 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.

Retrieving Data Using AMF



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

And I also added the TrafficService class to the services folder in AMFPHP. You will see the code for this class in Listing 5. This code is similar to the one that generated the XML, except that I don’t format the data here. I am just returning an array. To test the code, I use a browser that is included in AMFPHP.

Листинг 5. TrafficService.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;
}
}






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 minor changes in the previous examples. They are shown in Listing 6. The HTTPService is replaced by RemoteObject, which refers to the AMFPHP server and defines the method I want to access. And the onTraffic method now simply puts the data received from the server into the dataProvider property of the chart object. When I run this code in Flex Builder, the result remains the same as in the first example. The difference is that the code is now more understandable, and 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.

Листинг 6. Traffic_ro.php


xmlns:ilog="http://www.ilog.com/2007/ilog/flex" creationComplete="trafficRO.getTraffic.send()">

import mx.rpc.events.ResultEvent;

private var trackPt:Point = null;

private function onTraffic() : void {
chart.dataProvider = trafficRO.getTraffic.lastResult;
}
...
]]>

endpoint="http://localhost/amfphp/gateway.php"
source="traffic.TrafficService" destination="traffic.TrafficService"
showBusyCursor="true">



...







Листинг 7. traffic_ro2.php


xmlns:ilog="http://www.ilog.com/2007/ilog/flex" creationComplete="trafficRO.getTraffic.send()"
xmlns:flexlib="flexlib.controls.*">

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] );
}
...
]]>

endpoint="http://localhost/amfphp/gateway.php"
source="traffic.TrafficService" destination="traffic.TrafficService"
showBusyCursor="true">





snapInterval="1" />


...







I added an HSlider object with two sliders at the top of the page. When the sliders move, the onDateRangeChange method is called, which updates the chart and shows only the data between the 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, this 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 a choice of date range


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

Where to go next


The combination of technologies shown 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 its presentation simply magnificent. It is no exaggeration to say that making Elixir look bad is very difficult. If you don’t want to pay for Elixir, pay attention to the built-in graphing tools in Flex, or search Google for any open source projects that suit you.

Also popular now: