The 1.7 release of the Zend Framework includes the new Zend_Amf package which provides a gateway server implementation for AMF remoting. By the time of writing this article, there are not many resources available yet (a good starting point is here), and the few tutorials mostly guide you through the process of setting up the bootstrap file and establishing a MySQL database connection by using mysql_connect() directly in the service classes.
I would like to introduce a Zend AMF server setup that makes use of some of Zend’s best practices like configuration files, database adapters and models. If you are a Flash/Flex developer coming from an AMFPHP background and have never worked with the Zend framework before, you may easily feel overwhelmed by the framework’s complexity. This article is not meant to present a thourough overview of all Zend features you could possibly utilize in your Flex/Flash development work, but it might motivate you to dive deeper into the framework’s features.
The Folder Structure
First of all, even if I only need the AMF server from the Zend framework I set up my server directories like I would do with any other Zend/PHP application. If you already have some experience with the Zend framework this folder structure probably looks familiar to you:
This is a rudimentary folder structure, of course, because a typical Zend application with an HTML frontend has additional folders for controllers, views, layouts, forms, plugins, helpers, etc. But the basic setup is the same: We have an application and a library folder that are outside the web server’s root directory (public). The Zend framework packages are inside the library folder, and below the application folder there are a config and a models folder. For the special purpose of the AMF gateway, I added a services folder which is supposed to contain all service class files.
The Database and the Configuration File
Let’s assume we are working on an application that needs to manage user accounts. A very basic table would look like this:
-
id int(11) NOT NULL AUTO_INCREMENT,
-
username varchar(32) NOT NULL DEFAULT '',
-
password varchar(32) NOT NULL DEFAULT '',
-
email varchar(255) NOT NULL DEFAULT '',
-
firstname varchar(50) NOT NULL DEFAULT '',
-
lastname varchar(50) NOT NULL DEFAULT '',
-
PRIMARY KEY (id)
-
);
The database credentials are stored in an INI file (app.ini). In this example there are configuration data for both a production system and a development system. Because the development system configuration data are very similar to those for production, the development section inherits from the production section:
-
[production]
-
database.adapter = PDO_MYSQL
-
database.params.host = localhost
-
database.params.dbname = prod_dbname
-
database.params.username = dbusername
-
database.params.password = dbpassword
-
-
[development : production]
-
database.params.dbname = dev_dbname
This configuration file also allows you to easily change the database adapter (if needed).
The Bootstrap File
Let’s take a look at the bootstrap file (index.php):
-
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application/'));
-
-
set_include_path(
-
get_include_path()
-
. PATH_SEPARATOR . APPLICATION_PATH . '/../library/'
-
. PATH_SEPARATOR . APPLICATION_PATH . '/services/'
-
. PATH_SEPARATOR . APPLICATION_PATH . '/models/'
-
);
-
-
require_once 'Zend/Loader.php';
-
Zend_Loader::registerAutoload();
-
-
$server = new Zend_Amf_Server();
-
$server->setClass('UsersService');
-
$server->setClassMap('UserVO','User');
-
$server->setProduction(false);
-
-
echo($server->handle());
This bootstrap file is very similar to the standard bootstrap files you find in other tutorials or in the Zend Reference Guide. It adds some include paths, initializes the Zend autoload feature for classes, and sets up the AMF server.
The Service Classes
Utilizing the Zend_Config and Zend_Db packages, we set up the database connection in a base service class that the actual service classes inherit from. In line 7 in the listing below we provide a default database adapter for all subsequent instances of Zend_Db_Table objects in our application (for more information, please refer to the Zend_Db chapter in the Reference Guide). This way we keep the logic of creating a database connection in one central place.
-
class BaseService
-
{
-
public function __construct()
-
{
-
$configuration = new Zend_Config_Ini(APPLICATION_PATH . '/config/app.ini', 'development');
-
$dbAdapter = Zend_Db::factory($configuration->database);
-
Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);
-
}
-
}
The only real service class in our example is UsersService which extends BaseService and invokes the parent class’s constructor by calling parent::__construct();. For the sake of simplicity it contains only one method (getUsers()):
-
class UsersService extends BaseService
-
{
-
public function __construct()
-
{
-
parent::__construct();
-
}
-
-
public function getUsers()
-
{
-
$usersArray = array();
-
-
$table = new Users();
-
$result = $table->fetchAll();
-
-
foreach($result as $row)
-
{
-
$user = new User();
-
$user->id = $row->id;
-
$user->username = $row->username;
-
$user->email = $row->email;
-
$user->firstname = $row->firstname;
-
$user->lastname = $row->lastname;
-
array_push($usersArray, $user);
-
}
-
return $usersArray;
-
}
-
}
You may wonder what the Users class does (line 12 in the above code listing). Here’s the answer: It’s a model class.
The Model Class
Models are another important concept of the Zend framework. Although the classical MVC pattern doesn’t apply in the context of the Zend AMF server, I stick to this concept here because it may come in handy sometimes. Imagine an application that is supposed to support both a Flash and an HTML interface. By following the framework’s MVC guidelines, we are able to build an application engine that uses the same model classes for both the AMF server gateway and the MVC-based HTML frontend.
The class Users is located in the models folder. It extends Zend_Db_Table and holds the name of the corresponding database table:
-
class Users extends Zend_Db_Table
-
{
-
protected $_name = 'users';
-
}
Remember that we provided an application-wide database adapter for all Zend_Db_Table objects (see line 7 in the BaseService class). By creating an instance of Users (which inherits all methods from Zend_Db_Table) we are able to use fetchAll() to retrieve all rows from the table users.
The Value Object Class
The class User (see line 17 in the UsersService code listing) is a helper class that allows us to send an array of typed objects to the Flash player. This is especially useful in Flex-based applications where you want to use value objects for data-binding, for example. By the way, the class User doesn’t look any different than a VO class in an AMFPHP context.
-
class User {
-
public $id = 0;
-
public $username = '';
-
public $password = '';
-
public $firstname = '';
-
public $lastnamne = '';
-
public $email = '';
-
}
By calling $server->setClassMap('UserVO','User'); inside the bootstrap file, the User objects are mapped to UserVO.
I skip the Flex/Flash part here because this topic is well covered in other tutorials. But I hope you caught a glimpse of how you can leverage the power of other components inside the Zend framework – even if you are only interested in the Zend AMF server. There are more scenarios where the Zend framework may come in handy for a Flash/Flex developer (for example, think of generating PDF files on the fly by using Zend_Pdf).

This is great! Thanks for taking the time to post this.
Thanks for doing this… i wish you the best for endeavours.
Thanks for posting this. I added it to my resources list. Take care.
Great content! I just came across your blog and actually read your posts! I wish you would post more often. It is hard to find good informative blog like yours! Thanks for the information. – Versa
I was looking for blog ideas to add to my site and I found your site. I like what you have done and will be sure to check back for updates.
Nice post. Thank you for the info. Keep it up.
This has been very helpful for me. Thanks a ton!
I am interested in the very thing you suggested above. That is having two different front ends (HTML and Flex) for the application. My next task is understanding how to utilize the acl, auth, and sessions components for the Flex front end.
Do you have any suggestions for that?
Thnx for the info, this is just what I needed.
I just added another post on how to set up a Zend AMF server inside a regular Zend controller. I think this is the best way of keeping the bootstrap file free from any AMF server-related code. Also, you gain a lot more flexibility when building applications with both HTML and Flex interfaces.
Hi Stefan, thankyou for the great article. I’ve spent a week trying to find decent info on how to setup Zend_AMF properly and this is the most detailed tute I could find.
I do have a couple of questions however. It’s important to note that I am using the ZF MVC framework too.
1. When I follow your directions, almost exactly, and reload my root page, I get a popup that says: “You have chosen to open: [blank] application/x-amf”. I can’t actually refresh any page. I have downloaded the page and the contents are “Zend Amf Endpoint” followed by all the HTML in my layout/layout.phtml file. This problem is resolved by commenting out the line in the bootstrap “echo($server->handle());”. I also assume I am meant to turn the view off somewhere for this, but I have no idea where.
2. You instantiate your Zend_Amf_Server in the bootstrap for your User table. But what do you do if you have other tables and services to setup? Do you just add more setClass and setClassMap method calls to the same $server object?
Thanks for any help you can give. AMF has been the most difficult concept for me to get my head around with ZF. (namely, how to get it to work with the MVC system)
Regards
Aaron
Zend_AMF does set things up nicely for Flex, but it’s still particular to PHP.
There’s a new web-based platform called X2O that rids the need of server-side programming altogether (http://www.x2oframework.com) for Flex and Flash CS4 apps. It lets you create data models over the Web and then generates a content management system, web services, and integrated AS3 SWC library (you don’t even have to configure any services…it’s all built into the SWC). Seamless….
This allows you to build database-driven Flex/Flash apps without any server-side programming or setup.
@Ka Wai: Thanks for the link. However, I guess that most clients want to store their data on their own server.
In your BaseService class’ constructor, would it be possible to do some validation and then if that validation fails abort the call to the getUsers() function?
something like this, in the constructor:
if ($valid == FALSE)
{
return false;
exit;
}
It is for login/authentication purposes
@Lasse: For authentication with Zend AMF please take a look at this tutorial: http://www.keithcraigo.com/archives/66
I have looked at that tutorial, however it doesn’t provide a way to authenticate further calls to services… At least not that I can see. I’d like to abort the service call if authentication fails, and so authentication should be checked on every call, preferably in the constructor. The only thing I can’t figure out is how to abort the service call if authentication fails in the constructor..
Very nice post. Thank you!