{"id":136,"date":"2009-10-24T22:22:11","date_gmt":"2009-10-24T21:22:11","guid":{"rendered":"http:\/\/muratyaman.co.uk\/wp\/?p=136"},"modified":"2020-04-01T12:14:31","modified_gmt":"2020-04-01T11:14:31","slug":"flexing-with-web-services-using-zend-amf","status":"publish","type":"post","link":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/2009\/10\/flexing-with-web-services-using-zend-amf\/","title":{"rendered":"&#8220;Flex&#8221;ing with web services using Zend AMF"},"content":{"rendered":"<p>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.<\/p>\n<p>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.<\/p>\n<p>So, with the popularity of web applications and XML-like languages popping everyday, Adobe introduced (in 2004):<\/p>\n<p><a href=\"http:\/\/www.adobe.com\/products\/flex\/\">FLEX<\/a> = <a href=\"http:\/\/www.adobe.com\/flashplatform\/\">Flash <\/a>+ <a href=\"http:\/\/en.wikipedia.org\/wiki\/MXML\">MXML<\/a> + CSS + <a href=\"http:\/\/www.adobe.com\/devnet\/actionscript\/\">ActionScript<\/a>.<\/p>\n<p>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.<\/p>\n<p>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&#8217;s browser where Flash player runs it. Java is required by the MXML compiler!?<\/p>\n<p>Straightaway, I remember <a href=\"http:\/\/en.wikipedia.org\/wiki\/OpenLaszlo\">OpenLaszlo<\/a>! 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.<\/p>\n<p>Now let&#8217;s get hands dirty! I wanted to convert the user interface of my PHP Stock profiler into Flex.<\/p>\n<p><a href=\"http:\/\/muratyaman.co.uk\/wp\/wp-content\/uploads\/2009\/10\/phpShareFlex.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/muratyaman.co.uk\/wp\/wp-content\/uploads\/2009\/10\/phpShareFlex-300x200.jpg\" alt=\"phpShareFlex\" title=\"phpShareFlex\" width=\"300\" height=\"200\" class=\"aligncenter size-medium wp-image-142\" srcset=\"https:\/\/www.muratyaman.co.uk\/blog\/wp-content\/uploads\/2009\/10\/phpShareFlex-300x200.jpg 300w, https:\/\/www.muratyaman.co.uk\/blog\/wp-content\/uploads\/2009\/10\/phpShareFlex.jpg 1000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>For simplicity, I will keep all the files inside a folder on my web server; here is the folder structure of<br \/>\n\/phpShareFlex\/<br \/>\n|&#8211;\/flex\/<br \/>\n|&#8212;-services-config.xml<br \/>\n|&#8212;-phpShareFlex.mxml<br \/>\n|&#8212;-build.bat<br \/>\n|&#8211;\/service\/<br \/>\n|&#8212;-\/class.MyShareService.php<br \/>\n|&#8212;-\/index.php<br \/>\n|&#8211;\/zf\/library\/Zend\/<br \/>\n|&#8211;\/tmp\/<br \/>\n|&#8211;AC_OETags.js<br \/>\n|&#8211;phpShareFlex.swf<br \/>\n|&#8211;index.php<\/p>\n<p>Since I am a PHP coder, let&#8217;s write the code for our service first:<br \/>\n<strong>\/phpShareFlex\/service\/class.MyShareService.php<\/strong><\/p>\n<pre lang=\"php\">\r\n<?php\r\n\/**\r\n * Class to provide share services\r\n *\/\r\nclass MyShareService{\r\n\r\n\t\/**\r\n\t * Get options for index combobox\r\n\t * @return array\r\n\t *\/\r\n\tpublic function getIndexes(){\r\n\t\t$indexes = array();\r\n\t\t$indexes[] = array('label' => 'FTSE 100', 'data' => '^FTSE');\r\n\t\t$indexes[] = array('label' => 'FTSE 250', 'data' => '^FTMC');\r\n\t\treturn $indexes;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get options for top combobox\r\n\t * @return array\r\n\t *\/\r\n\tpublic function getTop(){\r\n\t\t$top = array();\r\n\t\tfor($i=1; $i<=10; $i++) $top[] = array('label' => 'Top ' .($i*10), 'data' => ($i*10));\r\n\t\treturn $top;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get array of share data\r\n\t * @param string $index\r\n\t * @param array $methods_arr \r\n\t * @param int $top Number of shares\r\n\t * @return array\r\n\t *\/\r\n\tpublic function getShares($index, $methods_arr, $top=10){\r\n\t\t$shares = array();\r\n\t\t$shares[] = array('code' => 'AAA', 'price' => rand(1,100), 'change' => rand(-10,10), 'volume' => rand(100,1000));\r\n\t\t$shares[] = array('code' => 'BBB', 'price' => rand(1,100), 'change' => rand(-10,10), 'volume' => rand(100,1000));\r\n\t\t$shares[] = array('code' => 'CCC', 'price' => rand(1,100), 'change' => rand(-10,10), 'volume' => rand(100,1000));\r\n\t\treturn $shares;\r\n\t}\r\n}\/\/end class\r\n?>\r\n<\/pre>\n<p><strong>Note:<\/strong> phpDoc blocks are required by Zend AMF, and the system does not like the output arrays with string keys, so use integer indexes.<\/p>\n<p>Now, parent page to publish it:<br \/>\n<strong>\/phpShareFlex\/service\/index.php<\/strong><\/p>\n<pre lang=\"php\">\r\n<?php\r\nerror_reporting(E_ALL);\r\ndate_default_timezone_set('Europe\/London');\r\n$myLog='';\r\nfunction myErrorHandler($errno, $errstr, $errfile, $errline){\r\n\tglobal $myLog;\r\n\t$myLog .= \"Error $errno on line $errline in file $errfile\\n\"\r\n\t\t\t. \"----- $errstr\\n\";\r\n\treturn TRUE;\r\n}\r\n$old_error_handler = set_error_handler(\"myErrorHandler\");\r\n\r\n$paths = array(\r\n    realpath(dirname(__FILE__) . '\/..\/zf\/library'),\r\n    '.'\r\n);\r\nset_include_path(implode(PATH_SEPARATOR, $paths));\r\n\r\nrequire_once \"..\/zf\/library\/Zend\/Loader.php\";\r\nZend_Loader::loadClass('Zend_Amf_Server');\r\n\r\nrequire \"class.MyShareService.php\";\/\/our class to do the job\r\n\r\n$server = new Zend_Amf_Server();\r\n$server->setProduction(FALSE);\r\n$server->setClass( \"MyShareService\" );\r\n\r\nif($myLog!=''){\r\n\t$filename = dirname(__FILE__).'\/tmp\/service.debug.'.date('YmdHis').'.txt';\r\n\tfile_put_contents($filename, $myLog);\r\n}\r\n$handle = $server->handle();\r\necho ($handle);\r\n?>\r\n<\/pre>\n<p><strong>Note:<\/strong> The path of Zend Framework library is required to be able to use the classes. One of the silly tricky points was to get <strong>set_include_path<\/strong> 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.<\/p>\n<p>Next is the MXML application to use our PHP Zend AMF service. Let&#8217;s define how it can communicate with our service.<br \/>\n<strong>\/phpShareFlex\/flex\/services-config.xml<\/strong><\/p>\n<pre lang=\"xml\">\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<services-config>\r\n    <services>\r\n        <service id=\"zend-service\"\r\n            class=\"flex.messaging.services.RemotingService\"\r\n            messageTypes=\"flex.messaging.messages.RemotingMessage\">\r\n            <destination id=\"zend\">\r\n                <channels>\r\n                    <channel ref=\"myZendChannel\"\/>\r\n                <\/channels>\r\n                <properties>\r\n                    <source>*<\/source>\r\n                <\/properties>\r\n            <\/destination>\r\n        <\/service>\r\n    <\/services>\r\n    <channels>\r\n        <channel-definition id=\"myZendChannel\"\r\n            class=\"mx.messaging.channels.AMFChannel\">\r\n            <endpoint uri=\"http:\/\/www.muratyaman.co.uk\/phpShareFlex\/service\/index.php\"\r\n                class=\"flex.messaging.endpoints.AMFEndpoint\"\/>\r\n        <\/channel-definition>\r\n    <\/channels>\r\n<\/services-config>\r\n<\/pre>\n<p><b>Note:<\/b> Destination id will be required by the <a href=\"http:\/\/livedocs.adobe.com\/flex\/3\/html\/help.html?content=data_access_4.html\">RemoteObject <\/a>in our MXML application. The type of channel we used is AMFChannel.<br \/>\n<strong>\/phpShareFlex\/flex\/phpShareFlex.mxml<\/strong><\/p>\n<pre lang=\"mxml\">\r\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<mx:Application xmlns:mx=\"http:\/\/www.adobe.com\/2006\/mxml\"\r\n pageTitle=\"phpShareFlex\" layout=\"absolute\"\r\n creationComplete=\"Application_creationComplete()\"\r\n>\r\n<mx:Script>\r\n<![CDATA[\r\n\r\n\timport mx.collections.ArrayCollection;\r\n\timport mx.collections.SortField;\r\n\timport mx.collections.Sort;\r\n\t\r\n\timport mx.rpc.events.ResultEvent;\r\n\timport mx.rpc.events.FaultEvent;\r\n\r\n\timport mx.utils.ObjectUtil;\r\n\t\r\n\tprivate function logMsg(msg:String):void{\r\n\t\ttxtLog.text += msg;\r\n\t}\r\n\tprivate function svcShareService_getShares_fault( event:FaultEvent ) : void {\r\n\t\tlogMsg('svcShareService_getShares_fault() ' + faultInfo(event) + '\\n');\r\n\t}\r\n\tprivate function Application_creationComplete() : void {\r\n\t\ttry{\r\n\t\t\tlogMsg('BEGIN Application_creationComplete()' + '\\n');\r\n\t\t\tlogMsg('Calling svcShareService.getIndexes()' + '\\n');\r\n\t\t\tsvcShareService.getIndexes();\r\n\t\t\tlogMsg('Calling svcShareService.getTop()' + '\\n');\r\n\t\t\tsvcShareService.getTop();\r\n\t\t\tlogMsg('END Application_creationComplete()' + '\\n');\r\n\t\t}catch(e:Error){\r\n\t\t\tlogMsg('ERROR Application_creationComplete():\\n    ' + e.message + '\\n');\r\n\t\t}\r\n\t}\r\n\tprivate function svcShareService_fault(event:FaultEvent):void{\r\n\t\tlogMsg('svcShareService_fault() ' + faultInfo(event) + '\\n');\r\n\t\ttrace('svcShareService_fault');\r\n\t}\r\n\tprivate function call_svcShareService_getShares() : void {\r\n\t\tlogMsg('BEGIN call_svcShareService_getShares()' + '\\n');\r\n\t\t\r\n\t\tvar myIndex:Object = cboIndexes.selectedItem;\r\n\t\tvar myIndexCode:String = myIndex.data;\r\n\t\t\r\n\t\tvar myTop:Object = cboTop.selectedItem;\r\n\t\tvar myTopNum:Number = myTop.data;\r\n\r\n\t\tvar myMethodsArr:Array;\r\n\t\tmyMethodsArr = new Array();\r\n\t\tif(chkLP.selected) myMethodsArr.push(\"LP\");\r\n\t\tif(chkLL.selected) myMethodsArr.push(\"LL\");\r\n\t\tif(chkLV.selected) myMethodsArr.push(\"LV\");\t\r\n\r\n\t\tlogMsg('Calling svcShareService.getShares()' + '\\n');\r\n\t\tsvcShareService.getShares(myIndexCode, myMethodsArr, myTopNum);\r\n\t\tlogMsg('END call_svcShareService_getShares()' + '\\n');\r\n\t}\r\n\tprivate function svcShareService_getIndexes_result( event:ResultEvent ) : void {\r\n\t\tlogMsg('svcShareService_getIndexes_result()' + '\\n');\r\n\t\tcboIndexes.dataProvider = event.result;\r\n\t}\r\n\tprivate function svcShareService_getIndexes_fault(event:FaultEvent):void {\r\n\t\tlogMsg('svcShareService_getIndexes_fault() ' + faultInfo(event) + '\\n');\r\n\t}\r\n\tprivate function svcShareService_getTop_result( event:ResultEvent ) : void {\r\n\t\tlogMsg('svcShareService_getTop_result()' + '\\n');\r\n\t\tcboTop.dataProvider = event.result;\r\n\t}\r\n\tprivate function svcShareService_getTop_fault(event:FaultEvent):void {\r\n\t\tlogMsg('svcShareService_getTop_fault() ' + faultInfo(event) + '\\n');\r\n\t}\r\n\tprivate function btnGetShares_click(event:Event):void{\r\n\t\tlogMsg('btnGetShares_click()' + '\\n');\r\n\t\tcall_svcShareService_getShares();\r\n\t}\r\n\tprivate function svcShareService_getShares_result( event:ResultEvent ) : void {\r\n\t\tlogMsg('svcShareService_getShares_result()' + '\\n');\r\n\t\tdgShares.dataProvider = event.result;\r\n\t}\r\n\tprivate function faultInfo(event:FaultEvent):String{\r\n\t\tvar s:String = event.fault.faultString + ' Msg: ' + event.fault.message + ' Status: ' + event.statusCode;\r\n\t\treturn s;\r\n\t}\r\n\tprivate function sortNumber(d1:Number, d2:Number):int{\r\n\t\tif(d1 < d2) {\r\n\t\t\treturn -1;\r\n\t\t} else if(d1 == d2) {\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\treturn 1;\r\n\t}\r\n\tprivate function myParseFloat(strNumber:String):Number{\r\n\t\tvar s:String = strNumber;\r\n\t\ts = s.split(\",\").join(\"\");\r\n\t\ts = s.split(\"%\").join(\"\");\r\n\t\tvar f:Number = parseFloat(s);\r\n\t\treturn f;\r\n\t}\r\n\tprivate function sortDate(obj1:Object, obj2:Object):int{\r\n\t\treturn sortNumber( (new Date(Date.parse(obj1.date))).getTime(), (new Date(Date.parse(obj2.date))).getTime());\r\n\t}\r\n\tprivate function sortNumber_price(obj1:Object, obj2:Object):int{\r\n\t\treturn sortNumber( myParseFloat(obj1.price), myParseFloat(obj2.price));\r\n\t}\r\n\tprivate function sortNumber_change(obj1:Object, obj2:Object):int{\r\n\t\treturn sortNumber( myParseFloat(obj1.change), myParseFloat(obj2.change));\r\n\t}\r\n\tprivate function sortNumber_volume(obj1:Object, obj2:Object):int{\r\n\t\treturn sortNumber( myParseFloat(obj1.volume), myParseFloat(obj2.volume));\r\n\t}\r\n\tprivate function shareChart(sign:String):void{\r\n\t\tvar url:String = 'http:\/\/uk.ichart.yahoo.com\/z?s=' + sign + '&#038;t=3m&#038;q=b&#038;l=on&#038;z=m&#038;p=e5,e20&#038;a=ss,vm';\r\n\t\timgShareChart.source = url;\r\n\t}\r\n\tprivate function dgShares_itemClick(event:Event):void{\r\n\t\tlogMsg('dgShares_itemClick()' + '\\n');\r\n\t\tvar code:String = dgShares.selectedItem.code;\r\n\t\tlblShareCode.text = code;\r\n\t\tshareChart(code);\r\n\t}\r\n\tprivate function lnkCompanyInfo_click(event:Event):void{\r\n\t\tlogMsg('lnkCompanyInfo_click()' + '\\n');\r\n\t\tvar url:String = 'http:\/\/uk.finance.yahoo.com\/q\/pr?s=' + lblShareCode.text;\/\/company profile\r\n\t\t\/\/ExternalInterface.call( \"myNewWindow(\"+url+\")\" );\r\n\t}\r\n]]>\r\n<\/mx:Script>\r\n\r\n<mx:RemoteObject id=\"svcShareService\" source=\"MyShareService\" destination=\"zend\" showBusyCursor=\"true\" fault=\"svcShareService_fault(event)\">\r\n\t<mx:method name=\"getIndexes\" result=\"svcShareService_getIndexes_result(event)\" fault=\"svcShareService_getIndexes_fault(event)\" \/>\r\n\t<mx:method name=\"getTop\" result=\"svcShareService_getTop_result(event)\" fault=\"svcShareService_getTop_fault(event)\" \/>\r\n\t<mx:method name=\"getShares\" result=\"svcShareService_getShares_result(event)\" fault=\"svcShareService_getShares_fault(event)\" \/>\r\n<\/mx:RemoteObject>\r\n\r\n<mx:Panel width=\"95%\" height=\"95%\" layout=\"vertical\" title=\"phpShareFlex\"\r\n\thorizontalAlign=\"center\" horizontalCenter=\"0\" verticalCenter=\"0\"\r\n\tpaddingBottom=\"5\" paddingLeft=\"5\" paddingRight=\"5\" paddingTop=\"5\">\r\n\t<mx:VDividedBox width=\"100%\" height=\"100%\">\r\n\t\t<mx:HDividedBox width=\"100%\" height=\"90%\">\r\n\t\t\t<mx:Canvas label=\"Criteria\" width=\"15%\" height=\"100%\">\r\n\t\t\t\t<mx:VBox width=\"100%\" height=\"90%\">\r\n\t\t\t\t\t<mx:ComboBox id=\"cboTop\" \/>\r\n\t\t\t\t\t<mx:Label text=\"shares from\" \/>\r\n\t\t\t\t\t<mx:ComboBox id=\"cboIndexes\" \/>\r\n\t\t\t\t\t<mx:Label text=\"Using\" \/>\r\n\t\t\t\t\t<mx:CheckBox id=\"chkLV\" label=\"Last Volume\" selected=\"true\" \/>\r\n\t\t\t\t\t<mx:CheckBox id=\"chkLP\" label=\"Last Profit %\" selected=\"true\" \/>\r\n\t\t\t\t\t<mx:CheckBox id=\"chkLL\" label=\"Last Loss %\" selected=\"false\" \/>\r\n\t\t\t\t\t<mx:Button id=\"btnGetShares\" label=\"Get Shares\" click=\"btnGetShares_click(event)\" \/>\r\n\t\t\t\t<\/mx:VBox>\r\n\t\t\t<\/mx:Canvas>\r\n\t\t\t<mx:Canvas label=\"Shares\" width=\"55%\" height=\"100%\">\r\n\t\t\t\t<mx:VBox width=\"100%\" height=\"100%\">\r\n\t\t\t\t\t<mx:DataGrid id=\"dgShares\" width=\"100%\" height=\"100%\" itemClick=\"dgShares_itemClick(event)\" >\r\n\t\t\t\t\t<mx:columns>\r\n\t\t\t\t\t\t<mx:DataGridColumn headerText=\"Code\" dataField=\"code\" \/>\r\n\t\t\t\t\t\t<mx:DataGridColumn headerText=\"Price\" dataField=\"price\" sortCompareFunction=\"sortNumber_price\" \/>\r\n\t\t\t\t\t\t<mx:DataGridColumn headerText=\"Change %\" dataField=\"change\" sortCompareFunction=\"sortNumber_change\" \/>\r\n\t\t\t\t\t\t<mx:DataGridColumn headerText=\"Volume\" dataField=\"volume\" sortCompareFunction=\"sortNumber_volume\" \/>\r\n\t\t\t\t\t<\/mx:columns>\r\n\t\t\t\t\t<\/mx:DataGrid>\r\n\t\t\t\t<\/mx:VBox>\r\n\t\t\t<\/mx:Canvas>\r\n\t\t\t<mx:Canvas label=\"Information from Yahoo!\" width=\"30%\" height=\"100%\">\r\n\t\t\t\t<mx:VBox width=\"100%\">\r\n\t\t\t\t\t<mx:Label text=\"Chart of Last 3 Months\" \/>\r\n\t\t\t\t\t<mx:HBox width=\"100%\">\r\n\t\t\t\t\t\t<mx:Label text=\"Selected share:\" \/>\r\n\t\t\t\t\t\t<mx:Label id=\"lblShareCode\" text=\"\" \/>\r\n\t\t\t\t\t\t<mx:LinkButton id=\"lnkCompanyInfo\" label=\"More info\" color=\"#0000FF\" fontWeight=\"bold\" click=\"lnkCompanyInfo_click(event)\"\/>\r\n\t\t\t\t\t<\/mx:HBox>\r\n\t\t\t\t\t<mx:Image id=\"imgShareChart\" width=\"100%\" \/>\r\n\t\t\t\t<\/mx:VBox>\r\n\t\t\t<\/mx:Canvas>\r\n\t\t<\/mx:HDividedBox>\r\n\t\t<mx:VBox width=\"100%\" height=\"10%\">\r\n\t\t\t<mx:TextArea id=\"txtLog\" width=\"100%\" height=\"100%\" text=\"\" \/>\r\n\t\t<\/mx:VBox>\r\n\t<\/mx:VDividedBox>\r\n<\/mx:Panel>\r\n<\/mx:Application>\r\n<\/pre>\n<p><b>Note:<\/b> 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: <em>separation of code section and user interface section<\/em>, if you see what I mean \ud83d\ude09<\/p>\n<p>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:<br \/>\n<strong>c:\\MyApps\\FlexSDK\\<\/strong><\/p>\n<p>So, the <strong>build.bat<\/strong> file is simply:<\/p>\n<pre lang=\"msdos\">\r\nC:\\MyApps\\FlexSDK\\bin\\mxmlc.exe -services services-config.xml phpShareFlex.mxml\r\n<\/pre>\n<p><b>Note:<\/b> The services switch tells the compiler custom service definitions. Once the <strong>phpShareFlex.swf<\/strong> file is created, you can upload it to your web server; mine is under:<br \/>\n<strong>www.muratyaman.co.uk\/phpShareFlex\/phpShareFlex.swf<\/strong><\/p>\n<p>Now, let&#8217;s present this to the world wide web either in a HTML page or PHP page; mine is:<br \/>\nwww.muratyaman.co.uk\/phpShareFlex\/index.php<\/p>\n<pre lang=\"html\">\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text\/html; charset=utf-8\" \/>\r\n<title>phpShareFlex<\/title>\r\n<script src=\"AC_OETags.js\" language=\"javascript\"><\/script>\r\n<script language=\"JavaScript\" type=\"text\/javascript\">\r\n<!--\r\n\t\/\/to be called by flex objects like link buttons\r\n\tfunction myNewWindow(url){\r\n\t\twindow.open(url);\r\n\t\treturn true;\r\n\t}\r\n\/\/ -->\r\n<\/script>\r\n<style>\r\nbody { margin: 0px; overflow:hidden }\r\n<\/style>\r\n<\/head>\r\n\r\n<body scroll='no'>\r\n<script language=\"JavaScript\" type=\"text\/javascript\">\r\n<!--\r\n\tAC_FL_RunContent(\r\n\t\t\t\t\t\"src\", \"phpShareFlex\",\r\n\t\t\t\t\t\"width\", \"100%\",\r\n\t\t\t\t\t\"height\", \"100%\",\r\n\t\t\t\t\t\"align\", \"middle\",\r\n\t\t\t\t\t\"id\", \"phpShareFlex\",\r\n\t\t\t\t\t\"quality\", \"high\",\r\n\t\t\t\t\t\"bgcolor\", \"#869ca7\",\r\n\t\t\t\t\t\"name\", \"phpShareFlex\",\r\n\t\t\t\t\t\"allowScriptAccess\",\"sameDomain\",\r\n\t\t\t\t\t\"type\", \"application\/x-shockwave-flash\",\r\n\t\t\t\t\t\"pluginspage\", \"http:\/\/www.adobe.com\/go\/getflashplayer\"\r\n\t);\r\n\/\/ -->\r\n<\/script>\r\n<noscript>\r\n\t<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\r\n\t\t\tid=\"phpShareFlex\" width=\"100%\" height=\"100%\"\r\n\t\t\tcodebase=\"http:\/\/fpdownload.macromedia.com\/get\/flashplayer\/current\/swflash.cab\">\r\n\t\t\t<param name=\"movie\" value=\"phpShareFlex.swf\" \/>\r\n\t\t\t<param name=\"quality\" value=\"high\" \/>\r\n\t\t\t<param name=\"bgcolor\" value=\"#869ca7\" \/>\r\n\t\t\t<param name=\"allowScriptAccess\" value=\"sameDomain\" \/>\r\n\t\t\t<embed src=\"phpShareFlex.swf\" quality=\"high\" bgcolor=\"#869ca7\"\r\n\t\t\t\twidth=\"100%\" height=\"100%\" name=\"phpShareFlex\" align=\"middle\"\r\n\t\t\t\tplay=\"true\"\r\n\t\t\t\tloop=\"false\"\r\n\t\t\t\tquality=\"high\"\r\n\t\t\t\tallowScriptAccess=\"sameDomain\"\r\n\t\t\t\ttype=\"application\/x-shockwave-flash\"\r\n\t\t\t\tpluginspage=\"http:\/\/www.adobe.com\/go\/getflashplayer\">\r\n\t\t\t<\/embed>\r\n\t<\/object>\r\n<\/noscript>\r\n<\/body>\r\n<\/html>\r\n<\/pre>\n<p><b>Note:<\/b> Main issue could be the cross site security issue (errors like &#8220;Send failed&#8221;) 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&#8217;s cache to see the latest version of your FLEX application.<\/p>\n<p>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 <a href=\"http:\/\/uk.finance.yahoo.com\/\">Yahoo Finance<\/a>, 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.<\/p>\n<p>Ideally, I want to improve this application to achieve the following diagram:<\/p>\n<p><a href=\"http:\/\/www.muratyaman.co.uk\/wp\/wp-content\/uploads\/2009\/10\/flex-app-structure.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.muratyaman.co.uk\/wp\/wp-content\/uploads\/2009\/10\/flex-app-structure-300x226.jpg\" alt=\"flex-app-structure\" title=\"flex-app-structure\" width=\"300\" height=\"226\" class=\"aligncenter size-medium wp-image-149\" srcset=\"https:\/\/www.muratyaman.co.uk\/blog\/wp-content\/uploads\/2009\/10\/flex-app-structure-300x226.jpg 300w, https:\/\/www.muratyaman.co.uk\/blog\/wp-content\/uploads\/2009\/10\/flex-app-structure.jpg 1000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PHP has always been my favourite scripting language to develop applications for the web.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[32,30,28,31,26,29],"class_list":["post-136","post","type-post","status-publish","format-standard","hentry","category-technology","tag-actionscript","tag-amf","tag-flex","tag-mxml","tag-php","tag-zend"],"_links":{"self":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts\/136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=136"}],"version-history":[{"count":15,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts\/136\/revisions"}],"predecessor-version":[{"id":932,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts\/136\/revisions\/932"}],"wp:attachment":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}