Zend AMF使用总结-服务端

Daniel Yang 撰写  

Zend Framework是php框架中的战斗机。各种功能应有尽有,没有的网上也能找到插件,helper, filter….而对于这样庞大的框架,最重要的就是配置了。

最近我作了一些尝试,在Zend Framework下使用AMF。现在把一些主要点共享给大家。

Tip 1,项目结构
这是刚接触ZF的同学们最头疼的。网上众说纷纭,其实很简单。
ZF发布的时候,bin目录下带有几个可运行的命令文件(包含各种系统了)。直接运行就可以了。
在这里,我是这样使用的(Mac Osx):

Yang:~ daniel$ ./zf.sh create project website

运行后,就会得到一个类似于这样的目录结构。
Screen shot 2009-09-28 at 5.43.30 PM

这里有个提示,尽管你可以把Zend文件夹(ZF的主要库文件)copy到刚才生成项目目录下的library里,我还是建议,一个服务器上维持一个ZF lib,这样升级起来容易。

现在可以把web服务器的服务地址只想我们生成目录bravo的public—这样,用户只能访问这个piblic目录中的文件,而程序文件是在application目录的,主要是安全。
好,打开浏览器,按照你配置的url来访问,应该能看到一个ZF生成的简单页面了。

Tip 2 index.php配置
ZF生成的public目录中,有一个index.php文件。这个文件是ZF应用的入口。这里的配置,主要是一些常量和ZF lib的位置。
比如我就是这样配置的:

<?php

// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

//这个是amf service的目录
define('SERVICES_PATH', APPLICATION_PATH . '/services');

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../../library'),
    get_include_path(),
)));

/** Zend_Application */
require_once '../../library/Zend/Application.php';  

// Create application, bootstrap, and run
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);

$application->bootstrap()
            ->run();

Tip 3 配置文件
ZF生成的application.ini文件位于/application/configs/下, 这个目录也经常会放其他配置文件,如route,i18n等。
配置文件一定不能乱了。我们按照dev, prod两种环境来配置。

[general]
;includePaths.library = APPLICATION_PATH "/../../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"

;database
resources.db.adapter = "PDO_MYSQL"
resources.db.isdefaulttableadapter = true
resources.db.params.driver_options.1002 = "SET NAMES UTF8;"

[development : general]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

resources.db.params.host = localhost
resources.db.params.username = bravo
resources.db.params.password = Z4wL6h8pA4KS5yDZ
resources.db.params.dbname = bravo

[production : general]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0

resources.db.params.host = 127.0.0.1
resources.db.params.username = test
resources.db.params.password = test
resources.db.params.dbname = test

Tip 4 AMF 服务的编写
这个很简单。
不需要继承任何类。

顺便说说gateway的提供。ZF中,gateway是一个controller。里面的内容比较常规:


<?php

	class GatewayController extends Zend_Controller_Action{

		public function init(){
			$this->getHelper('ViewRenderer')->setNoRender();
		}

		public function indexAction(){
			$server = new Zend_Amf_Server();
			$server->setSession('Bravo');
			Zend_Session::start(); //让amf服务支持session

			$server->addDirectory(SERVICES_PATH);//index.php中声明的,服务所在的目录
			//类的映射。
			$server->setClassMap('com.bravo.model.User', 'Brava_Model_User');

			echo($server->handle());
		}

	}

?>

Tip 5 Bootstrap
最主要的是初始化name space和数据库连接

	protected function _initAutoload(){
		$autoloader = new Zend_Application_Module_Autoloader(array(
            'namespace' => 'Bravo',
            'basePath'  => dirname(__FILE__),
        ));
        return $autoloader;
	}

	protected function _initExtraConfig(){
		$resource = $this->getPluginResource('db');
		$db = $resource->getDbAdapter();
		Zend_Registry::set('db',$db);

		Zend_Registry::set('configSection',APPLICATION_ENV);

	}

Tip 6 Value Object的传输
最让我头疼的。我现在的做法是,不使用ZF的Model, 直接用DbAdapter.
所以,我在Model里定义的其实是VO.

定义一个Base:

<?php

	class Bravo_Model_Base{

		public function setData($place){

			foreach($this as $key=>$value){
				if( array_key_exists($key, $place)){
					$this->$key = $place[$key];
				}
			}
		}

	}

?>

那么, User的Model就是:

<?php
	class Bravo_Model_User extends Bravo_Model_Base{
		public $_explicitType = 'com.bravo.model.User';

		public $id;
		public $email;
		public $nickname;
		public $passwd;
		public $avatar;

	}
?>

在从数据库中取得数据后:

		public function getPlace($i){
			$db = Zend_Registry::get('db');

			$select = $db->select();

			$select->from('place')
			->where('place.id='. $i);

			$p = $db->fetchRow($select);

			$pvo = new Bravo_Model_Place();
                        //就可以这样了
			$pvo->setData($p);
			return $pvo;
		}

下一篇我们说客户端-应该是很简单了。


3 条评论

  1. relenovo
    发表了 2009年12月14日 在 7:42 上午 | 永久链接 |

    你好 最近在研究amf 和flex 的通信
    我一开始 在Value Object的传输地方用的是
    DTO 可以通信, 我也试着用你这里提供的方法,一直无法成功。能发一份这篇文章里的源码给我吗? 不胜感激 relenovo#gmail.com

    • Daniel Yang
      发表了 2009年12月14日 在 1:34 下午 | 永久链接 |

      你好。
      文中所举例,使用的是Zend Framework的AMF模块。如果你也是用这个模块,可以把错误信息贴上来。
      代码我现在已经没有了。

发表评论

你必须在 登录 后才能发表评论.