“Flex”ing with web services using Zend AMF

PHP has always been my favourite scripting language to develop applications for the web. I have always envied Flash applications! PHP applications, to me, are a fine mixture of PHP + SQL + HTML + CSS + JavaScript. You can always add the fancy TLAs in your applications such as XML, if you want to.

With FLEX, Adobe has opened doors to developers like me, who have been kept apart for years, who are unwilling to commit time to learn the complexities of Flash development.

So, with the popularity of web applications and XML-like languages popping everyday, Adobe introduced (in 2004):

FLEX = Flash + MXML + CSS + ActionScript.

The first unknown in our formula: MXML is XML-based language which resembles HTML + CSS + JavaScript. In a traditional web application, the engine is the browser. Here it is the Flash player.

Our PHP + HTML + CSS + JavaScript codes/files of our application are stored on the web server. But MXML code has no use until it is compiled into SWF files Flash can run. For example, SWF file can be embedded inside a HTML page and sent to the visitor’s browser where Flash player runs it. Java is required by the MXML compiler!?

Straightaway, I remember OpenLaszlo! From 2000 onwards, they had this idea of compiling codes of web developers into Flash applications. Poor guys: because of fundamental marketing flaw and approach of presentation, Adobe is now collecting the fruits instead of them. Sometimes, even the choice of the name of a product has major effects on its lifespan.

Now let’s get hands dirty! I wanted to convert the user interface of my PHP Stock profiler into Flex.

phpShareFlex

For simplicity, I will keep all the files inside a folder on my web server; here is the folder structure of
/phpShareFlex/
|–/flex/
|—-services-config.xml
|—-phpShareFlex.mxml
|—-build.bat
|–/service/
|—-/class.MyShareService.php
|—-/index.php
|–/zf/library/Zend/
|–/tmp/
|–AC_OETags.js
|–phpShareFlex.swf
|–index.php

Since I am a PHP coder, let’s write the code for our service first:
/phpShareFlex/service/class.MyShareService.php

 'FTSE 100', 'data' => '^FTSE');
		$indexes[] = array('label' => 'FTSE 250', 'data' => '^FTMC');
		return $indexes;
	}

	/**
	 * Get options for top combobox
	 * @return array
	 */
	public function getTop(){
		$top = array();
		for($i=1; $i<=10; $i++) $top[] = array('label' => 'Top ' .($i*10), 'data' => ($i*10));
		return $top;
	}

	/**
	 * Get array of share data
	 * @param string $index
	 * @param array $methods_arr 
	 * @param int $top Number of shares
	 * @return array
	 */
	public function getShares($index, $methods_arr, $top=10){
		$shares = array();
		$shares[] = array('code' => 'AAA', 'price' => rand(1,100), 'change' => rand(-10,10), 'volume' => rand(100,1000));
		$shares[] = array('code' => 'BBB', 'price' => rand(1,100), 'change' => rand(-10,10), 'volume' => rand(100,1000));
		$shares[] = array('code' => 'CCC', 'price' => rand(1,100), 'change' => rand(-10,10), 'volume' => rand(100,1000));
		return $shares;
	}
}//end class
?>

Note: phpDoc blocks are required by Zend AMF, and the system does not like the output arrays with string keys, so use integer indexes.

Now, parent page to publish it:
/phpShareFlex/service/index.php

setProduction(FALSE);
$server->setClass( "MyShareService" );

if($myLog!=''){
	$filename = dirname(__FILE__).'/tmp/service.debug.'.date('YmdHis').'.txt';
	file_put_contents($filename, $myLog);
}
$handle = $server->handle();
echo ($handle);
?>

Note: The path of Zend Framework library is required to be able to use the classes. One of the silly tricky points was to get set_include_path right! Sometimes such things take hours to find out! You must have noticed my error logging function because the communication happens in the background and developing and debugging this side might be painful; just check the output files inside /tmp/ folder.

Next is the MXML application to use our PHP Zend AMF service. Let’s define how it can communicate with our service.
/phpShareFlex/flex/services-config.xml



    
        
            
                
                    
                
                
                    *
                
            
        
    
    
        
            
        
    

Note: Destination id will be required by the RemoteObject in our MXML application. The type of channel we used is AMFChannel.
/phpShareFlex/flex/phpShareFlex.mxml







	
	
	



	
		
			
				
					
					
					
					
					
					
					
					
				
			
			
				
					
					
						
						
						
						
					
					
				
			
			
				
					
					
						
						
						
					
					
				
			
		
		
			
		
	


Note: Like in other programming languages, there are various ways of doing the same thing: for example, I tried to stick to writing event handling functions first and then attaching them in object attributes like the click event of a button, rather than doing the job inside the MXML tags. I believe it is easier to understand: separation of code section and user interface section, if you see what I mean ๐Ÿ˜‰

To compile this MXML application code, I have a copy of it and the services-config file on my PC and my Flex SDK is under:
c:\MyApps\FlexSDK\

So, the build.bat file is simply:

C:\MyApps\FlexSDK\bin\mxmlc.exe -services services-config.xml phpShareFlex.mxml

Note: The services switch tells the compiler custom service definitions. Once the phpShareFlex.swf file is created, you can upload it to your web server; mine is under:
www.muratyaman.co.uk/phpShareFlex/phpShareFlex.swf

Now, let’s present this to the world wide web either in a HTML page or PHP page; mine is:
www.muratyaman.co.uk/phpShareFlex/index.php




phpShareFlex










Note: Main issue could be the cross site security issue (errors like “Send failed”) when RemoteObject is calling our Zend AMF service, so stick both on to the same domain/website. The second issue during development is that you have to clear the browser’s cache to see the latest version of your FLEX application.

In order not to increase the complexity of this sample tutorial about Flex and PHP Zend/AMF, I have not included the actual code that gathers the share data from Yahoo Finance, which lets you download a CSV file, given sign of a quote or share with date intervals. I have already done it in phpStockProfiler including more functions to save it locally, converting into arrays and working on the data.

Ideally, I want to improve this application to achieve the following diagram:

flex-app-structure

Main improvement is the processing of external data source (public CSV data from Yahoo Finance) and optimizing data flow by using a database. Next one could be a kind of queuing mechanism for concurrent requests and not to do the same calculations twice, at least for the current day, maybe. Any suggestions are welcome.

Happy coding!