看了一下ZF手册中的关于Zend_Soap的说明,感觉很晕,不知所云,是不是个人理解有问题,那就不得而知了,总觉得没有动手做过的就算看了再多文档也不顶事,于是做了一个关于复杂对象传输的例子,对于那些简单对字符窜做的东西基本不实用,所以直接做个可以用到项目中的。
对于复杂对象的传输这里决不仅指的是数组,还有自定义对象(stdclass),有人说php数组可以解决复杂数据结构的问题用自定义对象不是多此一举,原则上是这样,但是如果涉及到多语言通信的话,问题就会暴露出来,这个我们先放一下,在说完这个实例后再谈。
Zend_Soap中的自定义对象的关键点在于annotation,annotation在java中用的较多,不知道php中是不是这么叫,总知是一个参数类型的说明,看例子。
<?php
class Role{
/**
* @return string
*/
public function getDesc() {
return $this->desc;
}
/**
* @return string
*/
public function getParentid() {
return $this->parentid;
}
/**
* @return string
*/
public function getRoleid() {
return $this->roleid;
}
/**
* @return string
*/
public function getRolename() {
return $this->rolename;
}
/**
* @param string $desc
*/
public function setDesc($desc) {
$this->desc = $desc;
}
/**
* @param string $parentid
*/
public function setParentid($parentid) {
$this->parentid = $parentid;
}
/**
* @param string $roleid
*/
public function setRoleid($roleid) {
$this->roleid = $roleid;
}
/**
* @param string $rolename
*/
public function setRolename($rolename) {
$this->rolename = $rolename;
}
/**
* @var string
*/
public $roleid;
/**
* @var string
*/
public $rolename;
/**
* @var string
*/
public $parentid;
/**
* @var string
*/
public $desc;
}
这里定义了一个Role对象,并用标明了各个成员变量的类型,注意这种annotaion是不能省略的.
下面再给一个复合的数据结构的定义。
require_once 'Priority.php';
class RolePriority{
/**
* @return Priority[]
*/
public function getPrioritys() {
return $this->prioritys;
}
/**
* @return string
*/
public function getRoleid() {
return $this->roleid;
}
/**
* @return string
*/
public function getRolename() {
return $this->rolename;
}
/**
* @param Priority[] $prioritys
*/
public function setPrioritys($prioritys) {
$this->prioritys = $prioritys;
}
/**
* @param string $roleid
*/
public function setRoleid($roleid) {
$this->roleid = $roleid;
}
/**
* @param string $rolename
*/
public function setRolename($rolename) {
$this->rolename = $rolename;
}
/**
* @var string
*/
public $rolename;
/**
* @var string
*/
public $roleid;
/**
* @var Priority[]
*/
public $prioritys;
}
这样,根据需求,一个webservice可能要设计很多这样的数据结构,这里就省略了,做法大同小异而已。
在定义完这些对象以后,我们要定义一个webservice的接口文件,也就是要这个webservice去做什么。这里定义一个名叫Gateway的文件,当然根据ZF的命名规则,这个是要加前缀的,具体怎么回事,请参考zf文档,这里不细说。
<?php
require_once 'CommonMsg.php';
require_once 'MsgResp.php';
require_once 'User.php';
require_once 'UserPriority.php';
require_once 'Userole.php';
require_once 'RolePriority.php';
require_once 'Role.php';
require_once 'Priority.php';
class Custom_Soap_Gateway{
/**
* @param string
* @param string
* @param string
* @return MsgResp
*/
public function logonUser($username, $password,$key)
{
$msgResp =new MsgResp();
$user =new User();
if($username&&$password&&$key)
{
$user->userid ='1';
$user->sex='男';
$user->username='刘少奇';
}
$msgResp->user =$user;
$msgResp->code='0000';
$msgResp->msg='login successfully';
return $msgResp;
}
/**
* @param string
* @param string
* @return MsgResp
*/
public function logoutUser($username,$key)
{
$msgResp =new MsgResp();
$user =new User();
if($username&&$key)
{
$user->userid ='1';
$user->sex='男';
$user->username='刘少奇';
}
$msgResp->user =$user;
$msgResp->code='0000';
$msgResp->msg='logout successfully';
return $msgResp;
}
/**
* @param string
* @param string
* @return Userole
*/
public function getUserRole($username,$key)
{
$userole =new Userole();
for($i=0;$i<10;$i++)
{
$role =new Role();
$role->roleid =$i;
$role->parentid='-1';
$role->rolename="role_$i";
$role->desc='xixi';
$userole->roles[$i]=$role;
}
$userole->userid='1';
$userole->username='刘少奇';
return $userole;
}
/**
* @param array
* @param string
* @return MsgResp
*/
public function modifyUser($userinfo,$key)
{
$msgResp =new MsgResp();
$user =new User();
if($userinfo&&$key)
{
$user->userid =$userinfo[0];
$user->sex =$userinfo[1];
$user->username =$userinfo[2];
}
$msgResp->user =$user;
$msgResp->code='0000';
$msgResp->msg='modify successfully';
return $msgResp;
}
/**
* @param string
* @param string
* @return UserPriority
*/
public function getUserPriority($username,$key)
{
$userPriority =new UserPriority();
if($username&&$key)
{
for($i=0;$i<10;$i++)
{
$priority =new Priority();
$priority->prid=$i;
$priority->operation="opti_$i";
$userPriority->prioritys[$i]=$priority;
}
$userPriority->userid='1';
$userPriority->username='刘少奇';
}
return $userPriority;
}
}
这里直接就给了个处理文件,返回值写死了,但做法是一样的,定义的几个方法会暴露于交互接口。
在Action中的调用处理,咱们这里就直接写了不做动态的写法
<?php
/**
*
* @author Administrator
*
*/
class admin_SoapController extends Zend_Controller_Action {
private $_WSDL_URI="http://localhost/ZFDEMO/admin/soap/index?wsdl";
public function preDispatch() {
}
public function indexAction() {
if (isset ( $_GET ['wsdl'] )) {
//return the WSDL
$this->hadleWSDL();
} else {
//handle SOAP request
$this->handleSOAP ();
}
}
public function clientAction()
{
error_reporting( E_ALL | E_STRICT );
try {
$client = new Zend_Soap_Client('http://localhost/ZFDEMO/admin/soap/index?wsdl');
$rs_logout = $client->logoutUser('刘少奇','123456');
$rs_logon =$client->logonUser('刘少奇','123456','key');
$rs_userole =$client->getUserRole('刘少奇','123456');
$rs_priority =$client->getUserPriority('刘少奇','123456');
$userinfo =array(
'0'=>'1',
'1'=>'刘少奇',
'2'=>'男'
);
$rs_moduser =$client->modifyUser($userinfo,'11111');
Zend_Debug::dump($rs_logout,'logout user info',true);
Zend_Debug::dump($rs_moduser,'modify user info',true);
Zend_Debug::dump($rs_logon,'logon user info',true);
Zend_Debug::dump($rs_userole,'userole info',true);
Zend_Debug::dump($rs_priority,'user property info',true);
} catch (SoapFault $s) {
echo $s->faultstring;
die('ERROR: [' . $s->faultcode . '] ' . $s->faultstring);
} catch (Exception $e) {
echo $e->getMessage();
die('ERROR: ' . $e->getMessage());
}
}
private function hadleWSDL() {
$autodiscover = new Zend_Soap_AutoDiscover ('Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex');
$autodiscover->setUri('http://localhost/ZFDEMO/admin/soap/index');
$autodiscover->setClass ('Custom_Soap_Gateway');
$autodiscover->handle ();
}
private function handleSOAP() {
try{
$soap = new Zend_Soap_Server( $this->_WSDL_URI );
$soap->setClass('Custom_Soap_Gateway');
$soap->registerFaultException(array('Custom_Soap_SoapException'));
$soap->handle();
}catch(Exception $e)
{
echo $e->getMessage();
}
}
}
注意 http://localhost/ZFDEMO/admin/soap/index?wsdl 这个url实际上指向的就是indexAction,它的处理方法当然是hadleWSDL(), 其作用是通过我们的接口类自动生成wsdl的文件,并将其指向soap_server进行处理($autodiscover->setUri('http://localhost/ZFDEMO/admin/soap/index');),我们直接在IE上输入此URL得到wsdl的完整内容。
(略)
到此,soap端口已经开放,可以进行通信。于是通过soap_client(clientAction)去调用。
得到结果如下:
["user"] => object(stdClass)#45 (3) {
["userid"] => string(1) "1"
["username"] => string(9) "刘少奇"
["sex"] => string(3) "男"
}
["code"] => string(4) "0000"
["msg"] => string(19) "logout successfully"
}
modify user info object(stdClass)#70 (3) {
["user"] => object(stdClass)#71 (3) {
["userid"] => string(1) "1"
["username"] => string(3) "男"
["sex"] => string(9) "刘少奇"
}
["code"] => string(4) "0000"
["msg"] => string(19) "modify successfully"
}
logon user info object(stdClass)#46 (3) {
["user"] => object(stdClass)#47 (3) {
["userid"] => string(1) "1"
["username"] => string(9) "刘少奇"
["sex"] => string(3) "男"
}
["code"] => string(4) "0000"
["msg"] => string(18) "login successfully"
}
userole info object(stdClass)#48 (3) {
["username"] => string(9) "刘少奇"
["userid"] => string(1) "1"
["roles"] => array(10) {
[0] => object(stdClass)#49 (4) {
["roleid"] => string(1) "0"
["rolename"] => string(6) "role_0"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[1] => object(stdClass)#50 (4) {
["roleid"] => string(1) "1"
["rolename"] => string(6) "role_1"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[2] => object(stdClass)#51 (4) {
["roleid"] => string(1) "2"
["rolename"] => string(6) "role_2"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[3] => object(stdClass)#52 (4) {
["roleid"] => string(1) "3"
["rolename"] => string(6) "role_3"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[4] => object(stdClass)#53 (4) {
["roleid"] => string(1) "4"
["rolename"] => string(6) "role_4"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[5] => object(stdClass)#54 (4) {
["roleid"] => string(1) "5"
["rolename"] => string(6) "role_5"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[6] => object(stdClass)#55 (4) {
["roleid"] => string(1) "6"
["rolename"] => string(6) "role_6"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[7] => object(stdClass)#56 (4) {
["roleid"] => string(1) "7"
["rolename"] => string(6) "role_7"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[8] => object(stdClass)#57 (4) {
["roleid"] => string(1) "8"
["rolename"] => string(6) "role_8"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[9] => object(stdClass)#58 (4) {
["roleid"] => string(1) "9"
["rolename"] => string(6) "role_9"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
}
}
user property info object(stdClass)#59 (3) {
["username"] => string(9) "刘少奇"
["userid"] => string(1) "1"
["prioritys"] => array(10) {
[0] => object(stdClass)#60 (6) {
["prid"] => string(1) "0"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_0"
["desc"] => NULL
}
[1] => object(stdClass)#61 (6) {
["prid"] => string(1) "1"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_1"
["desc"] => NULL
}
[2] => object(stdClass)#62 (6) {
["prid"] => string(1) "2"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_2"
["desc"] => NULL
}
[3] => object(stdClass)#63 (6) {
["prid"] => string(1) "3"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_3"
["desc"] => NULL
}
[4] => object(stdClass)#64 (6) {
["prid"] => string(1) "4"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_4"
["desc"] => NULL
}
[5] => object(stdClass)#65 (6) {
["prid"] => string(1) "5"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_5"
["desc"] => NULL
}
[6] => object(stdClass)#66 (6) {
["prid"] => string(1) "6"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_6"
["desc"] => NULL
}
[7] => object(stdClass)#67 (6) {
["prid"] => string(1) "7"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_7"
["desc"] => NULL
}
[8] => object(stdClass)#68 (6) {
["prid"] => string(1) "8"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_8"
["desc"] => NULL
}
[9] => object(stdClass)#69 (6) {
["prid"] => string(1) "9"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_9"
["desc"] => NULL
}
}
}
php的调用到此结束, 关于针对多语言通信的记录在下一篇内容中。