{"id":898,"date":"2010-09-27T12:31:11","date_gmt":"2010-09-27T17:31:11","guid":{"rendered":"http:\/\/www.lonhosford.com\/lonblog\/?p=898"},"modified":"2015-07-31T18:25:51","modified_gmt":"2015-07-31T23:25:51","slug":"parsley-mvc-remoteobject-zend-amf-and-mysql-basic-flex-example","status":"publish","type":"post","link":"https:\/\/www.lonhosford.com\/lonblog\/2010\/09\/27\/parsley-mvc-remoteobject-zend-amf-and-mysql-basic-flex-example\/","title":{"rendered":"Parsley MVC, RemoteObject, Zend AMF and MySQL Basic Flex Example"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p><script src=\"https:\/\/connect.facebook.net\/en_US\/all.js#appId=105467682877384&amp;xfbml=1\"><\/script><fb:like href=\"https:\/\/www.lonhosford.com\/lonblog\/2010\/09\/27\/parsley-mvc-remoteobject-zend-amf-and-mysql-basic-flex-example\/\" send=\"true\" width=\"450\" show_faces=\"true\" font=\"\"><\/fb:like><\/p>\n<p>After conquering <a href=\"https:\/\/www.lonhosford.com\/lonblog\/2010\/09\/14\/basic-parsley-framework-flex-example-explained\/\">a basic Parsley Framework Flex example<\/a> I wanted to create a minimal example of using the Flex Parsley framework, Zend AMF and MySQL. The Flex implementation goal is to mold a model view controller framework using Parsley and to communicate via Flex RemoteObject to Zend AMF. Eventually I applied what I learned to revamp <a href=\"http:\/\/www.defineit.com\" target = \"_blank\">DefineIt.com<\/a> with Parsley and Zend AMF.<\/p>\n<p>There are many approached to using Parsley for MVC. The Parsley documentation is very light on the subject. <img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/lh3.ggpht.com\/_e5pwU0LJbN8\/TKDUAky8sUI\/AAAAAAAAFt8\/eYNi96PU-hA\/s800\/ParselyZendAmfHelloWorld_published.png\" class=\"alignleft\" width=\"380\" height=\"199\" \/>These also entail including using other frameworks like Caringorm. In this example I kept it simply by just using the Parsley messaging features and creating my own controller class.<\/p>\n<p>I found other examples of Parsley that go further into its features. You might look at <a href=\"http:\/\/coenraets.org\/blog\/2009\/07\/building-a-flex-application-with-the-parsley-framework\/\">Christophe Coenraets&#8217;<\/a> example. This is referenced from the <a href=\"http:\/\/www.spicefactory.org\/parsley\/docs\/2.3\/manual\/\" target = \"_blank\">Parsley documentation<\/a> . Christophe includes an update and add feature to the application. It also contains a dynamically loaded image class. It is a bit over featured and thus over involved for a pure beginner. It is void of substantive explanation leaving you to explore the Parsley documentation to try to understand why one approach was chosen over another in code. Worse code has no comments. This should be a minimum requirement for any referenced sample code. However there are some good Flex and Parsley techniques in there that can be helpful and one to bookmark for your learning process.<\/p>\n<figure style=\"width: 134px\" class=\"wp-caption alignright\"><a href=\"http:\/\/www.amazon.com\/gp\/product\/0321660501?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0321660501\" target=\"_blank\"><img decoding=\"async\" border=\"0\" src=\"http:\/\/lh3.ggpht.com\/_e5pwU0LJbN8\/TI93JgBp5AI\/AAAAAAAAFtU\/2oU3O6g1mvg\/s800\/41N912-mmWL._SL160_.jpg\"><\/a><figcaption class=\"wp-caption-text\">Learn More About Flex 4 From Adobe<\/figcaption><\/figure>\n<p>Parsley 2.3 is used and the SWCs are included in the example Flex 4 project download I have here. I did appreciate these SWCs also being included in the downloads from the <a href=\"http:\/\/www.spicefactory.org\/parsley\/download.php\"  target = \"_blank\">Parsley download page<\/a>. Lets you get to learning faster. <\/p>\n<p>You can build this with the free Flex SDK by using the code in the src folder and be sure to include a path to the Parsley and Spicelib library. <\/p>\n<ul style = \"padding-top:10px\">\n<li><a href=\"https:\/\/www.lonhosford.com\/content\/flex\/Parsley\/ParsleyAndZendFramework_HelloWorld.fxp\" onClick=\"javascript: pageTracker._trackPageview('\/downloads\/ParsleyAndZendFramework_HelloWorld.fxp'); \">Flex Builder 4 Flex Project<\/a><\/li>\n<\/ul>\n<p>When you run this application, the trace log will show you the interactions between the model, controller, view and service.<\/p>\n<p><strong>Application Class &#8211; Parsley_Configuration.mxml<\/strong><br \/>\nThis is the main MXML file. Line 15 links the Parsley_Configuration.mxml file that configures Parsley framework. <\/p>\n<p>Line 16 tells Parsley to include this mxml file and thus allows us to inject the ApplicationModel data.<\/p>\n<p>I put all locale language into the model to simplify the example. In the effort the ApplicationModel class for application level data only contains the locale language title for the application you can see referenced in the Label on lines 26 and 39. <\/p>\n<p>Line 40 contains the Panel to display the data grid.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;\r\n&lt;s:Application xmlns:fx=&quot;http:\/\/ns.adobe.com\/mxml\/2009&quot; \r\n\t\t\t   xmlns:s=&quot;library:\/\/ns.adobe.com\/flex\/spark&quot; \r\n\t\t\t   xmlns:hellozend=&quot;com.alh.parsley.example.hellozend.*&quot;\r\n\t\t\t   xmlns:parsley=&quot;http:\/\/www.spicefactory.org\/parsley&quot;\r\n\t\t\t   xmlns:mx=&quot;library:\/\/ns.adobe.com\/flex\/mx&quot;\r\n\t\t\t   xmlns:sf=&quot;http:\/\/www.spicefactory.org\/parsley&quot;\r\n\t\t\t   minWidth=&quot;955&quot; minHeight=&quot;600&quot; \r\n\t\t\t   xmlns:views=&quot;com.alh.parsley.example.hellozend.views.*&quot;\r\n\t\t\t   &gt;\r\n\t&lt;fx:Declarations&gt;\r\n\t\t&lt;!-- \r\n\t\tParsley configuration MXML file\r\n\t\t--&gt;\r\n\t\t&lt;parsley:ContextBuilder config=&quot;Parsley_Configuration&quot; \/&gt;\r\n\t\t&lt;sf:Configure\/&gt;\r\n\t&lt;\/fx:Declarations&gt;\r\n\t&lt;fx:Script&gt;\r\n\t\t&lt;!&amp;#91;CDATA&amp;#91;\r\n\t\t\timport com.alh.parsley.example.hellozend.model.ApplicationModel;\r\n\t\t\t\/**\r\n\t\t\t * Parsley injects the ApplicationModel here.\r\n\t\t\t * *\/\r\n\t\t\t&amp;#91;Inject&amp;#93;\r\n\t\t\t&amp;#91;Bindable&amp;#93;\r\n\t\t\tpublic var model:ApplicationModel;\r\n\t\t\t\r\n\t\t&amp;#93;&amp;#93;&gt;\r\n\t&lt;\/fx:Script&gt;\r\n\t&lt;!-- \r\n\t\tUI\r\n\t--&gt;\r\n\t&lt;s:layout&gt;\r\n\t\t&lt;s:VerticalLayout gap=&quot;10&quot; \r\n\t\t\t\t\t\t  horizontalAlign=&quot;center&quot;\r\n\t\t\t\t\t\t  paddingLeft=&quot;12&quot; paddingRight=&quot;12&quot; paddingBottom=&quot;12&quot; paddingTop=&quot;12&quot;\r\n\t\t\t\t\t\t  \/&gt;\r\n\t&lt;\/s:layout&gt;\r\n\t&lt;s:Label text=&quot;{model.lang_AppTitle}&quot; fontSize=&quot;20&quot;\/&gt;\r\n\t&lt;views:AllMembersGrid\/&gt;\r\n&lt;\/s:Application&gt;\r\n<\/pre>\n<p><strong>Parsley Configuration &#8211; Parsley_Configuration.mxml<\/strong><br \/>\nThis is the file Parsley reads for configuration. <\/p>\n<p>I included  the RemoteObject definitions here as well. I am following Christophe Coenraets&#8217; example on this. It makes sense to me to have this as part of the configuration file. Remember to change the YOUR_GATEWAY_URL on line 13 to reflect your link to the Zend AMF or other RemoteObject service. <\/p>\n<p>You may note there is no services xml or configuration file. The channel information is in the MXML instead. You can learn more on this by reading <a href=\"https:\/\/www.lonhosford.com\/lonblog\/2010\/08\/26\/zend-amf-action-message-format-minimalist-example-using-remoteobject-and-mysql\/\"><br \/>\nZEND AMF (Action Message Format) Minimalist Example Using RemoteObject and MySQL<\/a><\/p>\n<p>On lines 27 &#8211; 30 I have four Actionscript classes handling the model, view and controller. They are listed here so we can use the [Inject] metatag for Parsley.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;\r\n&lt;Objects \r\n\txmlns:fx=&quot;http:\/\/ns.adobe.com\/mxml\/2009&quot;\r\n\txmlns=&quot;http:\/\/www.spicefactory.org\/parsley&quot;\r\n\txmlns:s=&quot;library:\/\/ns.adobe.com\/flex\/spark&quot; \r\n\txmlns:hellozend=&quot;com.alh.parsley.example.hellozend.*&quot; \r\n\txmlns:model=&quot;com.alh.parsley.example.hellozend.model.*&quot; \r\n\txmlns:services=&quot;com.alh.parsley.example.hellozend.services.*&quot; \r\n\txmlns:controller=&quot;com.alh.parsley.example.hellozend.controller.*&quot;&gt;\r\n\t&lt;fx:Declarations&gt;\r\n\t\t&lt;s:ChannelSet id = &quot;zend_amf_channel_set&quot;&gt;\r\n\t\t\t&lt;s:channels&gt;\r\n\t\t\t\t&lt;s:AMFChannel uri=&quot;YOUR_GATEWAY_URL&quot;\/&gt;\r\n\t\t\t&lt;\/s:channels&gt;\r\n\t\t&lt;\/s:ChannelSet&gt;\r\n\t\t&lt;!-- MembershipService RemoteObject --&gt;\r\n\t\t&lt;s:RemoteObject\tid=&quot;membershipService_ro&quot; \r\n\t\t\t\t\t\tdestination=&quot;zend-amf&quot; \r\n\t\t\t\t\t\tsource=&quot;MembershipService&quot; \r\n\t\t\t\t\t\tchannelSet=&quot;{zend_amf_channel_set}&quot;\r\n\t\t\t\t\t\tshowBusyCursor=&quot;true&quot; \r\n\t\t\t\t\t\t&gt;\r\n\t\t&lt;\/s:RemoteObject&gt;\r\n\t\t&lt;!--\r\n\t\t\tParsley defined objects slated for injection where &amp;#91;Inject&amp;#93; metatag appears.\r\n\t\t--&gt;\r\n\t\t&lt;model:ApplicationModel\/&gt;\r\n\t\t&lt;model:MembershipModel\/&gt;\r\n\t\t&lt;services:MembershipServiceRemote\/&gt;\r\n\t\t&lt;controller:MembershipController\/&gt;\r\n&lt;\/fx:Declarations&gt;\r\n&lt;\/Objects&gt;\r\n<\/pre>\n<p><strong>Application Model Class &#8211; ApplicationModel.as<\/strong><br \/>\nThis class defines application level data and we only have a language variable to simplify the example for localization.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.model\r\n{\r\n\t\/**\r\n\t * Model for application level data\r\n\t * *\/\r\n\tpublic class ApplicationModel\r\n\t{\r\n\t\t\/**\r\n\t\t * UI language in model to simplify example\r\n\t\t * \r\n\t\t * Language for Application\r\n\t\t * *\/\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_AppTitle:String = \"Minimalist Parsley Zend AMF Example Using RemoteObject\";;\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>Membership Model Class &#8211; MembershipModel.as<\/strong><br \/>\nThis class defines membership data. Again you can see the variables to simplify the example for localization. <\/p>\n<p>The key data here is the ArrayCollection on line 13 for the member data.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.model\r\n{\r\n\timport mx.collections.ArrayCollection;\r\n\t\/**\r\n\t * Model for membership\r\n\t * *\/\r\n\tpublic class MembershipModel\r\n\t{\r\n\t\t\/**\r\n\t\t * List of members;\r\n\t\t * *\/\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var members:ArrayCollection;\r\n\t\t\/**\r\n\t\t * UI language in model to simplify example\r\n\t\t * \r\n\t\t * Language for AllMembersGrid view\r\n\t\t * *\/\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_AllMembersGridTitle:String = \"Membership Listing\";\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_MemberKey:String = \"Member Key\";\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_FirstName:String = \"First Name\";\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_LastName:String = \"Last Name\";\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_EmailAddress:String = \"Email Address\";\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_GetMembers:String = \"Get Members\";\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var lang_ClearMembers:String = \"Clear\";\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>IMembershipService Class &#8211; IMembershipService.as<\/strong><br \/>\nInterface to define methods for membership service classes. We only have one in the example: MembershipServiceRemote.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.services\r\n{\r\n\timport mx.rpc.AsyncToken;\r\n\t\/**\r\n\t * Interface to define MembershipService classes\r\n\t * *\/\r\n\tpublic interface IMembershipService\r\n\t{\r\n\t\tfunction getAllMembers():AsyncToken;\r\n\t}\r\n}\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>MembershipServiceRemote Class &#8211; MembershipServiceRemote.as<\/strong><br \/>\nThis class deals with the server service. Only the controller communicates with this class by calling the get getAllMembers() method.<\/p>\n<p>Line 46 is the interface back to the MVC or to the application however you want to look at it. Here a Parsley message is created for the MembershipGetAllMembersEvent.GET_ALL_MEMBERS event that you will see the MembershipController class handles. <\/p>\n<p>You could have the controller pass its own result and fault handlers to the getAllMembers() method and eliminate the MembershipGetAllMembersEvent.GET_ALL_MEMBERS message. <\/p>\n<p>As a further simplification, the faults are all routed to the catchAllServiceErrorHandler(&#8230;) method where a view component is inserted breaking a clean MVC. You could create a message for the fault handler to dispatch and have the controller to handle this. <\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.services\r\n{\r\n\timport com.alh.parsley.example.hellozend.events.MembershipGetAllMembersEvent;\r\n\timport com.alh.parsley.example.hellozend.services.IMembershipService;\r\n\timport mx.controls.Alert;\r\n\timport mx.rpc.AsyncResponder;\r\n\timport mx.rpc.AsyncToken;\r\n\timport mx.rpc.events.FaultEvent;\r\n\timport mx.rpc.events.ResultEvent;\r\n\timport mx.rpc.remoting.RemoteObject;\r\n\t\/**\r\n\t * IMembershipService class to handle RemoteObject data communications with server.\r\n\t * *\/\r\n\tpublic class MembershipServiceRemote implements IMembershipService\r\n\t{\r\n\t\t\/**\r\n\t\t * Specify the remote service for Parsley to inject.\r\n\t\t * *\/\r\n\t\t&#x5B;Inject(id=\"membershipService_ro\")]\r\n\t\tpublic var service:RemoteObject;\t\t\r\n\t\t\/**\r\n\t\t * Parsley creates an event dispatcher function\r\n\t\t * *\/\r\n\t\t&#x5B;MessageDispatcher]\r\n\t\tpublic var dispatcher:Function;\r\n\r\n\t\t\/**\r\n\t\t * Get all members from RemoteObject service.\r\n\t\t * *\/\r\n\t\tpublic function getAllMembers():AsyncToken\r\n\t\t{\r\n\t\t\ttrace (\"SERVICE: MembershipServiceRemote.getAllMembers()\");\r\n\t\t\tvar token:AsyncToken = service.getAllMembers();\r\n\t\t\ttoken.addResponder(\r\n\t\t\t\tnew AsyncResponder(getAllMembersResultsHandler, catchAllServiceErrorHandler));\r\n\t\t\treturn token;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * ResultEvent handler for service.getAllMembers()\r\n\t\t * *\/\r\n\t\tprotected function getAllMembersResultsHandler(event:ResultEvent, result:Object):void\r\n\t\t{\r\n\t\t\ttrace (\"SERVICE: MembershipServiceRemote.getAllMembersResultsHandler()\");\r\n\t\t\t\/\/event.result == Array.\r\n\t\t\tvar members:Array = event.result as Array;\r\n\t\t\tdispatcher( new MembershipGetAllMembersEvent(MembershipGetAllMembersEvent.GET_ALL_MEMBERS, members));\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Default handler for MembershipServiceRemote calls\r\n\t\t * *\/\r\n\t\tprotected function catchAllServiceErrorHandler(e:FaultEvent):void\r\n\t\t{\r\n\t\t\tAlert.show(e.toString());\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>MembershipController Class &#8211; MembershipController.as<\/strong><br \/>\nThis controller ties in the MembershipModel class and the MembershipServiceRemote class on line 18 and 24 respectively.<\/p>\n<p>The controller listens for the MembershipEvent events on line 29. The Parsley [MessageHandler] tag makes this happen. These events are dispatched in the view.<\/p>\n<p>On line 46 the controller listens for the MembershipGetAllMembersEvent dispatched from the MembershipServiceRemote class.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.controller\r\n{\r\n\timport com.alh.parsley.example.hellozend.events.MembershipEvent;\r\n\timport com.alh.parsley.example.hellozend.events.MembershipGetAllMembersEvent;\r\n\timport com.alh.parsley.example.hellozend.model.MembershipModel;\r\n\timport com.alh.parsley.example.hellozend.services.MembershipServiceRemote;\r\n\timport mx.collections.ArrayCollection;\r\n\t\/**\r\n\t * Controller for Membership model and views.\r\n\t * *\/\r\n\tpublic class MembershipController\r\n\t{\r\n\t\t\/**\r\n\t\t * Parsley injects the MembershipModel here.\r\n\t\t * *\/\r\n\t\t&#x5B;Inject]\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var model:MembershipModel;\r\n\t\t\/**\r\n\t\t * Parsley injects the MembershipService here.\r\n\t\t * *\/\r\n\t\t&#x5B;Inject]\r\n\t\t&#x5B;Bindable]\r\n\t\tpublic var service:MembershipServiceRemote;\r\n\t\t\/**\r\n\t\t * Parsley identified handler for MembershipEvent\r\n\t\t * *\/\r\n\t\t&#x5B;MessageHandler]\r\n\t\tpublic function membershipEventHandler( message:MembershipEvent ):void\r\n\t\t{\r\n\t\t\ttrace (\"CONTROLLER: MembershipController.membershipEventHandler(...) - message.type:\" + message.type);\r\n\t\t\tswitch (message.type )\r\n\t\t\t{\r\n\t\t\t\tcase MembershipEvent.GET_ALL_MEMBERS:\r\n\t\t\t\t\tservice.getAllMembers();\r\n\t\t\t\t\tbreak\r\n\t\t\t\tcase MembershipEvent.CLEAR_ALL_MEMBERS:\r\n\t\t\t\t\tmodel.members.removeAll();\r\n\t\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Parsley identified handler for MembershipGetAllMembersEvent\r\n\t\t * *\/\r\n\t\t&#x5B;MessageHandler]\r\n\t\tpublic function membershipGetAllMembersEventHandler( message:MembershipGetAllMembersEvent ):void\r\n\t\t{\r\n\t\t\ttrace (\"CONTROLLER: MembershipController.membershipGetAllMembersEventHandler(...)\");\r\n\t\t\tmodel.members = new ArrayCollection(message.members);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>Membership Grid View &#8211; AllMembersGrid.mxml<\/strong><br \/>\nThis is a Panel containing a DataGrid and Buttons for the user interaction.<\/p>\n<p>Lines 27 and 28 sets up the class to dispatch Parsley messages. Line 35 dispatches the MembershipEvent.CLEAR_ALL_MEMBERS event and line 43 dispatches the MembershipEvent.GET_ALL_MEMBERS event. The MembershipController class handles these messages to update the model and communicate with the service as needed.<\/p>\n<p>This view is tied to the MembershipModel class via Parsley on line 23. The DataGrid binds to the model members variable.<\/p>\n<p>Other bindings for the language localizations appear as well.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;\r\n&lt;s:Panel xmlns:fx=&quot;http:\/\/ns.adobe.com\/mxml\/2009&quot; \r\n\t\t xmlns:s=&quot;library:\/\/ns.adobe.com\/flex\/spark&quot; \r\n\t\t xmlns:mx=&quot;library:\/\/ns.adobe.com\/flex\/mx&quot;\r\n\t\t xmlns:sf=&quot;http:\/\/www.spicefactory.org\/parsley&quot;\r\n\t\t title = &quot;{model.lang_AllMembersGridTitle}&quot;\r\n\t\t&gt;\r\n\t&lt;fx:Declarations&gt;\r\n\t\t&lt;!-- \r\n\t\tParsely will manage this component.\r\n\t\t--&gt;\r\n\t\t&lt;sf:Configure\/&gt;\r\n\t&lt;\/fx:Declarations&gt;\r\n\t&lt;fx:Script&gt;\r\n\t\t&lt;!&amp;#91;CDATA&amp;#91;\r\n\t\t\timport com.alh.parsley.example.hellozend.events.MembershipEvent;\r\n\t\t\timport com.alh.parsley.example.hellozend.model.MembershipModel;\r\n\t\t\t\/**\r\n\t\t\t * Parsley injects the MembershipModel here.\r\n\t\t\t * *\/\r\n\t\t\t&amp;#91;Inject&amp;#93;\r\n\t\t\t&amp;#91;Bindable&amp;#93;\r\n\t\t\tpublic var model:MembershipModel;\r\n\t\t\t\/**\r\n\t\t\t * Parsley creates an event dispatcher function\r\n\t\t\t * *\/\r\n\t\t\t&amp;#91;MessageDispatcher&amp;#93;\r\n\t\t\tpublic var dispatcher:Function;\r\n\t\t\t\/**\r\n\t\t\t * Dispatch MembershipEvent.CLEAR_ALL_MEMBERS event\r\n\t\t\t * *\/\r\n\t\t\tprotected function clearDataGrid():void\r\n\t\t\t{\r\n\t\t\t\ttrace(&quot;VIEW: &quot; + className + &quot;.clearDataGrid()&quot;);\r\n\t\t\t\tdispatcher( new MembershipEvent( MembershipEvent.CLEAR_ALL_MEMBERS ));\r\n\t\t\t}\r\n\t\t\t\/**\r\n\t\t\t * Dispatch MembershipEvent.GET_ALL_MEMBERS event\r\n\t\t\t * *\/\r\n\t\t\tprotected function getAllMembers():void\r\n\t\t\t{\r\n\t\t\t\ttrace(&quot;VIEW: &quot; + className + &quot;.getAllMembers()&quot;);\r\n\t\t\t\tdispatcher( new MembershipEvent( MembershipEvent.GET_ALL_MEMBERS ));\r\n\t\t\t}\r\n\t\t&amp;#93;&amp;#93;&gt;\r\n\t&lt;\/fx:Script&gt;\r\n\t&lt;s:layout&gt;\r\n\t\t&lt;s:VerticalLayout gap=&quot;10&quot; \r\n\t\t\t\t\t\t  paddingLeft=&quot;12&quot; paddingRight=&quot;12&quot; paddingBottom=&quot;12&quot; paddingTop=&quot;12&quot;\r\n\t\t\t\t\t\t  \/&gt;\r\n\t&lt;\/s:layout&gt;\r\n\t&lt;mx:DataGrid  id=&quot;member_dg&quot;  height=&quot;100&quot; dataProvider=&quot;{model.members}&quot;&gt;\r\n\t\t&lt;mx:columns&gt;\r\n\t\t\t&lt;mx:DataGridColumn headerText=&quot;{model.lang_MemberKey}&quot; dataField=&quot;memberKey&quot;\/&gt;\r\n\t\t\t&lt;mx:DataGridColumn headerText=&quot;{model.lang_FirstName}&quot; dataField=&quot;firstName&quot;\/&gt;\r\n\t\t\t&lt;mx:DataGridColumn headerText=&quot;{model.lang_LastName}&quot; dataField=&quot;lastName&quot;\/&gt;\r\n\t\t\t&lt;mx:DataGridColumn headerText=&quot;{model.lang_EmailAddress}&quot; dataField=&quot;emailAddress&quot; width=&quot;200&quot;\/&gt;\r\n\t\t&lt;\/mx:columns&gt;\r\n\t&lt;\/mx:DataGrid&gt;\r\n\t&lt;s:HGroup horizontalAlign=&quot;center&quot; width=&quot;100%&quot;&gt;\r\n\t\t&lt;s:Button label=&quot;{model.lang_GetMembers}&quot; click=&quot;{getAllMembers();}&quot;\/&gt;\r\n\t\t&lt;s:Button label=&quot;{model.lang_ClearMembers}&quot; click=&quot;{clearDataGrid();}&quot;\/&gt;\r\n\t&lt;\/s:HGroup&gt;\r\n\r\n&lt;\/s:Panel&gt;\r\n<\/pre>\n<p><strong>MembershipEvent.as<\/strong><br \/>\nThis is a standard Event class to inform the MVC framework all membership data is required or needs to be cleared. These free the view from being coupled with the service or updating the model.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.events\r\n{\r\n\timport flash.events.Event;\r\n\t\/**\r\n\t * Events related to membership.\r\n\t * *\/\r\n\tpublic class MembershipEvent extends Event\r\n\t{\r\n\t\t\/**\r\n\t\t * Request to retrieve all membership data\r\n\t\t * *\/\r\n\t\tpublic static const GET_ALL_MEMBERS:String = \"com.alh.parsley.example.hellozend.events.MembershipEvent.getAllMembers\";\r\n\t\t\/**\r\n\t\t * Request to clear all membership data\r\n\t\t * *\/\r\n\t\tpublic static const CLEAR_ALL_MEMBERS:String = \"com.alh.parsley.example.hellozend.events.MembershipEvent.clearAllMembers\";\r\n\r\n\t\tpublic function MembershipEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)\r\n\t\t{\r\n\t\t\tsuper(type, bubbles, cancelable);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>MembershipGetAllMembersEvent.as<\/strong><br \/>\nThis event message signals success retrieval of members data from the service. <\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.alh.parsley.example.hellozend.events\r\n{\r\n\timport flash.events.Event;\r\n\t\/**\r\n\t * Event defining service receipt of membership data.\r\n\t * *\/\r\n\tpublic class MembershipGetAllMembersEvent extends Event\r\n\t{\r\n\t\tpublic static const GET_ALL_MEMBERS:String = \"com.alh.parsley.example.hellozend.events.MembershipGetAllMembersEvent.getAllMembers\";\r\n\t\t\/**\r\n\t\t * Membership data\r\n\t\t * *\/\r\n\t\tpublic var members:Array;\r\n\t\t\r\n\t\tpublic function MembershipGetAllMembersEvent(type:String, members:Array, bubbles:Boolean=false, cancelable:Boolean=false)\r\n\t\t{\r\n\t\t\tsuper(type, bubbles, cancelable);\r\n\t\t\tthis.members = members;\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>Zend AMF Gateway PHP Script<\/strong><br \/>\nThis is the gateway program for the Zend Amf. This is the file that you reference on line 13 of the Parsley_Configuration.mxml file. In this example it was named index.php.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\/**\r\n*  Sample Zend AMF gateway\r\n*  @return Endpoint &amp;#91;Zend Amf Endpoint&amp;#93;\r\n* *\/\r\n\r\n\/\/ Configurable values\r\n\/\/ Debugging values\r\n$debug = true;                             \/\/ Debugging status\r\nif ($debug)\r\n{\r\n\t\/\/ Report all errors, warnings, interoperability and compatibility\r\n\terror_reporting(E_ALL|E_STRICT);\r\n\t\/\/ Show errors with output\r\n\tini_set(&quot;display_errors&quot;, &quot;on&quot;);\r\n}\r\nelse\r\n{\r\n\terror_reporting(0);\r\n\tini_set(&quot;display_errors&quot;, &quot;off&quot;);\r\n}\r\n\/\/ Add the Zend AMF installation folder to the include path.\r\n\/\/ In this example the frameworks folder is a sibling folder to\r\n\/\/ this application folder. The frameworks folder contains the Zend\r\n\/\/ folder that is extracted from http:\/\/framework.zend.com\/download\/amf\r\nini_set(&quot;include_path&quot;, ini_get(&quot;include_path&quot;) . PATH_SEPARATOR . &quot;..\\\\frameworks&quot; );\r\n\r\n\/\/ Instantiate the Zend Amf server\r\nrequire_once &#039;Zend\/Amf\/Server.php&#039;;\r\n$server = new Zend_Amf_Server();\r\n\r\n\/\/ Register your service classes\r\nrequire_once &#039;MembershipService.php&#039;;\r\n$server-&gt;setClass(&quot;MembershipService&quot;);\r\n\r\n\/\/Map ActionScript value objects to the PHP value objects.\r\n$server-&gt;setClassMap(&quot;MemberData&quot;, &quot;MemberData&quot;);\r\n\r\n\/\/ Return the handle.\r\necho ($server-&gt;handle());\r\n\r\n?&gt;\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>MembershipService Class<\/strong><br \/>\nThis is the service class that contains remote methods. Generally a the database and business logic is delegated to another API you write. In this case they are all together for simplicity.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\/**\r\n*\tService class exposing the methods to deal with membership.\r\n*   This example includes business logic for simplicity of study.\r\n*\/\r\nrequire_once &#039;MemberData.php&#039;;\r\nclass MembershipService\r\n{\r\n\tpublic function MembershipService()\r\n\t{\r\n\t\t\/\/ Connect to MySql database.\r\n\t\t\/\/ Supply your own MySQL access values.\r\n\t\t\/\/ These are defaults when running on your own private computer.\r\n\t\tmysql_connect(&quot;localhost&quot;, &quot;root&quot;, &quot;&quot;);\r\n\t\t\/\/ Select the database.\r\n\t\t\/\/ Supply your own database name.\r\n\t\tmysql_select_db(&quot;test&quot;);\r\n\t}\r\n\t\/**\r\n\t*\tGet all members and all fields.\r\n\t*\/\r\n\tpublic function getAllMembers()\r\n\t{\r\n\t\t\/\/ Array of MemberData objects.\r\n\t\t$members = array();\r\n\t\t\/\/ Selecting all fields and all records from table.\r\n\t\t\/\/ Supply your own table name and optionally your own SQL statement.\r\n\t\t$result = mysql_query(&quot;SELECT * FROM zend_amf_members&quot;);\r\n\t\t\/\/ Assuming mysql_query success. Slog through records.\r\n\t\twhile ($row = mysql_fetch_assoc($result))\r\n\t\t{\r\n\t\t\t\/\/ Create a MemberData value object and populate.\r\n\t\t\t$member = new MemberData();\r\n\t\t\t$member-&gt;memberKey = $row&#x5B;&quot;memberKey&quot;];\r\n\t\t\t$member-&gt;firstName = $row&#x5B;&quot;firstName&quot;];\r\n\t\t\t$member-&gt;lastName = $row&#x5B;&quot;lastName&quot;];\r\n\t\t\t$member-&gt;emailAddress = $row&#x5B;&quot;emailAddress&quot;];\r\n\t\t\tarray_push($members, $member);\r\n\t\t}\r\n\t\t\/\/ Return the members array to client.\r\n\t\treturn $members;\r\n\t}\r\n}\r\n?&gt;\r\n<\/pre>\n<p><strong>MemberData Value Object Class for PHP<\/strong><br \/>\nThis is the value object on the server side to define the field names for a member object. This is mapped to the client side on line 37 of the Zend AMF gateway script.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\/**\r\n * Value object defining the member data\r\n * *\/\r\nclass MemberData\r\n{\r\n  public $memberKey;\t\/\/ uint\r\n  public $firstName;\t\/\/ String\r\n  public $lastName;\t\t\/\/ String\r\n  public $emailAddress;\t\/\/ String\r\n}\r\n?&gt;\r\n<\/pre>\n<p><strong>SQL To Create Testing Table<\/strong><br \/>\nThe PHP script uses zend_amf_members for the table and this is the SQL to create that table. In this example the database was called test.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nSET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";\r\n\r\n--\r\n-- Database: `test`\r\n--\r\n\r\n-- --------------------------------------------------------\r\n\r\n--\r\n-- Table structure for table `zend_amf_members`\r\n--\r\n\r\nCREATE TABLE IF NOT EXISTS `zend_amf_members` (\r\n  `memberKey` int(10) unsigned NOT NULL auto_increment,\r\n  `firstName` varchar(30) NOT NULL default '',\r\n  `lastName` varchar(30) NOT NULL default '',\r\n  `emailAddress` varchar(50) NOT NULL default '',\r\n  PRIMARY KEY  (`memberKey`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Zend Amf Examples' AUTO_INCREMENT=7 ;\r\n\r\n--\r\n-- Dumping data for table `zend_amf_members`\r\n--\r\n\r\nINSERT INTO `zend_amf_members` (`memberKey`, `firstName`, `lastName`, `emailAddress`) VALUES\r\n(1, 'Donald', 'Duck', 'quacker@pond.com'),\r\n(2, 'Daffy', 'Duck', 'daft_2x@farm.org'),\r\n(3, 'Elmer', 'Fudd', 'elmer.fudd@hunters.net'),\r\n(4, 'Bugs', 'Bunny', 'whats_up_doc@underground.org'),\r\n(5, 'Yosemite', 'Sam', 'varmint_chaser@forest.com'),\r\n(6, 'Wile', 'Coyote', 'ceo@acme.com');\r\n<\/pre>\n<div id=\"fb-root\"><\/div>\n<p><script src=\"https:\/\/connect.facebook.net\/en_US\/all.js#xfbml=1\"><\/script><fb:comments href=\"https:\/\/www.lonhosford.com\/lonblog\/2010\/09\/27\/parsley-mvc-remoteobject-zend-amf-and-mysql-basic-flex-example\" num_posts=\"2\" width=\"500\"><\/fb:comments><\/p>\n","protected":false},"excerpt":{"rendered":"<p>After conquering a basic Parsley Framework Flex example I wanted to create a minimal example of using the Flex Parsley framework, Zend AMF and MySQL. The Flex implementation goal is to mold a model view controller framework using Parsley and to communicate via Flex RemoteObject to Zend AMF. Eventually I applied what I learned to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[19,51,9,55,57,94],"class_list":["post-898","post","type-post","status-publish","format-standard","hentry","category-general","tag-actionscript","tag-amf","tag-flex","tag-parsley","tag-php-2","tag-zend-amf"],"_links":{"self":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/898","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/comments?post=898"}],"version-history":[{"count":49,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/898\/revisions"}],"predecessor-version":[{"id":3698,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/898\/revisions\/3698"}],"wp:attachment":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/media?parent=898"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/categories?post=898"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/tags?post=898"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}