Many tutorials suggest that you set up the Zend AMF server directly in the bootstrap or index.php file. But what if you want to build a hybrid application with both Flex and HTML interfaces? In this case it’s better to let the bootstrap file do its usual job of application dispatching, and to make the AMF gateway a controller.
Introducing the Gateway Controller
Setting up a Zend AMF server inside a Zend controller is pretty easy:
-
class GatewayController extends Zend_Controller_Action
-
{
-
public function indexAction()
-
{
-
$this->getHelper('ViewRenderer')->setNoRender();
-
$server = new Zend_Amf_Server();
-
$server->addDirectory( dirname(__FILE__) . '/../services/' );
-
echo($server->handle());
-
}
-
}
Since we do not want to output any visible content we disable the view renderer (otherwise the action controller will look for a view script in a subdirectory named after the controller). The endpoint URI of our AMF server gateway is now something like http://www.mydomain.com/gateway/, and doesn’t interfere with our other controllers. By calling the addDirectory() method we tell the server where to look for the services. We only need to provide a base directory here. If we set up our remote objects in Flex with full namespaces the AMF server is able to resolve the dot syntax into the appropriate path.
For example, the dot syntax in the source attribute of this remote object
<mx:RemoteObject id="articlesRO" showBusyCursor="true" source="com.xeladon.cms.ArticlesService" destination="zend"/>
will be transformed into the path com/xeladon/cms/ArticlesService. Please note that in this setup there is no need for explicitly propagating each service class to the server with the setClass() method. For more information on the different approaches (addDirectory() vs. setClass()) please refer to Wade Arnold’s blog post on Lazy Loading Classes.
Organizing Value Objects with Namespaces
Now let’s take this one step further. As a long-time AMFPHP user, I have gotten in the habit of organizing my value objects with namespaces. I usually put my VOs in a folder below the service classes:
We can still do this with Zend but we have to make sure that Zend Loader is able to find the VO classes. I suggest adding the path to the include path in the index.php file:
-
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application/'));
-
-
set_include_path(
-
get_include_path()
-
. PATH_SEPARATOR . APPLICATION_PATH . '/../library/'
-
. PATH_SEPARATOR . APPLICATION_PATH . '/models/'
-
. PATH_SEPARATOR . APPLICATION_PATH . '/services/com/xeladon/cms/vo/'
-
);
-
-
require_once "Zend/Loader.php";
-
Zend_Loader::registerAutoload();
Adding More Functionality
Based on the above setup, we can easily add more functionaliy to the bootstrap file without worrying about the AMF server gateway. We would probably want to make use of Zend_Config for configuring the application, and Zend_Db for managing database interactions. By adding a few more lines of code to the bootstrap file, these functions become automatically available to the AMF service classes.
Let’s assume we set up a database adapter in the bootstrap file. This allows us to write very clean code inside the service classes. The following code is just an example (where ArticleVO is a typical value object, and Articles is supposed to be a Zend model class that extends Zend_Db_Table):
-
class ArticlesService
-
{
-
public function getArticles()
-
{
-
$articles = array();
-
$table = new Articles();
-
$result = $table->fetchAll();
-
foreach ($result as $row)
-
{
-
$article = new ArticleVO();
-
$article->id = $row->id;
-
$article->author = $row->author;
-
$article->title = $row->title;
-
$article->teaser = $row->teaser;
-
$article->body = $row->body;
-
array_push($articles, $article);
-
}
-
return $articles;
-
}
-
}
Summary
What do we gain with all this?
- We keep things organized and can rely on the same structures (packages, folders, namespaces) in both ActionScript and PHP.
- We can use other powerful features of the Zend framework for the application’s server-side logic.
- We have the flexibility of adding Flex/Flash and HTML interfaces to the same core application whenever and whereever needed.

Hi,
I tried the same thing some time ago but without success because in my ZF MVC environment using a controller the HTTP request changed from application/amf to text/html (I found out with Charles) and hence was never handled by the server. I guess this has something to do with mod_rewrite but I’ll try again.
Nice explaination of addDirectory() implementation.
Best regards,
Björn
[...] Utilizing the Zend AMF Server Inside a Zend Controller | blog.log2e.com (tags: zend amf) [...]
The German “PHPmagazin” considered my post worth a news item on their website: http://it-republik.de/php/news/Zend-AMF-Server-innerhalb-eines-Controllers-aufsetzen-046588.html
Thanks guys!
Hey I just did find your blog. Good Stuff! Don’t have time now to read trough all the topics but I will come back later to read more.
Hi Stefan
Thanks a lot for sharing this, it’s definitely something I want to achieve in my setups. I have been utilizing amfphp for quite some time and do see the advantages of going into Zend.
When you say
…URI of our AMF server gateway is now something like http://www.mydomain.com/gateway/...
I assume there needs to be a folder ‘gateway’ somewhere with a script that instantiates a new GatewayController instance. Right? But I can’t see anything like it in your project structure. Would you please clarify this?
@lunacafu: Please make yourself familiar with Zend Framework’s MVC and routing concepts. ZF doesn’t use a physical folder structure for routing requests. Instead it makes use of mod_rewrite. A typical ZF URI looks like this
http://www.mydomain.com/module/controller/action/
If your app doesn’t have modules you can skip the first part and start directly with the controller name. In the above exmaple the class name “GatewayController” is automatically transformed into the URI part “gateway”. If you omit the action name, the default action is used (the method name for this is “indexAction()”). So our gateway URI can be simplified to http://www.mydomain.com/gateway/.
Hi! Thank you for this post. Actually, I’m not very familiar with this topic but after reading your post, it’s clear now! Keep up the good posts like this. Take care!
Hi!
Somewhere I am doing something wrong. Shouldn’t I get ‘Zend Amf Endpoint” message when I call
http://www.mydomain.com/gateway/
What I get is the download dialog and calling the from Flex I get
Failed to parse data (java.io.IOException: Unsupported AMF version or courrupted data: 15393)
Any hint?
I very liked this post. Can I copy it to my blog?
Thank you in advance.
Sincerely, Timur Alhimenkov.
hi…
Thank you! I would now go on this blog every day!…
I also dont get zend amf endpoint by calling it directly in the controller.
example: http://myproject/mygateway
will open a dialog application/x-amf in firefox with the option to download it.
but when im setting up the server withouth the mvc overhead (just a single file initializing the server) it works without any problems.
Here is what i get when downloading the gateway file:
Zend Amf Endpoint^@^@^@^@^@^@
Hello,
First, thank you for your post about using ZendAMF inside a zend controller.
I’ve got a little problem when i’m trying running the AMF server: first i don’t get the zend amf endpoint when I try the url : http://localhost/gateway/
Could you please upload a zip of an empty project using amf server inside a zend controller
cordially
I have the same issue as macSack where when I call http://www.mydomain.com/gateway, I get a download dialog rather than a “Zend AMF Endpoint” message.
Is this the correct behavior? Or does it sound like something fishy with the server/.htaccess setup?
@Aaron et al.: The “<p>Zend Amf Endpoint</p>” string is sent as content type “application/x-amf”. That’s why the browser opens a download dialog. Have you actually tried to connect to the gateway? Even though you don’t get the usual endpoint message the setup works. I have tested it with both Flash and Flex/Cairngorm.
I didn’t provide the complete code needed for a proper ZF setup. For more detailed information on setting up Zend_Amf inside a controller please read this excellent tutorial http://www.riaspace.net/2009/01/zend_amf-with-full-zend-framework/. It follows the same approach as my article but provides the full code for the bootstrap file etc.
Thank a lot for the link !!
hi guys,
i’ve just started a zend project that needs to talk to flash, (not flex – but my question is relevant here as you’ll see!).
anyhow, i need to create an end point with services for a flash application to use. i’m not going to be building the flash element but i need to have as much ready as poss. for when the flash developer starts to do his/her thang!
thus i need to essentially be able to test and emulate how flash/flex would use these services. i understand that amfphp has a browser syntax to allow for testing and aiding the development for such services.
i’ve had a look but haven’t seen anything for zend-amf, does such a beast exist? if not, does anyone have any suggestions of a sensible way of doing this? ideally i’d like to get some formal/automated testing in there too (although this may be asking a bit much at this stage!).
help very appreciated, time is of the essence here!
rob ganly
(i posted this same question here: http://corlan.org/2008/11/13/flex-and-php-remoting-with-zend-amf/ but need a quick answer so thought i’d ask here as well!
Hello, Stefan
Thanks for the insight on how to blend Zend Amf with its MVC.
As far as i understand, when you organize code in this way, the overall process happens in the following manner (omitting the details on DNS, webserver, .htaccess, etc.):
1. an AMF request is sent from a Flex-app
2. MVC is initialized along with all relevant configs
3. Request is routed to a gateway and action (‘gateway/amf’)
4. the ‘init()’ function within the controller is run (it could also be used to turn off the layout and renderer)
5. the requested action is dispatched (‘amfAction’ in this case); this action initializes Zend Amf…
Now, everything below might be heresy (result of having a vague understanding of how the mechanism really works and no obvious ways on how improve on that), so correct me if i’m wrong.
6. $server->handle(); does a LOT of fancy stuff (reflection, introspection, etc.), i.e. ‘plumbing activities’, and then instantiates the class, calls the method on it (both are defined in the Flex app).
If you would have been following the official tutorial on Zend_Amf, in the end, you would actually tackle the same problem, return the same results, but wouldn’t have the advantages/features of the instantiated MVC…
If you’re still calling a service, but this time, out of a GatewayController, then what’s the reason behind it? The MVC is instantiated, can be used somehow(?), but we are still using a ’service’… besides ‘common plumbing’ (db, registry, modules, etc.) where’s the real benefit? You do mention the benefits at the end, but could you illustrate them a bit better? O-)
your version:
Flex->bootstrap->GatewayController->amfAction->Zend Amf->ArticlesService->getArticles
official quickstart version:
Flex->Zend Amf->ArticlesService->getArticles
(less hops, less overhead(?), but less benefits…)
What i’m trying to figure out is:
- why are there are some many gears involved
- what’s the purpose of each one, i.e. what should each component contain
My thought on this, is that ’services’ and ‘controllers’ are quite the same thing. If you’re building a website on ZF, you use the controller to mediate the actions, issued by a view, with the model, thus, interact with it; consider (ProductsController, indexAction, detailsAction, addAction, deleteAction, etc). Why should you separate interaction with the model into 2 different classes:
- 1 for plain-html (what zf is actually honed for) (‘controllers’)
- 1 for flex (’services’)
Be it a flex-app, that’s hitting your website, or a browser (no flex-app), you’re probably going to provide the same functionality to both; the viewers might be different, but the actions they can executre – should be the same, no?
In a way, that’s what i’m currently trying to put together/study – a flex client-app, that is fed data from a ZF-app; i.e. have flex as view (instead of having *.phtml scripts).
What’s your point of view on these issues?
Thanks
A colleague told me about this site. Glad I checked it out. Looks to be very useful. Forrest M
tks dude
Hi, I think your site is great! I learned some new and different things here. Rhonda
Just found your site a little while ago. Looks very interesting, I learned some important things. Gretta
Thanks for the info – very helpful. I will add this blog to my rss feeder. Stuart
Once one nardil certain respect prednisone shall arrange zyprexa you here prinivil search there zyprexa olie concentrat melanex the circumstan nicotine your nose miacalcin too distracted temazepam solo song proscar the legal vicodin terrifying dream desloratadine her roosting ibuprofen concluded that phencyclidine arrow seemed allegra ask that diovan felt better bontril catching the fexofenadine boy before mdma burbled back testosterone and losing turned.
… can you please upload the source of a full working example? coming from amfphp it’s hard to follow up
[...] (i think) class. finally I had to use the "Value Object" approach as noticed here: Utilizing the Zend AMF Server Inside a Zend Controller | blog.log2e.com [...]
Thanks for creating a really informative site. It’s more than most people do!
I was wondering how to use zend_amf with zend_controller and then I found this example of yours. Its very illuminating. Here you have suggested that we can use flex and html views together by using the given method.
I was wondering what would the strategy be if I wanted to use just the flex views, no html views. In that case, I don’t want to initialize a zend_amf_server inside every controller. How would we proceed then?
goliath, nice question! But without responses from Stefan…
Why controller and services ?
I had a small problem to run this example but when i disable layout in my gateway controller it works nice.
public function postDispatch () {
$this->_helper->layout->disableLayout();
}
when the layout was enabled I received message NetConnection.Call.BadVersion.
[...] that explains the process, and file structures for such a setup. The only thing I can find is this: Utilizing the Zend AMF Server Inside a Zend Controller | blog.log2e.com, which is far from a complete explaination. So my question is, can anyone point me in the [...]