php[architect] logo

Want to check out an issue? Sign up to receive a special offer.

Mobile Dashboards Made Easy – Part 1

Posted by on September 1, 2011

Editor’s note: you can download the code for this article series here.

One thing that I’ve learned over the years is that smart people like to measure things. It’s impossible to understand how well anything works unless you have some way of understanding its effects in a quantitative way.

Here at php|architect, we are fortunate enough that the vast majority of our business runs almost entirely on the Internet, which means that all our information—from customer data to sales records—is safely stored in a single location.

Internally, our system is composed essentially of three different layers: a PHP-powered back end that encapsulates all our business logic, and then one or more front ends that provide interfaces to the various users. There is also a data layer, sitting at the far back, where our models are stored.

Setting the system up this way was, by far, one of the best decisions that we ever made. Our layers are physically separate, making it easier for us to contain the business logic neatly in a single place.

APIs Make Things Easier

Compared with building a website and then attaching an API to it as an afterthought, this enables us to easily create an arbitrary number of interfaces specialized for a variety of purposes. These include, obviously, our main website, but also a number of other subsystems that are not normally visible to the public.

For example, one of the subsystems, called Orion, is used by our staff to manage just about every aspect of site operations – like customer support, sales management, store maintenance, magazine publication, and so on and so forth.

In addition to being a bunch of highly opinionated hackers, we are also very peculiar about our work environments. Blue Parabola (BP) is a highly distributed company, with offices in four different cities across North America. Our staff uses the entire gamut of desktop operating systems, and because I find working in a web browser a less-than-elegant solution, we have always run our entire business using native applications.

Naturally, it would be prohibitively expensive to write and maintain a different app for each platform that we have to support (or to force everyone onto the same platform). As a result, we have written most of our internal applications using the Flex and Flash platforms that Adobe produces.

Flash, Seriously

When I tell people that we do this, I am usually met with puzzlement (and sometimes, with outright hostility), likely because Flash has gotten so much bad press in the past few years.

The problem, of course, is that even though the same Flash powers both all those ads in your browser and our management system, the results are quite different. Used on the desktop, Flash is a powerful and convenient way of building fully-functional applications that combine the convenience of a native environment with the ease of development associated with Internet technologies.

For the longest time, I’ve wanted to give our readers a glimpse into the way our system is built to show them what Flash can do if put to good use and how beneficial writing a system from the API up can be.

Unfortunately, our code is too complex to use as a simple example, and so I’ve been trying to think of a simpler project that could allow me to show the benefits of our setup.

Over the past couple of months, Cal and I had been actively bemoaning the fact that more and more of our daily lives are spent on a mobile device, and yet our backend didn’t really have any mobile capabilities.

As a result, we decided to write our own mobile dashboard.  Since the latest version of Flash supports mobile platforms and we use different devices (iPhone, iPad, and Android), we decided to use Flash Builder.

This, therefore, is the first of a three-part series in which Cal and I will show you how our mobile dashboard works. The principles are fairly simple, and we even built a little Zend Framework-based backend that feeds dummy data you can use to follow along (because even we are not quite so crazy as to share our actual sales number).

Getting Started

The goals of this project are fairly simple: pull up a breakdown of sales by product, category, and country for today, this week, and this month. To make things a little more visually interesting—always a good thing on mobile platforms—we have tweaked the app’s layout so that the numbers are shown as a scrollable table view when a device is oriented in landscape mode and as a pie chart when in vertical mode.

We’ll use Flash Builder for PHP to create a mobile app that can be compiled to run on iOS, Android and RIM’s Playbook without any changes, adapting automatically to the resolution of each target device. If you’ve never tried Flash Builder, you can grab a free trial from Adobe’s site.

In this first article, I will discuss the basic setup of the system, starting from the backend, where we assume that the retrieval of the data will go through a two-step process.

First, we’ll need to log in as an administrator on the system—this seems like an important step, considering that we’ll be dealing with highly sensitive data. Once the setup is complete, we can pull data remotely from the server by calling a method that returns a list of purchases for a given time period, optionally restricted based on country, category or SKU.

The actual interface to the backend is not entirely relevant at this point, since each backend will have a different API. In general, however, Flash Builder provides two methods for connecting to an external source.

The first is to use one of the IDE’s data connection wizards, which creates a proxy class in ActionScript with an interface that naturally matches the one offered by the remote system. The wizards are quite easy to use and work rather well, in my experience, but there are some cases where unusual interfaces require a more hands-on approach.

In Flex, this takes the form of HTTPService, which can be used to instantiate an HTTP call to a remote system.

Like most of Flex’s infrastructure, HTTPService works in a completely asynchronous way: once instantiated and asked to load a remote resource, it will work quietly in the background until either data becomes available or an error occurs. At that point, HTTPService will fire one of two events, advising the rest of the application that it’s time to take action.

HTTP Connections in Practice

From a practical perspective, connecting to a remote data source using HTTPService is a three-step process. First, you instantiate and populate an object instance with the appropriate information:

var localHttpService:HTTPService = new HTTPService();

localHttpService.url = "http://example.org/script.php";
localHttpService.method = "POST";

As you can see, the code simply instantiates HTTPService, then sets the URL and HTTP method of the request. Next, we need to set up callback closures that can be called when either a response is successfully received, or when an error occurs:

localHttpService.addEventListener(ResultEvent.RESULT, function(e:ResultEvent):void {
   // Do something
   trace(e.target.lastResult);
});

localHttpService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void {
   // Handle error
});

The lastResult property of our HTTPService instance (which is the target of the ResultEvent) contains the text data returned by the remote server.

Detour: Handling JSON Information

In principle, HTTPService can also manipulate XML data, which ActionScript supports natively; however, I think it’s most likely that, these days, developers will have to contend with data encoded using JSON, which is a much more popular format.

Interestingly, the current AIR runtime doesn’t support JSON natively, which is a little odd if you consider ActionScript’s pedigree. Adobe is adding native JSON support to the next version of the runtime, but that won’t help you here; luckily, Flash Builder comes with a set of JSON serializers that can be used without having to resort to external libraries.

On my setup, making use of this serializer requires first adding two SWC files to the app’s build path. They are called serializers.swc and serializers_rb.swc, located in the eclipse/plugins/com.adobe.flexbuilder.project_4.5.1.313231/dcradSwcs/4.5/ folder of your Flash Builder installation.

Once these are linked into your application, you will be able to use the com.adobe.serializers.json.* packages to encode and decode JSON data:

import com.adobe.serializers.json.JSONDecoder;
import com.adobe.serializers.json.JSONEncoder;

...

// To encode:

var encoder:JSONEncoder = new JSONEncoder;
encode.encode(sourceData);

// To decode:

var decoder:JSONDecoder = new JSONDecoder;
var result:Object = decoder.decode(jsonData);

Receiving and Aggregating Data

Now that everything is set up, we can ask our HTTPService instance to reach out to the server and retrieve the appropriate information:

localHttpService.send({"data" : requestData});

As you can see, the send() method takes an object that contains a set of name/value pairs. These, in turn, are passed to the remote script either as query parameters (in the case of a GET operation) or as part of the HTTP request’s payload (in the case of a POST operation).

When data is returned by the server, it’s likely that we’ll need to manipulate it in some way—for example, we may want to aggregate it based on the category of the product. Assuming that the result is JSON-encoded and contains an array of these values:

  • sku: the SKU (unique identifier) of the product
  • productName: the name of each product
  • quantity: the quantity of products sold
  • price: the individual sales price of each product

We could aggregate the results using a simple loop:

for each (var result:ObjectProxy in resultCollection) {
	var bin:Object = skuResults[result.sku];

	if (!bin) {
		bin = {
			name		: result.productName,
			itemCount 	: 0,
			total		: 0
		};

			skuResults[result.sku] = bin;
	}

	bin.itemCount += Number(result.quantity);
	bin.total += Number(result.price) * Number(result.quantity);

	// Generate the final output

	var skuArray:Array = new Array();

	var formatter:CurrencyFormatter = new CurrencyFormatter();

	formatter.useCurrencySymbol = true;

	for each (entry in skuResults) {
		entry.description = "Sales: " + entry.itemCount +
		" — Revenue: " + formatter.format(entry.total); 

		skuArray.push(entry);
	}

	_resultsBySKU = new ArrayCollection(
		skuArray.sortOn("total", Array.DESCENDING | Array.NUMERIC));

The final line of this listing uses sortOn(), one of my favorite array manipulation functions in ActionScript, to sort the result sets by total revenues in descending order.

That’s All for Now…

The mechanics of pulling data from an external resource are not quite that complex—which allows us to focus on the actual functionality provided by our application.

In the next installment of this series, I will show you how to build the UI of the app, taking advantage of several mobile features provided by Flash that provide a rich feature set without having to deal with the intricacies of multiple platforms.


Marco is the keeper of keys and Chief Garbage Collector at Blue Parabola. He can be found on Twitter as @mtabini.
 

Responses and Pingbacks

[…] the first installment of this article, I showed how a Flex-based front end can easily connect to a PHP backend; this is particularly true […]

[…] three of a four-part series on building mobile dashboards with Flash and PHP. You can still read Part One and Part Two on php|architect’s […]

Leave a comment

Use the form below to leave a comment: