Posted on Thursday 29 March 2007
My fellow flasher Aral Balkan sent me an email today about his new project, SWX. Basically SWX is a way of sending and receiving data from and to PHP that is very similar in principle to, say, amfphp. Instead of using the native NetConnection object, however, SWX relies on loadMovie, and its ability to send and receive data on a remote server. Instead of sending the data as AMF, the data is sent as PHON, which is very similar in essence to JSON. Instead of receive an AMF packet, you receive a swf which contains variables. As much as I love and respect Aral, I must say, I find SWX a bad idea.
Now my first point is that SWX reinvents the wheel, and for no good reason. Let's list out the various ways to do asynchronous data communication in Flash. We have LoadVars, XML, Remoting, JSON, SOAP, XML-RPC, and PHPObject. One solution seems more than enough for this very simple tasks; adding another one to these 7 seems like a complete waste of time. Of course, it wouldn't be if in fact SWX gave some mighty good advantages over all the other solutions. To my knowledge, however, the only positive advantage to using SWX is the ability to use getBytesLoaded and getBytesTotal, which isn't available, in, say, Remoting.
The second point is that this approach, while clever, is a hack at best. If you look at the sample code on the webpage, which I will reprint here:
org.swxformat.PHP.init();
// dataHolder is a movie clip on Stage.
dataHolder.className = "Simple";
dataHolder.method = "echoData";
dataHolder.data = [ 'data', 'to', 'send' ];
dataHolder.loadMovie("http://localhost:8888/swx/trunk/php/swx.php", "POST");
// A very simple check for returned data
function onEnterFrame()
{
debug_txt.text = "Data: " + dataHolder.data;
}
The first thing you'll notice is that dataHolder is a movie clip on Stage. That means that either you must place this empty movie clip on stage manually, or you have to use createEmptyMovieClip first. Of course, if you do the latter, you have to think about depths and whatnot. The second thing you'll notice is that there is an onEnterFrame. I thought the whole reason we dropped the use of onEnterFrame for polling a movie clip is that we had all sorts of crazy issues with that, including the difference between 0 and 4 loaded bytes. There's a reason why MovieClipLoader appeared in Flash 7. To my knowledge, MovieClipLoader doesn't allow you to send POST variables, so using that is a no go. The third point is that the PHON serialization that is used relies on a prototype hack, which I will show here:
// Extend the prototypes of the Object, Array and String
// classes to add automatic PHON serialization functionality.
Object.prototype.toString = function()
{
var str:String = "array(";
for (var i:String in this)
{
str += "'" + i + "' => " + this[i].toString() + ", ";
}
str = str.substr(0, str.length-2);
str += ")";
return str;
}
Array.prototype.toString = function()
{
var str:String = "array(";
var len:Number = this.length;
for (var i = 0; i < len; i++)
{
str += this[i].toString();
if ( i != len-1 ) str += ", ";
}
str += ")";
return str;
}
String.prototype.toString = function()
{
// From JSON.as by Trannie Carter <tranniec@designvox.com>
// http://json.org/json.as
var l:Number = this.length;
var s:String = "'";
for (var i:Number = 0; i < l; i += 1)
{
var c = this.charAt(i);
if (c >= ' ')
{
if (c == '\\' || c == '"' || c == "'")
{
s += '\\';
}
s += c;
}
else
{
switch (c)
{
case '\b':
s += '\\b';
break;
case '\f':
s += '\\f';
break;
case '\n':
s += '\\n';
break;
case '\r':
s += '\\r';
break;
case '\t':
s += '\\t';
break;
default:
c = c.charCodeAt();
s += '\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16);
}
}
}
return s+"'";
}
} // end of if
So we hack toString in Array, Object and even (gasp!) String. I am not even to bother to expand as to the myriad ways in which I think this is a bad approach, but you can imagine the argument. The fourth issue with this hack approach is that it is not going to work in AS3, either in Flex or in Flash 9. For one thing because you can't hack prototype, for another because the AS3 bytecode is different from the AS2 bytecode.
SWX also had the disadvantage of being impossible to debug in Charles or ServiceCapture. Aral did a nice job with his Flex debugger, but why bother when you have native tools in your hands that do the job really really well. I could go on: SWX doesn't have anything for batched calls, or for typed objects, and I can hardly see how it could be put to use on a serious RIA. You might argue that SWX is not meant to be used in RIAs, it's better for smaller projects, but that's why we have LoadVars and XML. Honestly I really don't see the point.
Now I'm not saying that Aral's code is useless. In fact, having a non-native way to write swfs in PHP is great. But I think that as it stands, SWX doesn't do anything Remoting, or SOAP, or XML-RPC, or JSON doesn't already do, and do very well at that. If this were 2001, I'd be jumping in the air in excitement over this new approach. But this is 2007, and we have better, proven, and standardized tools to do asynchronous data exchange in Flash. Again, why reinvent the wheel?


