ZendAmfDs first release!!!
Last night on a way back from Katowice (spodek20.pl – barcamp event) I found some time to put my ZendAmfDs project together into distributable package. I created a zendamfds project on Google Code to host source files. Okay now couple of words what’s it all about…
ZendAmfDs is an extension to Zend_Amf (it actually extends Zend_Amf_Server class). It allows developers to configure and execute on the server side database queries against model classes that extend Zend_Db_Table_Abstract (SELECT, INSERT statements are supported with this release, I’m also planning to add in the future UPDATE statements – I encourage anyone from the community to help me on this
). As part of this project I also created very simple AS3 helper library that makes it very simple to use it from Flex side. With just a single line of code it is possible to execute queries plus register result and fault handlers, look further for more explanation.
To start playing with quickstart package you need to do couple of necessary steps:
- Download ZendAmfDsQuickstart package from here: http://code.google.com/p/zendamfds/downloads/list
- Download Zend Framework (Minimal is enough) from here: http://framework.zend.com/download/latest
- Unzip both archives and copy Zend library to ZendAmfDsQuickstart\library folder.
- Register your quickstart application in httpd.conf – Apache configuration file (there are probably couple of other ways to do that but that is something that works for me and I found it useful when working on multiple projects on the same Apache instance). My httpd.conf configuration looks like this:
Alias /quickstart /Users/pwalczys/Workspaces/Zend_Amf_Ds/ZendAmfDsQuickstart/public <Directory "/Users/pwalczys/Workspaces/Zend_Amf_Ds/ZendAmfDsQuickstart/public"> AllowOverride all Options None FollowSymLinks Order allow,deny Allow from all </Directory>
What it does it points requests from http://localhost/quickstart to web root folder that is in my case placed in /Users/pwalczys/Workspaces/Zend_Amf_Ds/ZendAmfDsQuickstart/public. Make sure you modify this according to your folders structure!!! Also important to note here is that under public folder there is a hidden .htaccess file that assumes that your application will have quickstart as web root folder. If you want to run it directly under http://localhost/ make sure you change /quickstart/index.php => /index.php at the bottom of .htaccess file. Make sure you restart Apache server after changes made in httpd.conf.
-
Next step is to create database, this example assumes that you will be using MySQL with ZEND_AMF_DS database and and FOOS_TABLE in it. There is a schema.mysql.sql file under scripts folder that will help you creating proper table structure with some sample data. Another important thing is to configure database access. In order to do that go to application/config/app.ini file and set property values for host, user and password. You may also want to change adapter if using different database engine.
// application/config/app.ini
[production] database.adapter = "PDO_MYSQL" database.params.dbname = "ZEND_AMF_DS" database.params.host = "127.0.0.1" database.params.username = "USERNAME" database.params.password = "PASSWORD" ...
-
Finally we are ready to run it, simply go to http://localhost/quickstart/ and you should see something like this:
You can play with this by using form that adds new records into FOOS_TABLE that are displayed in the DataGrid above.
If you had any problems with steps above you may want to refer to one of my previous posts where I explained how to configure Zend_Amf with full Zend Framework.
Okay now lets have a look how it works. Whole ZendAmfDsQuickstart package is a PHP/PDT project with Flex nature so if you are using Flex Builder or Eclipse with Flex Builder plugin you can download PDT from eclipse.org site to have also PHP editor in place.
- On PHP side it all starts with MessageBrokerController class (its in application/controllers/MessageBrokerController.php file). Major difference here is that I’m using ZendAmfDs class to instantiate AMF service that is located in library/ZendAmDs/ZendAmfDs.php. This class actually extends Zend_Amf_Server so you can use functions like addDirectory, setClassMap as you would do with Zend_Amf_Server itself. ZendAmfDs class constructor requires parameter with path to data-services.xml file that contains all SELECT, INSERT statements definitions.
<?php class MessageBrokerController extends Zend_Controller_Action { public function init() { $this->_helper->viewRenderer->setNoRender(true); } public function amfAction() { require_once 'ZendAmfDs/ZendAmfDs.php'; $server = new ZendAmfDs(APPLICATION_PATH . '/config/data-services.xml'); $server->addDirectory(APPLICATION_PATH . '/services/'); echo($server->handle()); } }
- Configuration file data-services.xml (its in application/config/data-services.xml) contains information about SELECT, INSERT statements and also where model classes are placed. In case of quickstart project there is only one model class called Foo that maps to FOOS_TABLE. There is one more thing to point here is that underscore notation (_) can be used when naming table columns and ZendAmfDs will convert these to camelCase property names on ActionScript class side (columnNameCamelSeparator element defines what is default separator in your column names, in case this is omitted it will map one-to-one column names to property names).
<?xml version="1.0" encoding="utf-8"?> <service> <destination id="ZendAmfDs"> <properties> <defaults> <columnNameCamelSeparator>_</columnNameCamelSeparator> <modelsPath>models</modelsPath> </defaults> <select id="findFooById"> <asClass>Foo</asClass> <modelClass>Foo</modelClass> <where>ID = 1</where> </select> <select id="findAllFoos"> <asClass>Foo</asClass> <modelClass>Foo</modelClass> <order>NAME</order> </select> <insert id="insertFoo"> <asClass>Foo</asClass> <modelClass>Foo</modelClass> </insert> </properties> </destination> </service>
-
Now if you take a look into Flex code there are two things to note here. I’m using ZendAmfDs.swc library that brings single helper class that is instantiated in MXML with following line:
<zendAmfDs:Service id="zendAmfDs" remoteObject="{remoteObject}" />and later on it is used by calling query method like this:zendAmfDs.query("findAllFoos", null, allFoosResultHandler);. This way it is possible to execute findAllFoos query on the server side without any parameters with allFoosResultHandler method as a result handler. If query requires any parametersnullvalue should be exchanged with an array of objects that will be passed to PHP and used in WHERE part of the query statement. Additionally it is possible to register fault handler that can be specified after result handler, in this particular case I’m using default fault handler registered during RemoteObject initialization.<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]" xmlns:models="quickstart.models.*" xmlns:zendAmfDs="net.riaspace.zendAmfDs.*" initialize="findAllFoos()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.rpc.events.ResultEvent; import mx.controls.Alert; [Bindable] private var allFoos:ArrayCollection; private function findAllFoos():void { zendAmfDs.query("findAllFoos", null, allFoosResultHandler); } private function allFoosResultHandler(event:ResultEvent):void { allFoos = new ArrayCollection(event.result as Array); } private function insertFoo():void { zendAmfDs.query("insertFoo", [foo], insertFooResultHandler); } private function insertFooResultHandler(event:ResultEvent):void { findAllFoos(); } ]]> </mx:Script> <mx:RemoteObject id="remoteObject" endpoint="http://localhost/quickstart/MessageBroker/amf" destination="zend" fault="Alert.show(event.message.toString())"/> <zendAmfDs:Service id="zendAmfDs" remoteObject="{remoteObject}" /> <mx:DataGrid dataProvider="{allFoos}"> <mx:columns> <mx:DataGridColumn headerText="ID" dataField="id"/> <mx:DataGridColumn headerText="NAME" dataField="name"/> <mx:DataGridColumn headerText="FOO_NUMBER" dataField="fooNumber"/> </mx:columns> </mx:DataGrid> <models:Foo id="foo" name="{txtName.text}" fooNumber="{Number(txtFooNumber.text)}" /> <mx:Form> <mx:FormItem label="NAME"> <mx:TextInput id="txtName"/> </mx:FormItem> <mx:FormItem label="FOO_NUMBER"> <mx:TextInput id="txtFooNumber"/> </mx:FormItem> <mx:FormItem> <mx:Button label="Insert" click="insertFoo()" /> </mx:FormItem> </mx:Form> </mx:Application>
This just couldn’t be simpler!!! Of course I’m waiting for the feedback and if anyone feels like adding UPDATE support please let me know…


[...] http://www.riaspace.net/2009/02/zendamfds-first-release/ [...]
Polish Adobe Flex User Group » Blog Archive » ZendAmfDs pierwsza wersja
11 Feb 09 at 5:49 pm
[...] http://www.riaspace.net/2009/02/zendamfds-first-release/ [...]
Tom Krcha's FlashRealtime.com ZendAMF DataServices with SQL XML Assembler —
11 Feb 09 at 6:28 pm
[...] it out at Piotr’s blog No Comments [...]
flexgeek » Blog Archive » ZendAMF DataServices with SQL XML Assembler
11 Feb 09 at 7:22 pm
Would you use this in real life public websites ?
Anyone thereafter can simulate your flash applet and execute any query they want afterward.
Take care.
iongion
12 Feb 09 at 6:46 am
My answer is yes… You have to remember that user can execute only queries that you configure on the server side in data-services.xml file. From Flex side you pass query id like “findFooById”, you have to make sure that you don’t configure queries on the server side that may return sensitive data like user password etc. this is always the case no matter what technology u are using. Another tricky thing is when you have INSERT and UPDATE statements and in those cases you have to know what you are doing and be prepared that someone may want to abuse your service with direct calls. In such a case you probably may want to use Zend_Acl and Zend_Auth in MessageBrokerController – I will try to put together an example in near future how it can be used together. At the moment you can check this: http://www.keithcraigo.com/archives/181
Piotr
12 Feb 09 at 9:36 am
[...] 4. ZendAmfDs pierwsza wersja więcej dowiecie się tutaj. [...]
Kilka newsów… | massiveProCreation Blog
13 Feb 09 at 10:20 pm
An interesting approach, it seems odd to build on the Zend Framework and not continue their style of coding (ie. ZendAmfDs instead of Zend_Amf_Ds) and I can only say that will certainly keep you from getting this project included by any means in the overall scheme of things. I’m not sure, however, I completely understand the benefit here, in fact it seems like it adds additional complexity to that which was already simple. I’ll agree that the inclusion of an XML file might make it easier to configure the services but I think that’s negligible. My understanding of the benefit for things like Blaze DS wasn’t the ease of use but the built-in functionality of data paging and management which I do not see exhibited here. If nothing else, at least it shows promise that people are pursuing alternative options to the standard array of data services providers for AMF systems.
James
4 Mar 09 at 1:15 am
I follow your posts for quite a long time and must tell you that your articles always prove to be of a high value and quality for readers.
How to Get Six Pack Fast
15 Apr 09 at 4:54 pm
The points above are all very insightful, thanks very much.
Serviced Apartment Bangkok
5 May 09 at 12:00 pm
I feel that it will not fit into the space of developers who are not native with Zend Framework. It should have been a standalone component support any frameworks.
Vinothbabu
8 Jun 09 at 1:35 pm
mm. funny
lesbian incest story
28 Jun 09 at 5:56 pm
I don’t think so
Steve
12 Jul 09 at 10:44 pm
I keep getting an error or should I say the fauoltEvent keeps getting fired. I figured out that my uri is pointing to localhost/quickstart while my uri is localhost:8888/quickstart. I have checked everywhere you set the url, i.e. app.ini, and the main flex application file. I created a new flex application tried to model your application structure so i can reconstruct the swf file but the problem seems to linger. Tried clearing my cache, same problem. Dont know if there’s any way you can help resolve this problem. Everthing thing else works but the faultevent just keeps getting fired.
Oluwaseun
21 Jun 10 at 2:54 pm