Introducing
Flex2/ActionScript3 have introduced many changes in the Flash world, but actually the remoting classes we were used to include in our projects dont work anymore, or until Macromedia/Adobe wont release an ActionScript3 remoting package for us.
Anyway Flash remoting AMFPHP will continue to work also in AS3, with little modifications to our code.
The bad thing is for what regards the results objects. Since mx.remoting.RecordSet, which converted in Flash 8 remoting data into recordset objects, now you have to create your own wrappers
1. Create the AMFPHP service class
In this tutorial we will just create a simple flash/amfphp application just to show how things work.
The Flash will display a remote folder explorer using PHP for getting the list of folders and files on the server. Every time you will click on a folder icon flash will ask to amfphp for that folder contents and then will attach them to the expanded folder.
Let's start creating the PHP side of our application. Just a php class which parse a given directory and returns an array of contents. Save this file as "FolderBrowser.php" and place it into your amfphp installation dir under "/services/org/sepy/test" directory.
<?php
DEFINE("ROOT_FOLDER", "C:/Program Files/wamp/www");
DEFINE("EXCLUDE_EXT", "php,phps,inc");
class FolderBrowser
{
function FolderBrowser()
{
$this->methodTable = array(
"getList" => array(
"description" => "Get list of file/folders..",
"access" => "remote",
"return" => "array",
"arguments" => array(
"item" => "folder to scan",
),
)
);
}
/**
* return a list of files and folders
* for a given folder
*/
function getList($item)
{
$rest = array();
if(!$item)
{
$item = ROOT_FOLDER;
} else {
$item = ROOT_FOLDER . "/" . $item;
}
$dir = opendir($item);
if($dir)
{
while($file = readdir($dir))
{
if($file != "." && $file != "..")
{
$info = pathinfo($file);
if($info)
{
if(!in_array($info['extension'], explode(",", EXCLUDE_EXT)))
{
$realpath = realpath($item."/".$file);
array_push($rest, array("name"=>$file, "is_dir"=>is_dir($realpath)));
}
}
}
}
}
return $rest;
}
}
?>
See in large window
the .getList method will return an array of objects, which contain "name" and "is_dir" properties (name is the basename of the file/folder, is_dir just will tell to flash how to threat this item)
2. Create the mxml application
Open your flex builder or just use a plain text editor for creating the mxml application file. Look at the file's code, then we will look deeper at it:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" pageTitle="Flex2 & AMFPHP" creationComplete="init()" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
import mx.managers.CursorManager;
import mx.events.TreeEvent;
private var conn:NetConnection;
[Bindable]
private var treeData:XML;
private var currItem:XML;
/**
* Initialize the connection using NetConnection
* and assign the default dataProvider
* to the Tree component
*/
private function init():void
{
conn = new NetConnection();
conn.objectEncoding = ObjectEncoding.AMF0;
conn.connect("http://alessandro-pc/amfphp/gateway.php");
treeData =
<node label="root" data="" loaded="false">
<node label="" data="" loaded="false" />
</node>;
}
/**
* Responder for all the tree events
*/
private function treeHandler(e:Event):void
{
// if item opening event
if(e.type == TreeEvent.ITEM_OPENING)
{
var evt:TreeEvent = TreeEvent(e);
// save a reference to the current opening item
currItem = XML(evt.item);
// call the remote server method only if
// the current folder has not been already parsed
if(evt.item.@loaded == "false")
{
// create a responder for the remote method
// and assign a result handler and fault handler
var resp:Responder = new Responder(getList_result, onFault);
evt.item.node.@label = "Loading...";
// make a remoting call
conn.call("org.sepy.test.FolderBrowser.getList", resp, String(evt.item.@data));
CursorManager.setBusyCursor()
}
}
}
/**
* getList remote server method responder
*/
private function getList_result(e:*):void
{
CursorManager.removeBusyCursor();
if(e is Array)
{
if(e.length)
{
delete currItem.node[0];
var node:XML;
for each(var item:Object in e)
{
currItem.@loaded = "true";
node = XML("<node label='"+item.name+"' loaded='false' data='"+currItem.@data+"/"+item.name+"'></node>");
if(item.is_dir)
{
node.node = <node label="" data="" loaded="false"></node>
}
currItem.node += node
}
} else {
delete currItem.node[0];
currItem.@loaded = "true";
tree.setItemIcon(currItem, tree.getStyle("folderOpenIcon"), tree.getStyle("folderClosedIcon"));
}
}
setTimeout(tree.validateNow, 100)
}
/**
* Default error handler for remote server calls
*/
private function onFault(e:*):void
{
for each(var s:String in e) trace(s, e[s]);
}
]]>
</mx:Script>
<mx:Panel x="10" y="10" width="617" height="548" layout="absolute" title="Folder Browser..." paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:VBox x="0" y="0" width="100%" height="100%" horizontalAlign="right" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:Text width="100%" height="49" fontSize="12">
<mx:htmlText>
<![CDATA[Browse directories using <u><b><a href='http://www.amfphp.org'>AMFPHP</a></b></u>. Evey time you open a folder leaf amfphp will return the folder contents to flash ]]>
</mx:htmlText>
</mx:Text>
<mx:Tree
width="100%"
height="100%"
id="tree"
labelField="@label"
dataProvider="{treeData}"
itemOpening="treeHandler(event)"
disclosureOpenIcon="@Embed(source='/assets/assets.swf#Tree_disclosureOpenIcon')"
disclosureClosedIcon="@Embed(source='/assets/assets.swf#Tree_disclosureClosedIcon')"
openDuration="0"
></mx:Tree>
</mx:VBox>
</mx:Panel>
</mx:Application>
See in large window
