作者:zccst
1,定义Service Provider
Yii依靠文档注解(doc comments)和类反射(class reflection)来识别哪个方法可以被远程调用,包括他们的参数和返回值。
我们定义服务器端的类,继承CController,如下面的例子所示:
在上面的例子中,我们定义了方法getPrice(使用@soap)作为一个可供远程调用的API,并且通过文档注解(doc comments)来指定参数和返回值的数据类型。
批注:后面会讲数据类型可分为基本数据类型和复合数据类型。
2,定义 Web Service Action
既然前面已知服务器端类是继承自CController,所以需要定义一个action,将服务暴露出去。继续上面的例子,我们仅仅在StockController增加如下代码:
至此,如果我们访问地址:http://hostname/path/to/index.php?r=stock/quote
我们将得到一个包含大量XML格式的内容,实际上它就是上面Web Service定义的WSDL。
批注:缺省情况下,CWebServiceAction默认当前controller就是Service Provider,这就是为什么上面直接在StockController里定义getPrice方法。
3,在客户端调用:(可以使用多种语言)
4,关于参数和返回值的数据类型
在实际应用中,参数和返回值的数据类型可分为基本数据类型和复合数据类型。
(1)基本类型数据
string , integer , float, boolean, date, time, datetime, array , object, mixed
(2)复合类型数据
如果是复合数据类型,则复合数据类型会通过类的形式表示,这时它的每一个public的数据项都需要使用@soap来进行文档注解(doc comments)。例如:
需要注意的是,如果想让client端收到复合类型数据,除了上面给出的类定义外,还需要在Service Provider的actions方法里增加配置项classMap=>array('outsource_header')。如下面所示:
此外,复合数据类型也可以使用数组(Array),通过[]向基本数据类型或复合数据类型的末尾追加的方式。例如,
该实例,调用getPosts方法时,将返回一个数组。
5,拦截远程方法调用(Intercepting Remote Method Invocation)
通过实现[IWebServiceProvider]接口,可以拦截所有方法,在[IWebServiceProvider::beforeWebMethod],这个provider可以获取当前CWebService实例,并通过CWebService::methodName来获取当前请求的方法名,它可以返回false,如果这个远程方法因某些原因(比如未经授权的访问)不应被调用。
如果您觉得本文的内容对您的学习有所帮助,您可以微信:
[img]http://dl2.iteye.com/upload/attachment/0109/0668/fb266dfa-95ca-3d09-b41e-5f04a19ba9a1.png[/img]
1,定义Service Provider
Yii依靠文档注解(doc comments)和类反射(class reflection)来识别哪个方法可以被远程调用,包括他们的参数和返回值。
我们定义服务器端的类,继承CController,如下面的例子所示:
class StockController extends CController{
/**
* @param String the symbol of the stock
* @return float the stock price
* @soap
*/
public function getPrice($symbol){
$prices = array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol]) ? $prices[$symbol] : 0;
// ... return stock price for $symbol
}
}
在上面的例子中,我们定义了方法getPrice(使用@soap)作为一个可供远程调用的API,并且通过文档注解(doc comments)来指定参数和返回值的数据类型。
批注:后面会讲数据类型可分为基本数据类型和复合数据类型。
2,定义 Web Service Action
既然前面已知服务器端类是继承自CController,所以需要定义一个action,将服务暴露出去。继续上面的例子,我们仅仅在StockController增加如下代码:
class StockController extends CController{
/*********** 增加 start **************/
public function actions(){
return array(
'quote'=>array(
'class'=>'CWebServiceAction'
),
);
}
/*********** 增加 end **************/
/**
* @param String the symbol of the stock
* @return float the stock price
* @soap
*/
public function getPrice($symbol){
$prices = array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol]) ? $prices[$symbol] : 0;
// ... return stock price for $symbol
}
}
至此,如果我们访问地址:http://hostname/path/to/index.php?r=stock/quote
我们将得到一个包含大量XML格式的内容,实际上它就是上面Web Service定义的WSDL。
批注:缺省情况下,CWebServiceAction默认当前controller就是Service Provider,这就是为什么上面直接在StockController里定义getPrice方法。
3,在客户端调用:(可以使用多种语言)
$client = new SoapClient('http://hostname/path/to/index.php?r=stock/quote');
echo $client->getPrice('GOOGLE');
//运行上面的脚本,通过Web或命令行方式,可以得出结果:350
4,关于参数和返回值的数据类型
在实际应用中,参数和返回值的数据类型可分为基本数据类型和复合数据类型。
(1)基本类型数据
string , integer , float, boolean, date, time, datetime, array , object, mixed
(2)复合类型数据
如果是复合数据类型,则复合数据类型会通过类的形式表示,这时它的每一个public的数据项都需要使用@soap来进行文档注解(doc comments)。例如:
class outsource_header {
/**
* @var string 访问密钥, a和b之间的访问控制
* @soap
*/
public $token;
/**
* @var integer 外包单号
* @soap
*/
public $id;
/**
* @var string 该外包单对应的机房名称
* @soap
*/
public $idc_name;
/**
* @var outsource_handler 处理人信息
* @soap
*/
public $handler; // 处理人信息
}
需要注意的是,如果想让client端收到复合类型数据,除了上面给出的类定义外,还需要在Service Provider的actions方法里增加配置项classMap=>array('outsource_header')。如下面所示:
class XXController extends CController{
public function actions(){
return array(
'service'=>array(
'class'=>'CWebServiceAction',
//增加 classMap 配置项
'classMap'=>array(
'outsource_header',
),
),
);
}
}
此外,复合数据类型也可以使用数组(Array),通过[]向基本数据类型或复合数据类型的末尾追加的方式。例如,
class PostController extends CController{
/**
* @return Post[] a list of posts
* @soap
*/
public function getPosts(){
return Post::model()->findAll();
}
}
class Post extends CActiveRecord{
/**
* @var integer post ID
* @soap
*/
public $id;
/**
* @var string post title
* @soap
*/
public $title;
public static function model($className=__CLASS__){
return parent::model($className);
}
}
该实例,调用getPosts方法时,将返回一个数组。
5,拦截远程方法调用(Intercepting Remote Method Invocation)
通过实现[IWebServiceProvider]接口,可以拦截所有方法,在[IWebServiceProvider::beforeWebMethod],这个provider可以获取当前CWebService实例,并通过CWebService::methodName来获取当前请求的方法名,它可以返回false,如果这个远程方法因某些原因(比如未经授权的访问)不应被调用。
如果您觉得本文的内容对您的学习有所帮助,您可以微信:
[img]http://dl2.iteye.com/upload/attachment/0109/0668/fb266dfa-95ca-3d09-b41e-5f04a19ba9a1.png[/img]