`
lonestone
  • 浏览: 92922 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Yii Framework 整合Extjs Direct实现RPC的方法

阅读更多
    这些天由于公司需要开发一个类似CRM的会员管理系统,我的技术选型为 Extjs+Yii+Mysql实现,发现Extjs3.x后推出了Direct组件,可以很方便的将服务器端的方法暴露给客户端调用,非常方便,于是就有了整合Yii框架的想法。

    说干就干,花了一天时间进行研究、实现代码,Yii的组件架构和OOP的特性,让我比较方便的就实现了这个目标:兼容RPC批量调用和正常的MVC页面流程。

    具体实现了几个类:
  • ExtApplication,是CApplication的继承类,覆盖了ProcessRequest方法,区分普通页面action和RPC调用action等。
  • Controller,是CController的继承类,覆盖若干方法以调用ExtAction
  • ExtAction,是CAction的继承类,用于执行RPC方法
  • ApiAction,也是CAction的继承类,用于暴露服务器端方法
  • ExtDirect_API和ExtDirect_CacheProvider这两个类是direct自带的类,稍作修改。


将以上类文件放入项目的protected/components下即可,然后修改入口文件index.php为:

<?php

// change the following paths if necessary
$yii=dirname(__FILE__).'/../yii-trunk/framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';

// remove the following lines when in production mode
defined('YII_DEBUG') or define('YII_DEBUG',true);
// specify how many levels of call stack should be shown in each log message
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

require_once($yii);
require(dirname(__FILE__).'/protected/components/ExtApplication.php');
Yii::createApplication('ExtApplication',$config)->run();



然后修改 protected/views/layouts/main.php,加入extjs引用和代码:
<link rel="stylesheet" type="text/css" href="/ext3/resources/css/ext-all.css" />
	<link rel="stylesheet" type="text/css" href="/css/main.css" />
	
	<script type="text/javascript" src="/ext3/adapter/ext/ext-base-debug.js"></script>
	<script type="text/javascript" src="/ext3/ext-all-debug.js"></script>
	<script type="text/javascript" src="/ext3/src/locale/ext-lang-zh_CN.js"></script>
	<script src="<?php echo $this->createUrl('/site/api') ?>"></script>
	<script type="text/javascript">
		Ext.BLANK_IMAGE_URL = '/ext3/resources/images/default/s.gif';
		var mk;
		Ext.onReady(function(){						
		    // Notice that Direct requests will batch together if they occur
		    // within the enableBuffer delay period (in milliseconds).
		    // Slow the buffering down from the default of 10ms to 100ms
		    Ext.app.REMOTING_API.enableBuffer = 100;
		    Ext.Direct.addProvider(Ext.app.REMOTING_API);
		    // provide feedback for any errors
		    Ext.QuickTips.init();
			// turn on validation errors beside the field globally
		    Ext.form.Field.prototype.msgTarget = 'side';
		});
</script>


这段代码“<script src="<?php echo $this->createUrl('/site/api') ?>"></script>”就是调用了接口页面,得到了服务器端暴露的方法列表,如:
Ext.ns('Ext.app'); Ext.app.REMOTING_API = {"url":"\/index.php","type":"remoting","actions":{"Site":[{"name":"DoLogin","len":1,"formHandler":true},{"name":"Logout","len":0},{"name":"updateBasicInfo","len":1,"formHandler":true},{"name":"getBasicInfo","len":2},{"name":"GetPhoneInfo","len":0},{"name":"getLocationInfo","len":1}],"Test":[{"name":"Index","len":0}]}};


然后这句:“Ext.Direct.addProvider(Ext.app.REMOTING_API);“就是向extjs注册了rpc的api。

这样准备工作就完成了。

接着添加apiAction的定义到 SiteController.php中:
	/**
	 * Declares class-based actions.
	 */
	public function actions()
	{
		return array(
            'api'=>array(
                'class'=>'ApiAction',
            ),
		);
	}

然后在Controllers中定义普通action和rpc方法:

	public function actionLogin()
	{
		$this->render('login');
	}

	/**
	 * @remotable
	 * @formHandler
	 */
	public function actionDoLogin($formPacket)
	{
		$model=new LoginForm;

		// collect user input data
		if(isset($formPacket['username']))
		{
			$model->username = $formPacket['username'];
			$model->password = $formPacket['password'];
			
			// validate user input and redirect to the previous page if valid
			if($model->validate() && $model->login())
				$output['success'] = true;
			else
			{
				$output['success'] = false;
				$output['errors'] = $model->errors;
			}
			return $output;
		}
	}


注意上面的 “
/**
* @remotable
* @formHandler
*/”
注释,表示DoLogin这个方法是可以远程调用的,且是表单处理方法,这里的备注可以在反射的时候用到。而且可以发现普通页面action和RPC的action的写法上的区别:一个是没有参数的,render页面或者直接输出内容的;一个是有参数的,然后有返回值的。

actionLogin对应的视图文件中就可以调用DoLogin方法来登录用户了:
var indexUrl = '<?php echo $this->createUrl('index') ?>';

Ext.onReady(function(){
	function login(){
		if(form.getForm().isValid()){
			form.getForm().submit({
				waitMsg: '正在登录,请稍候...',
				waitTitle:'登录中', 
				success: function(form,action){
					loginwin.hide();
					window.location = indexUrl;
				}
			});
		}
	}
	var form = new Ext.form.FormPanel({
        baseCls: 'x-plain',
        labelWidth: 55,
        defaultType: 'textfield',
		title: '<div style="padding:10px;text-align:center;font-size:22px;  border-bottom:silver solid 1px; margin-bottom:5px;">会员管理系统</div>',
		api: {submit: Site.DoLogin },
        items: [{
            fieldLabel: '用户名',
            name: 'username',
			allowBlank: false,
			blankText: "请输入您的用户名",
            anchor:'92%',
            listeners: {
            	specialkey : function(field, e) {
                    if (e.getKey() == Ext.EventObject.ENTER) {
                        login();
                    }
                }
            }
        },{
			inputType: "password",
            fieldLabel: '密 码',	
			allowBlank: false,
			blankText: "请输入您的密码",
            name: 'password',
            anchor: '92%' ,
            listeners: {
            	specialkey : function(field, e) {
                    if (e.getKey() == Ext.EventObject.ENTER) {
                        login();
                    }
                }
            }
        }],
		buttons: [{
			text: '登录',
			handler: login
			},
			{text: '重设', handler: function(){form.getForm().reset();}}
		],
		buttonAlign:'center'
    });
	
	var loginwin = new Ext.Window({
			title: "管理登录",
			width: 300,
			height: 180,
			modal: true,
			draggable: false,
			closable: false,
			tools: [{id: "help", handler: function(){Ext.Msg.alert('帮助','输入您的用户名和密码登录系统。')}}],
			layout: 'fit',
			plain:true,
			bodyStyle:'padding:5px;',
			items: form,
			resizable: false
		});
	loginwin.show();
});


注意FormPanel中的 “api: {submit: Site.DoLogin },”,这样表单的处理请求就自动被发送到了SiteController的actionDoLogin方法,其处理结果也自动返回给客户端了,是不是很方便?

以上涉及到的完整代码已附上,需要的朋友拿去吧,有问题别忘了反馈,一起改进完善。

效果截图:





以上截图表现的是如何处理表单,下面说说如何调用服务器端其他方法,如我们在SiteController中定义:
    /**
    * @remotable
    * put your comment there...
    * This method configured with len=2, so 2 arguments will be sent
    * in the order according to the client side specified paramOrder
    * @param Number $userId
    * @param String $foo
    * @return Array response packet
    */
    function actiongetBasicInfo($userId, $foo){
        return array(
            'success'=>true,
            'data'=>array(
                'foo'=>$foo,
                'name'=>'Aaron Conran',
                'company'=>'Ext JS, LLC',
                'email'=>'aaron@extjs.com'
             )
        );
    }

    /**
    * Handler for client side form sumbit
    * @formHandler
    * @remotable
    *
    * @param Array $formPacket Collection of form items along with direct data
    * @return Array response packet
    * 
    */
    function actionUpdateBasicInfo($formPacket){
        $response = array();
        $email = $formPacket['email'];
        if ($email == 'aaron@extjs.com') {
            $success = false;
            $response['errors'] = array(
                'email'=>'already taken'
            );
        } else {
            $success = true;
        }
        $response['success'] = $success;
        // return form packet for demonstration/testing purposes
        $response['debug_formPacket'] = $formPacket;
        return $response;
    }



接下来就可以在客户端js中这么调用:
var basicInfo = new Ext.form.FormPanel({
        // configs for FormPanel
        title: 'Basic Information',
        border: false,
        padding: 10,
        buttons:[{
            text: 'Submit',
            handler: function(){
                basicInfo.getForm().submit({
                    params: {
                        foo: 'bar',
                        uid: 34
                    }
                });
            }
        }],

        // configs apply to child items
        defaults: {anchor: '-20'}, // provide some room on right for validation errors
        defaultType: 'textfield',
        items: [{
            fieldLabel: 'Name',
            name: 'name'
        },{
            fieldLabel: 'Email',
            msgTarget: 'side',
            name: 'email'
        },{
            fieldLabel: 'Company',
            name: 'company'
        }],

        // configs for BasicForm
        api: {
            // The server-side method to call for load() requests
            load: Site.getBasicInfo,
            // The server-side must mark the submit handler as a 'formHandler'
            submit: Site.UpdateBasicInfo
        },
        // specify the order for the passed params
        paramOrder: ['uid', 'foo']
    });


这样一来,这个表单的初始数据加载和提交,就都是RPC自动调用了,是不是很赞?呵呵

  • 大小: 72.1 KB
  • 大小: 71.2 KB
5
0
分享到:
评论
4 楼 winsonkong05 2013-09-15  
博主您好,我嘗試webapp "c:\wamp\www\yii\newyii" 然後依照以上的形式加入進去可是不成功,是否在 (入口文件index.php)出問題呢?

如果全部照以上的形式我將會是以下的情況:


然後我將入口文件index.php 回复原本文件

    <?php

    // change the following paths if necessary
    $yii=dirname(__FILE__).'/../yii/framework/yii.php';
    $config=dirname(__FILE__).'/protected/config/main.php';

    // remove the following lines when in production mode
    defined('YII_DEBUG') or define('YII_DEBUG',true);
    // specify how many levels of call stack should be shown in each log message
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

    require_once($yii);
    Yii::createWebApplication($config)->run();
    //require(dirname(__FILE__).'/protected/components/ExtApplication.php'); 
    //Yii::createApplication('ExtApplication',$config)->run(); 


就會變成以下:
3 楼 yiqing 2013-01-22  
有github账号没 可以相互交流哈
2 楼 xingkid 2012-12-06  
xingkid 写道
博主很厉害,要向您学习~~

博主您好。能否发一个完整版的程序参考一下呢?我根据您上面说的折腾了很久还是不行,有可能是版本问题~~我的邮箱是xingkid@163.com
1 楼 xingkid 2012-12-06  
博主很厉害,要向您学习~~

相关推荐

    Yii Framework API手册

    Yii Framework API手册是针对开发者的一款详尽参考资料,它包含了Yii框架的所有核心组件、类库以及扩展的使用方法和接口信息。Yii是一个高性能、基于组件的PHP框架,用于开发Web 2.0应用。API(Application ...

    yii framework框架 + yii app模板(基本、高级).zip

    yii framework框架 + yii app模板(基本、高级)

    Yii Framework 2.0 权威指南 pdf格式 中文高清离线版 有书签

    ### Yii Framework 2.0 权威指南知识点详解 #### 一、Yii框架概述 - **定义**:Yii是一款高效能、基于组件的PHP框架,主要用于加速现代Web应用的开发进程。其名称“Yii”(发音类似于“易”)在中国文化中有“极致...

    Yii Framework v2.0.8.rar

    Yii Framework是一个高性能的PHP5的web应用程序开发框架。通过一个简单的命令行工具 yiic 可以快速创建一个web应用程序的代码框架,开发者可以在生成的代码框架基础上添加业务逻辑,以快速完成应用程序的开发。

    Yii Framework 1.1.6

    Yii Framework 1.1.6 是一个高效、可扩展的 PHP 开发框架,它为开发者提供了构建大型Web应用所需的工具和功能。这个版本是Yii框架的稳定版本之一,发布于2011年,旨在提高开发效率并降低维护成本。 在Yii 1.1.6中,...

    yii framework 中文完全手册

    该手册的"yii-api.chm"文件很可能是Yii的API参考文档,包含框架内所有类、方法和属性的详细说明。API文档对于开发者来说是至关重要的,因为它允许他们快速查找并理解框架提供的各种功能。 在Yii框架中,核心概念...

    Yii Framework v1.1.19

    Yii是一个高性能的PHP5的web应用程序开发框架。通过一个简单的命令行工具 yiic 可以快速创建一个web应用程序的代码框架,开发者可以在生成的代码框架基础上添加业务逻辑,以快速完成应用程序的开发。

    yii framework 1.1.14 chm文档

    yii framework 1.1.14 chm文档,从官方html文档编译,展示效果很好.

    YII Framework框架教程之使用YIIC快速创建YII应用详解

    主要介绍了YII Framework框架教程之使用YIIC快速创建YII应用的方法,详细分析说明了YII Framework框架使用YIIC命令行创建应用的相关技巧与注意事项,需要的朋友可以参考下

    Yii Framework v1.10 Class Reference

    Yii Framework 1.10的API手册

    Yii Framework框架中事件和行为的区别及应用实例分析

    主要介绍了Yii Framework框架中事件和行为的区别及应用,结合实例形式分析了Yii Framework框架中事件和行为的相关概念、原理、区别及应用操作技巧,需要的朋友可以参考下

    基于Yii2和ExtJs的RBAC权限控制设计源码

    本Yii2 ExtJs5 RBAC项目基于PHP开发,包含83个文件,包括PHP源代码、PNG图片、Markdown文档、SQL脚本、GIT忽略...系统实现了Yii2框架下的ExtJs5前端界面和RBAC权限控制功能,界面友好,功能完善,适合用于权限管理。

    yii framework 中文手册

    yii framework 最全最新的中文手册

    Yii Framework 2.0 Where条件拼接 pdf

    Yii Framework 2.0通过Active Record模式和强大的查询构建器为开发者提供了一套完善的数据库操作解决方案,通过where条件拼接等高级查询功能极大地简化了复杂查询的构建过程,使得开发者能够更专注于业务逻辑的实现...

    PhpStorm6 创建yii framework项目

    文档中提到的路径为`C:\Apache2.2\htdocs\yii\framework&gt;`,这是假设我们已经将Apache服务器安装在了C盘的Apache2.2目录下,并且Yii框架也放置在了对应的htdocs文件夹中。通过输入`cd`命令加上目录路径,即可切换到...

    yiiframework 中文 手册

    开发者可以通过 Yii 的组件系统轻松集成这些扩展,实现快速开发。 十一、调试与性能优化 Yii 自带了调试工具条和性能分析工具,可以帮助开发者找到性能瓶颈,进行优化。此外,Yii 还支持配置生产环境和开发环境,以...

    YiiFramework

    - 这个文件可能包含了Yii框架的安装指南、基本使用方法、注意事项等重要信息,对于初学者来说是非常宝贵的资源。 7. **文件"yii-1.1.14-rc.2d9982"**: - 文件名中的"1.1.14-rc"可能表示这是Yii 1.1.x版本的一个...

    PHP实例开发源码-Yii Framework php框架.zip

    PHP实例开发源码—Yii Framework php框架.zip PHP实例开发源码—Yii Framework php框架.zip PHP实例开发源码—Yii Framework php框架.zip

    Yii Framework v1.1.10类参考中文手册

    Yii Framework v1.1.10类参考中文手册

Global site tag (gtag.js) - Google Analytics