YII框架之soap协议的配置跟使用(Webservice)

Yii依靠文档注解(doc comments)和类反射(class reflection)来识别哪个方法可以被远程调用,包括他们的参数和返回值,但目前只能返回字符串,不能返回数组,若返回数组,则为"array";故我将返回值转换为json字符串再返回.


1. 定义Service Provider,服务器端文件代码,WebServerController.php

<?php
/******************************
 * @author sara zhou
* create time 2014-06-25 16:00:00
* YII框架API接口端的server (基于Webservice的接口服务器端)
* 注意php.ini开启soap扩展:extension=php_soap.dll
*******************************
*/
class WebServerController extends CController{
	
	/**
	 * @var array error
	 * @soap
	 */
	public $error=array(
			'0000'=>'操作成功',
			'0001'=>'操作失败',
			'0002'=>'参数param错误',
			'1001'=>'用户不存在',
	);
	
	public function actions()
	{
		return array(
				'approval'=>array(
						'class'=>'CWebServiceAction',
						'classMap'=>array(//classMap其实只要是对应的Model就行,比如这里的ApiUser
								'ApiUser',  
						),
						
				),
		);
	}
	
	/**
	 * @desc get_user_info()获取用户信息,代码注释里包含 * @soap,则 此方法可通过soap访问到
	 * @param array
	 * @return array the ApiUser info 也必须和Model名称一致
	 * @soap
	 */
	public function get_user_info($param_arr){
		$param_arr=CJSON::decode($param_arr);
		$param['user_name']=htmlspecialchars(@$param_arr['user_name']);
		$param['request_id']=intval(@$param_arr['request_id']);
		
		//添加API访问日志信息
		$apiLog=new ApiLog1();
		$log_id=$apiLog->insert_api_log($param['request_id'], CJSON::encode($param));

		$res=array('user_name'=>$param['user_name'],'user_email'=>$param['user_email']);
		//验证相关参数是否符合要求
		if (empty($param['user_name'])) {
			$res['response_time']=date("YmdHis");
			$res['error_code']='0002';
			$res['error_msg']=str_replace('param','user_name',$this->error['0002']);
			//更新API访问日志信息
			$apiLog->update_api_log($log_id, CJSON::encode($res),@$res['response_time'], @$res['error_code'],$res['error_msg']);
			return CJSON::encode($res);
		}		
		
		if ($param['request_id']<=0) {
			$res['response_time']=date("YmdHis");
			$res['error_code']='0002';
			$res['error_msg']=str_replace('param','request_id',$this->error['0002']);
			//更新API访问日志信息
			$apiLog->update_api_log($log_id, @$res,@$res['response_time'], @$res['error_code'],$res['error_msg']);
			return $res;
		}
		$user=new User();
		$user_info=$user->getUserInfo($param['user_name']);
		
		if ($user_info)
		{
			$res['error_code']="1003";
		}
		else 
		{
			$res['error_code']="0000";
		}
		$res['response_time']=date("YmdHis");
		$res['error_msg']=$this->error[$res['error_code']];
		
		//更新API访问日志信息
		$apiLog->update_api_log($log_id, @$res,@$res['response_time'], @$res['error_code'],$res['error_msg']);
		
		return $res; 

	}

	/*
	 * 代码注释里不包含 * @soap,则无法通过soap方式访问
	 */
	public function test($param_arr){
		$arr =  array(
					'user_id'=>$param_arr['user_id'],
				    'request_id'=>$param_arr['user_id'],//'请求号',
				    'request_time'=>$param_arr['user_id'],//'请求时间'
                );
		return true;
	}

}


保存WebServerController.php文件,浏览器输入地址:http://localhost/api/webServer/approval,将得到一个包含大量XML格式的内容,实际上他就是上面Web Service定义的WSDL.XML内容中,可以看到服务器API接口中开放的方法


2.客户端调用(此实例为php客户端调用实例,可使用其他语言)


<?php
/******************************
 * @author sara zhou
* create time 2014-06-25 16:00:00
* YII框架API接口端的客户端调用实例 (基于Webservice的接口服务器端)
* 注意php.ini开启soap扩展:extension=php_soap.dll
*******************************
*/
class ClientController extends CController
{
	public function actionGetUserInfo(){
		//制定服务器访问地址
		$client = new SoapClient('http://localhost/api/webServer/approval');
		
		//调用服务器接口方法 get_user_info()获取用户信息;由于接口是传json数组,故这里以传json格式传递
		$res= $client->get_user_info('{"user_ame":"123","request_id":"23123"}');
		var_dump($res);
	}
}
?>




3.用户模型层文件 User.php => model

 

<?php
/**
 * 用户模型
 *
 * @author Sara Zhou 
 */
 
class User extends CActiveRecord
{
	//Model里要公开的变量,需要用下面的形式标明
	
	/** 
	 * @var integer    user_id
	 * @soap
	 */
	public $id;
	
	/**
	 * @var string     post title
	 * @soap
	 */
	public $title;
	
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	public function tableName()
	{
		return 'user';
	}
	
	public static function getUserInfo($user_name){
	    return User::model()->findbyPk($user_name);
	}
 
}
model里要公开的变量,需要用下面的形式标明

/** 
* @var integer    user_id
* @soap
*/
public $id;


4.请求模型层的日志API文件,ApiLog.php  => model

<?php
/**
 * 
 * @author Sara zhou
 * @create 2014-06-11
 * @desc:主要用于记录API访问日志
 */
class ApiLog extends CActiveRecord
{
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}
	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return 'api_log';
	}
	
	/*
	 * insert_api_log()记录API请求日志
	* @param $require_no
	* @param $require_param
	*/
	public function insert_api_log($require_no,$require_param){
		//只做插入
		$binsd = array(
				'require_no'=> $require_no,
				'require_url'=> $_SERVER['HTTP_HOST'] .$_SERVER['REQUEST_URI'],
				'require_param'=> $require_param,
				'require_time'=> date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']),
				'require_method'=> $_SERVER['REQUEST_METHOD'],
				'server_protocol'=> $_SERVER['SERVER_PROTOCOL'],
				'create_time'=> date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']),
		);
		if ($_SERVER["HTTP_X_FORWARDED_FOR"]=="")
		{
			$bind['require_ip']=$_SERVER['REMOTE_ADDR'] .':'.$_SERVER['REMOTE_PORT'];
		}
		else
			$bind['require_ip']=$_SERVER["HTTP_X_FORWARDED_FOR"].':'.$_SERVER['REMOTE_PORT'];
	
		$this->setAttributes($binsd, false);
		$this->save();
		return $this->attributes['id'];
	}

	/*
	 * update_api_log()更新API请求日志
	* @param $log_id
	* @param $response_param
	* @param $response_time
	* @param $error_code
	* @param $error_msg
	*/
	public function update_api_log($log_id,$response_param,$response_time,$error_code,$error_msg){
		//只做更新
		$sql = "UPDATE api_log set response_param=:response_param,response_time=:response_time,error_code=:error_code,error_msg=:error_msg where id=:id";
		$command=Yii::app()->db->createCommand($sql);
		$bind = array(
				'id'=> $log_id,
				'response_param'=> $response_param,
				'response_time'=> $response_time,
				'error_code'=> $error_code,
				'error_msg'=> $error_msg,
		);
		return $command->execute($bind);
	}
	
}


5.拦截远程方法调用(Intercepting Remote Method Invocation) 

通过实现[IWebServiceProvider]接口,可以拦截所有方法,在[IWebServiceProvider::beforeWebMethod],这个provider可以获取当前CWebService实例,并通过CWebService::methodName来获取当前请求的方法名,它可以返回false,如果这个远程方法因某些原因(比如未经授权的访问)不应被调用


6.注意:
a. 服务器要打开soap功能,在phpinfo里搜soap,如果已经打开了的话有个大标题就是SOAP
b. classMap其实只要是对应的Model就行,比如这里的ApiUser。
c. 代码注释里* @return ApiUser[] the apiUser records ApiUser[]也必须和Model名称一致
d. 代码注释里* @soap 这个也不能少,不然无法通过soap方式访问,想不到注释里还有这么多文章
e. 如果controller里有accessRules的话,得设定访客就可以访问getPredictions()
f. Model里要公开的变量,需要用下面的形式标明:

/**
     * @var integer UID of this record
     * @soap
     */
    public $uid;

YII框架之soap协议的配置跟使用(Webservice),古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。