The use of PHP and MySQL as a back end for Adobe Flex applications can be a powerful combination for web developers dealing with clients who do not require enterprise-level solutions. Drupal—a modular, PHP-based content management system—can further enhance this marriage of technologies by providing a nearly instant, structured environment for managing data and content. With the introduction of the Services module for Drupal 5.x written by Scott Nelson, Drupal provides an optional integrated API for creating Flex or Flash applications driven by the Drupal framework. In this tutorial, I'll show you a basic operation for such an application: retrieving a node from Drupal.
Note: This tutorial is based on an example by Alexander Crugnola, in the example, Flex with AMFPHP. Please note that Alexander Crugnola's example is not specific to Drupal.
In order to make the most of this article, you need the following software and files:
Before building your application, you'll need to install the Drupal content management system. As of Drupal Version 5.0, the installation process has been vastly simplified. An automated process has been added that installs the Drupal package, including the database. Follow the steps below to perform a base installation:
Create a MySQL or PostgreSQL database for use with your Drupal install:
mysql create database your_db_name
Unpack the Drupal tarball in the HTML document root of your web server or another HTTP-accessible directory:
On Unix: Unpack the archive using the command: tar -zxvf drupal-5.x.tar.gz
On Windows: Unpack the archive using WinZip or WinRAR
Modify permissions on the default settings.php file in your_drupal_install/sites/default/settings.php to allow the install script to modify it:
On Unix: Use the command: chmod 777 your_drupal_install/sites/default/settings.php
On Windows: Use the Windows command CACLS or XACLS, or use the Windows context-sensitive menu Properties (Security tab) to modify the permissions.
Once the installation is complete, the install will direct you to a "Welcome" page. Should you have trouble with your install, see the Drupal Troubleshooting FAQ. For Windows-specific installation guidelines, see Drupal's Windows-specific guidelines page. For further information regarding the installation of Drupal, see the Drupal Installation and configuration page.
Next, install the required Drupal modules, including AMFPHP, which is an RPC stack for PHP that enables Drupal to communicate with Flex.
Enable both the Services and AMFPHP modules within the Drupal administrator's interface at:
http://your_drupal_install/admin/build/modules
For this example, I have disabled the "Use keys" and "Use sessid" options for the Services module. This is done in an effort to present the simplest possible example. To disable these options, do the following:
Once step 2 is complete, test AFMPHP by navigating your browser to http://your_drupal_install/admin/build/services and clicking on the AMFPHP - /services/amfphp link under the "Services" heading.
If AMFPHP is working properly, the output of that URL should look something like the following:
amfphp and this gateway are installed correctly. You may now connect to this gateway from Flash.
Note: If you're reading an old tutorial, it will tell you that you should see a download window instead of this message. This confused people so this is the new behaviour starting from amfphp 1.2.
View the amfphp documentation
AMFPHP is now installed.
Note: For Flex to retrieve a node from your Drupal database, you must first create one. Make sure you create at least one story, page, or other node type to retrieve by clicking the "Create content" link in your Drupal administrator's interface, selecting a node type, and submitting it. Since it is the first node in the system, it will have a node ID of 1. If the node you decide to use has a different ID, adjust the MXML Application code accordingly. You will use this node later in this tutorial.
Use the following steps to create the Flex application.
In this file, you'll want the following code. You will need to specify the <endpoint uri="" to reflect the location of your own installation of the AMFPHP module:
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="amfphp-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<destination id="amfphp">
<channels>
<channel ref="my-amfphp"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://your_drupal_install/services/amfphp" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>
Add a compiler directive for the services-config.xml file you just created by using the following steps:
In the "Additional compiler arguments" text field, you must add a directive that specifies to Flex the location of your services-config.xml file on your machine.
In my case this file is in my default Flex Project location, and my directive looks like the block below. You will add something that starts with "-services":
-locale en_US -services "/Users/your-user-name/Documents/Flex Builder 2/your-project-name/services/services-config.xml".
Note: In my case it was necessary to provide the full path to the file, and this path reflects the Apple file system structure. This may not be necessary in your case. If you are using a different OS, specify the appropriate path.
Add the code for the MXML application file. The code is provided below in bulk and commented, and detailed descriptions are provided afterward:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="430" height="270">
<!-- set up a RemoteObject with which to access the services api -->
<mx:RemoteObject id="node" fault="faultHandler(event)" showBusyCursor="true" source="node" destination="amfphp">
<mx:method name="load" result="resultHandler(event)" />
</mx:RemoteObject>
<mx:Script>
<![CDATA[
//import the required packages and classes
import mx.rpc.remoting.RemoteObject;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
//declare an object to store the data we retrieve
[Bindable]
public var resObject:Object;
//declare an event handler to deal with the result
public function resultHandler(event:ResultEvent):void {
//set the bindable object to the value of the result
resObject = event.result;
//set the value of the TextArea to the title of the loaded node
result_text.text = "Success! The title of your node is: " + event.result.title;
}
//declare an event handler to deal with a potential fault
public function faultHandler (event:FaultEvent):void {
//set the value of the TextArea to the fault in the event of failure
result_text.text = "fault: " + String(event.fault);
}
]]>
</mx:Script>
<!-- note that by naming a RemoteObject the same as the Drupal service, we get a relative mirror of the Services and Drupal api;
"node" - the service
"load" - the method
"node.load" - clear & concise -->
<!-- set up simple ui elements to invoke the service & display the result -->
<mx:Button id="btn" label="Load that node!" click="node.load(1);" width="115" bottom="5" right="15"/>
<mx:TextArea width="400" height="200" id="result_text" horizontalCenter="0" verticalCenter="0"/>
<mx:Label text="Result:" left="15" top="10"/>
</mx:Application>
Here's a quick piece-by-piece analysis of the really important pieces of the MXML application file:
Declare the RemoteObject and method with which you will connect to the node service, which looks like the following code:
<mx:RemoteObject id="node" fault="faultHandler(event)" showBusyCursor="true" source="node" destination="amfphp"> <mx:method name="load" result="resultHandler(event)" /> </mx:RemoteObject>
id attribute of the RemoteObject is local to the Flex project, specific to the RemoteObject, and is not associated with the services-config.xml file.source attribute of the RemoteObject is the node service, identified by its name, "node."destination attribute of the RemoteObject matches the destination ID of the service declared in the services-config.xml file,<mx:method name> is the method of the node service you wish to call. Additional methods would be added in the same fashion.Import the classes and packages you need, which looks like this:
import mx.rpc.remoting.RemoteObject; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent;
Declare the button used to invoke the call to the service, which looks like this:
<mx:Button id="btn" label="Load that node!" click="node.load(1);" y="{result_text.y + result_text.height + 20}" x="{result_text.width - btn.width}"/>
click event uses the ID you gave your RemoteObject to send the request with a node ID of 1. In my case this is a Drupal page with a title of "TestPage." You can change the node ID to any node that you have published in Drupal.Make sure you have saved the changes made to your MXML application file and click Debug in Flex Builder. Once the application has launched, click "Load that node!" and wait for a result. If you have assembled these pieces correctly, you will see output in the TextArea that looks something like the following:
Success! The title of your node is: Your node title
Here are some common problems you might encounter and their probable causes:
Drupal also provides developer-contributed modules that can, among many other things, expand the core permissions functionality. See the Drupal Module pages for a complete categorized listing of contributed modules.
AMFPHP - /services/amfphp link, make sure that you have the AMFPHP version 1.9. beta, not the AMFPHP version 2 beta . The AMFPHP 1.9 Beta contains method calls that enable the Services module to override the default AMFPHP gateway and make services available via Drupal directly. As of the time of this writing, these methods were missing from the AMFPHP Beta 2 package. Check the PHP category of the 5 1/2 blog, maintained by Patrick Mineault for any potential updates to this beta, and keep up to date with official AMFPHP distributions at AMFPHP.org.In this tutorial you've accomplished much more than the simple face value task of retrieving a node from Drupal. Rather, upon completion of this tutorial you've armed yourself with a stable, modular, extensive and entirely cost-free back end with which to build Flex and Flash applications for your clients or business. In conjunction with the power of the Flex SDK, the Flex Builder development environment, and the visualization capabilities of Flex components, you wield an impressive set of tool. For development of rich Internet applications and websites for use in low to medium bandwidth and traffic environments, this developer thinks this combination is just the ticket.
As noted in my conclusion, the possibilities are myriad. For instance, you might leverage Drupal's contributed Flash Video module, Flash Media Server (or ffmpeg) and Flex to create a next-generation video website with the ease of use and the extensibility of Flex components. Or, perhaps you might create a video encoder/decoder for a production environment that could be used by a group of employees, online, concurrently. Drupal's community, networking, and content aggregation/syndication features could be leveraged in conjunction with Flex to create very usable and efficient corporate intranets or management applications. You could develop the next step in social networking websites with new and enticing features that Flex can facilitate at very low cost. The possibilities are exciting.
If you are not already, you take this opportunity to familiarize yourself more with the Drupal framework, node and theme systems, core and contributed modules, and APIs to get a good idea of exactly how powerful and viable this combination of technologies can be. Drupal includes a very solid core group of modules and content-types out of the box, and the list of contributed modules is growing at a pace that is effectively impossible to keep up with. The Drupal community is large, perpetually growing and, largely, very helpful to beginners. The Drupal forums are a great resource for tracking down specific solutions to issues or requesting help with a problem. You might also consider joining Drupal groups that pertain to your specific development needs or interests at groups.drupal.org. Understanding the Services module framework will also be important if you intend to develop your own services for use in your applications. Check out the beginnings of the Services module handbook.
I hope you've found this tutorial to be helpful and inspiring. Happy "Flupaling"!
Justin Girard began his career as a web developer and designer at The @Home Network developing rich interfaces for broadband cable television, prior to which he spent seven years designing for traditional media and skateboarding professionally. He currently lives and works in New York City.