在Thinkphp中使用Soap

最近的項目開發中要用到soap技術,但是thinkphp裏面並沒集成。經過研究終於成功了。呵呵。在此和大家分享先!

1,soap要用到的代碼:

 

  1. <?php 
  2. //Soap接口服務端 
  3. class Server extends Think{ 
  4.     private static $soap; 
  5.      
  6.     public static function Init(){//URL採用普通模式 
  7.         $host = $_SERVER['HTTP_HOST']; 
  8.         $module = MODULE_NAME
  9.         $action = ACTION_NAME
  10.         if((bool)$_GET['ws']){ 
  11.             self::$soap = new SoapServer("http://".$host."/index.php?m=".$module."&a=".$action); 
  12.             self::$soap->setClass($module."Action"); 
  13.             self::$soap->handle(); 
  14.         }else{ 
  15.             $wsdl = new Wsdl(); 
  16.             $wsdl->generateWsdl($module."Action","http://".$host."/index.php?m=".$module."&a=".$action."&ws=1"); 
  17.             unset($wsdl); 
  18.         } 
  19.     } 
  20.      
  21.     public static function UnInit(){ 
  22.         self::$soap = NULL;  
  23.     } 
  24. class Wsdl { 
  25.  
  26.     private $_operations; 
  27.     private $_types; 
  28.     private $_messages; 
  29.     private $_namespace; 
  30.     private $_serviceName; 
  31.  
  32.     public function generateWsdl($className, $serviceUrl, $encoding='UTF-8'
  33.     { 
  34.         $this->_operations=array(); 
  35.         $this->_types=array(); 
  36.         $this->_messages=array(); 
  37.         $this->_serviceName=$className; 
  38.         $this->_namespace="urn:{$className}wsdl"
  39.  
  40.         $reflection=new ReflectionClass($className); 
  41.         foreach($reflection->getMethods() as $method) 
  42.         { 
  43.             if($method->isPublic()){ 
  44.                 $this->processMethod($method); 
  45.             } 
  46.         } 
  47.         header("content-type: text/xml"); 
  48.         echo $this->buildDOM($serviceUrl,$encoding)->saveXML(); 
  49.     } 
  50.  
  51.     private function processMethod($method) 
  52.     { 
  53.         $comment = $method->getDocComment(); 
  54.         if(strpos($comment,'@soap')===false) 
  55.             return; 
  56.          
  57.         $methodName = $method->getName(); 
  58.         $comment = preg_replace('/^\s*\**(\s*?$|\s*)/m','',$comment); 
  59.         $params = $method->getParameters(); 
  60.         $message = array(); 
  61.         $n = preg_match_all('/^@param\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/im',$comment,$matches); 
  62.         if($n>count($params)) 
  63.             $n = count($params); 
  64.         for($i=0;$i<$n;++$i) 
  65.             $message[$params[$i]->getName()] = array($this->processType($matches[1][$i]), trim($matches[3][$i])); // name => type, doc 
  66.  
  67.         $this->_messages[$methodName.'Request'] = $message; 
  68.  
  69.         if(preg_match('/^@return\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/im',$comment,$matches)) 
  70.             $return = array($this->processType($matches[1]),trim($matches[2])); // type, doc 
  71.         else 
  72.             $return = null
  73.              
  74.         $this->_messages[$methodName.'Response'] = array('return'=>$return); 
  75.  
  76.         if(preg_match('/^\/\*+\s*([^@]*?)\n@/s',$comment,$matches)) 
  77.             $doc = trim($matches[1]); 
  78.         else 
  79.             $doc=''
  80.         $this->_operations[$methodName]=$doc; 
  81.     } 
  82.  
  83.     private function processType($type) 
  84.     { 
  85.         static $typeMap=array
  86.             'string'=>'xsd:string', 
  87.             'str'=>'xsd:string', 
  88.             'int'=>'xsd:int', 
  89.             'integer'=>'xsd:integer', 
  90.             'float'=>'xsd:float', 
  91.             'double'=>'xsd:float', 
  92.             'bool'=>'xsd:boolean', 
  93.             'boolean'=>'xsd:boolean', 
  94.             'date'=>'xsd:date', 
  95.             'time'=>'xsd:time', 
  96.             'datetime'=>'xsd:dateTime', 
  97.             'array'=>'soap-enc:Array', 
  98.             'object'=>'xsd:struct', 
  99.             'mixed'=>'xsd:anyType', 
  100.         ); 
  101.         if(isset($typeMap[$type])) 
  102.             return $typeMap[$type]; 
  103.         else if(isset($this->_types[$type])) 
  104.             return is_array($this->_types[$type]) ? 'tns:'.$type : $this->_types[$type]; 
  105.         else if(($pos=strpos($type,'[]'))!==false) // if it is an array 
  106.         { 
  107.             $type=substr($type,0,$pos); 
  108.             if(isset($typeMap[$type])) 
  109.                 $this->_types[$type.'[]']='xsd:'.$type.'Array'; 
  110.             else 
  111.             { 
  112.                 $this->_types[$type.'[]']='tns:'.$type.'Array'; 
  113.                 $this->processType($type); 
  114.             } 
  115.             return $this->_types[$type.'[]']; 
  116.         } 
  117.         else // class type 
  118.         { 
  119.             $type=Yii::import($type,true); 
  120.             $this->_types[$type]=array(); 
  121.             $class=new ReflectionClass($type); 
  122.             foreach($class->getProperties() as $property) 
  123.             { 
  124.                 $comment=$property->getDocComment(); 
  125.                 if($property->isPublic() && strpos($comment,'@soap')!==false) 
  126.                 { 
  127.                     if(preg_match('/@var\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/mi',$comment,$matches)) 
  128.                         $this->_types[$type][$property->getName()]=array($this->processType($matches[1]),trim($matches[3]));  // name => type, doc 
  129.                 } 
  130.             } 
  131.             return 'tns:'.$type; 
  132.         } 
  133.     } 
  134.  
  135.     private function buildDOM($serviceUrl,$encoding) 
  136.     { 
  137.         $xml="<?xml version=\"1.0\" encoding=\"$encoding\"?> 
  138.               <definitions name=\"{$this->_serviceName}\" targetNamespace=\"{$this->_namespace}\" 
  139.                         xmlns=\"http://schemas.xmlsoap.org/wsdl/\" 
  140.                         xmlns:tns=\"{$this->_namespace}\" 
  141.                         xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" 
  142.                         xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" 
  143.                         xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" 
  144.                         xmlns:soap-enc=\"http://schemas.xmlsoap.org/soap/encoding/\"> 
  145.                </definitions>"; 
  146.  
  147.         $dom=new DOMDocument(); 
  148.         $dom->loadXml($xml); 
  149.         $this->addTypes($dom); 
  150.         $this->addMessages($dom); 
  151.         $this->addPortTypes($dom); 
  152.         $this->addBindings($dom); 
  153.         $this->addService($dom,$serviceUrl); 
  154.  
  155.         return $dom; 
  156.     } 
  157.  
  158.     private function addTypes($dom) 
  159.     { 
  160.         if($this->_types===array()) 
  161.             return; 
  162.         $types=$dom->createElement('wsdl:types'); 
  163.         $schema=$dom->createElement('xsd:schema'); 
  164.         $schema->setAttribute('targetNamespace',$this->_namespace); 
  165.         foreach($this->_types as $phpType=>$xmlType) 
  166.         { 
  167.             if(is_string($xmlType) && strrpos($xmlType,'Array')!==strlen($xmlType)-5) 
  168.                 continue;  // simple type 
  169.             $complexType=$dom->createElement('xsd:complexType'); 
  170.             if(is_string($xmlType)) 
  171.             { 
  172.                 if(($pos=strpos($xmlType,'tns:'))!==false) 
  173.                     $complexType->setAttribute('name',substr($xmlType,4)); 
  174.                 else 
  175.                     $complexType->setAttribute('name',$xmlType); 
  176.                     $complexContent=$dom->createElement('xsd:complexContent'); 
  177.                     $restriction=$dom->createElement('xsd:restriction'); 
  178.                     $restriction->setAttribute('base','soap-enc:Array'); 
  179.                     $attribute=$dom->createElement('xsd:attribute'); 
  180.                     $attribute->setAttribute('ref','soap-enc:arrayType'); 
  181.                     $attribute->setAttribute('wsdl:arrayType',substr($xmlType,0,strlen($xmlType)-5).'[]'); 
  182.                     $restriction->appendChild($attribute); 
  183.                     $complexContent->appendChild($restriction); 
  184.                     $complexType->appendChild($complexContent); 
  185.             } 
  186.             else if(is_array($xmlType)) 
  187.             { 
  188.                 $complexType->setAttribute('name',$phpType); 
  189.                 $all=$dom->createElement('xsd:all'); 
  190.                 foreach($xmlType as $name=>$type) 
  191.                 { 
  192.                     $element=$dom->createElement('xsd:element'); 
  193.                     $element->setAttribute('name',$name); 
  194.                     $element->setAttribute('type',$type[0]); 
  195.                     $all->appendChild($element); 
  196.                 } 
  197.                 $complexType->appendChild($all); 
  198.             } 
  199.             $schema->appendChild($complexType); 
  200.             $types->appendChild($schema); 
  201.         } 
  202.  
  203.         $dom->documentElement->appendChild($types); 
  204.     } 
  205.  
  206.     private function addMessages($dom) 
  207.     { 
  208.         foreach($this->_messages as $name=>$message) 
  209.         { 
  210.             $element=$dom->createElement('wsdl:message'); 
  211.             $element->setAttribute('name',$name); 
  212.             foreach($this->_messages[$name] as $partName=>$part) 
  213.             { 
  214.                 if(is_array($part)) 
  215.                 { 
  216.                     $partElement=$dom->createElement('wsdl:part'); 
  217.                     $partElement->setAttribute('name',$partName); 
  218.                     $partElement->setAttribute('type',$part[0]); 
  219.                     $element->appendChild($partElement); 
  220.                 } 
  221.             } 
  222.             $dom->documentElement->appendChild($element); 
  223.         } 
  224.     } 
  225.  
  226.     private function addPortTypes($dom) 
  227.     { 
  228.         $portType=$dom->createElement('wsdl:portType'); 
  229.         $portType->setAttribute('name',$this->_serviceName.'PortType'); 
  230.         $dom->documentElement->appendChild($portType); 
  231.         foreach($this->_operations as $name=>$doc) 
  232.             $portType->appendChild($this->createPortElement($dom,$name,$doc)); 
  233.     } 
  234.  
  235.     private function createPortElement($dom,$name,$doc) 
  236.     { 
  237.         $operation=$dom->createElement('wsdl:operation'); 
  238.         $operation->setAttribute('name',$name); 
  239.  
  240.         $input = $dom->createElement('wsdl:input'); 
  241.         $input->setAttribute('message', 'tns:'.$name.'Request'); 
  242.         $output = $dom->createElement('wsdl:output'); 
  243.         $output->setAttribute('message', 'tns:'.$name.'Response'); 
  244.  
  245.         $operation->appendChild($dom->createElement('wsdl:documentation',$doc)); 
  246.         $operation->appendChild($input); 
  247.         $operation->appendChild($output); 
  248.  
  249.         return $operation; 
  250.     } 
  251.  
  252.     private function addBindings($dom) 
  253.     { 
  254.         $binding=$dom->createElement('wsdl:binding'); 
  255.         $binding->setAttribute('name',$this->_serviceName.'Binding'); 
  256.         $binding->setAttribute('type','tns:'.$this->_serviceName.'PortType'); 
  257.  
  258.         $soapBinding=$dom->createElement('soap:binding'); 
  259.         $soapBinding->setAttribute('style','rpc'); 
  260.         $soapBinding->setAttribute('transport','http://schemas.xmlsoap.org/soap/http'); 
  261.         $binding->appendChild($soapBinding); 
  262.  
  263.         $dom->documentElement->appendChild($binding); 
  264.  
  265.         foreach($this->_operations as $name=>$doc) 
  266.             $binding->appendChild($this->createOperationElement($dom,$name)); 
  267.     } 
  268.  
  269.     private function createOperationElement($dom,$name) 
  270.     { 
  271.         $operation=$dom->createElement('wsdl:operation'); 
  272.         $operation->setAttribute('name', $name); 
  273.         $soapOperation = $dom->createElement('soap:operation'); 
  274.         $soapOperation->setAttribute('soapAction', $this->_namespace.'#'.$name); 
  275.         $soapOperation->setAttribute('style','rpc'); 
  276.  
  277.         $input = $dom->createElement('wsdl:input'); 
  278.         $output = $dom->createElement('wsdl:output'); 
  279.  
  280.         $soapBody = $dom->createElement('soap:body'); 
  281.         $soapBody->setAttribute('use', 'encoded'); 
  282.         $soapBody->setAttribute('namespace', $this->_namespace); 
  283.         $soapBody->setAttribute('encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/'); 
  284.         $input->appendChild($soapBody); 
  285.         $output->appendChild(clone $soapBody); 
  286.  
  287.         $operation->appendChild($soapOperation); 
  288.         $operation->appendChild($input); 
  289.         $operation->appendChild($output); 
  290.  
  291.         return $operation; 
  292.     } 
  293.  
  294.     private function addService($dom,$serviceUrl) 
  295.     { 
  296.         $service=$dom->createElement('wsdl:service'); 
  297.         $service->setAttribute('name', $this->_serviceName.'Service'); 
  298.  
  299.         $port=$dom->createElement('wsdl:port'); 
  300.         $port->setAttribute('name', $this->_serviceName.'Port'); 
  301.         $port->setAttribute('binding', 'tns:'.$this->_serviceName.'Binding'); 
  302.  
  303.         $soapAddress=$dom->createElement('soap:address'); 
  304.         $soapAddress->setAttribute('location',$serviceUrl); 
  305.         $port->appendChild($soapAddress); 
  306.         $service->appendChild($port); 
  307.         $dom->documentElement->appendChild($service); 
  308.     } 
  309. ?> 

 

2,服務端調用方式:

 

  1. public function ExamSoap(){ 
  2.         import('@.ORG.Soap'); 
  3.         Server::Init(); 
  4.     } 
  5.      
  6.     /** 
  7.     *   @param array 
  8.     *   @return string 
  9.     *   @soap 
  10.     */ 
  11.     public function SendExamScore($arr){ 
  12.         return $arr[0]."  ".$arr[1]; 
  13.     } 

在這裏主要是ExamSoap調用。而SendExamScore函數主要是提供的接口。

3,遠程調用

 

  1. $soap = new SoapClient("http://*.com/index.php?m=Public&a=ExamSoap"); 
  2. $soap->SendExamScore(array($user["user_workno"],($score + $k_score),$user["fid"])); 
  3. unset($soap); 

一切完成,萬事大吉!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章