• php下webservice使用总结


    基于thinkphp3.2的

    1.修改php配置 php.ini 

      extension=php_soap.dll

      soap.wsdl_cache_enabled=0 

    2.soap有两种模式 wsdl和 no-wsdl 

      (1)wsdl

      首先,先生成wsdl文件

    生成wsdl的方法

    <?php
    namespace ApiController;
    use ApiServiceSoapDiscovery;
    use ThinkController;
    
    class CreatewsController extends Controller
    {
        public function index()
        {
            $disco = new SoapDiscovery('\Api\Controller\ServerController', 'soap'); //第一个参数是类名(生成的wsdl文件就是以它来命名的),即Service类,第二个参数是服务的名字(这个可以随便写)。
            $r     = $disco->getWSDL();
            exit();
        }
    }
    View Code

    ServerController.class.php

    <?php
    namespace ApiController;
    use ThinkController;
    class ServerController extends Controller
    {
        public function hello1()
        {
            return 'hello good';
        }
        public function sum1($a = 0, $b = 1)
        {
            return $a + $b;
        }
    }
    View Code

     SoapDiscovery.class.php

    <?php
    namespace ApiService;
    /**
     * SoapDiscovery Class that provides Web Service Definition Language (WSDL).
     * 
     * @package SoapDiscovery
     * @author Braulio Jos?Solano Rojas
     * @copyright Copyright (c) 2005 Braulio Jos?Solano Rojas
     * @version $Id$
     * @access public
     **/
    class SoapDiscovery {
        private $class_name = '';
        private $service_name = '';
        
        /**
         * SoapDiscovery::__construct() SoapDiscovery class Constructor.
         * 
         * @param string $class_name
         * @param string $service_name
         **/
        public function __construct($class_name = '', $service_name = '') {
            $this->class_name = $class_name;
            $this->service_name = $service_name;
        }
        
        /**
         * SoapDiscovery::getWSDL() Returns the WSDL of a class if the class is instantiable.
         * 
         * @return string
         **/
        public function getWSDL() {
            if (empty($this->service_name)) {
                throw new Exception('No service name.');
            }
            $headerWSDL = "<?xml version="1.0" ?>
    ";
            $headerWSDL.= "<definitions name="$this->service_name" targetNamespace="urn:$this->service_name" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="urn:$this->service_name" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/">
    ";
            $headerWSDL.= "<types xmlns="http://schemas.xmlsoap.org/wsdl/" />
    ";
    
            if (empty($this->class_name)) {
                throw new Exception('No class name.');
            }
            
            $class = new ReflectionClass($this->class_name);
            
            if (!$class->isInstantiable()) {
                throw new Exception('Class is not instantiable.');
            }
            
            $methods = $class->getMethods();
            
            $ws_url = '/api/index/ws?wsdl';
            $host = 'http://'.$_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
            $tmp  = str_replace('\', '', dirname($_SERVER['SCRIPT_NAME']));
            $tmp  = empty($tmp) ? '' : '/' . trim($tmp, '/');
            $host .= $tmp;
            $site = $host.'/index.php';
            $ws_url = $site.$ws_url;
    
            $portTypeWSDL = '<portType name="'.$this->service_name.'Port">';
            $bindingWSDL = '<binding name="'.$this->service_name.'Binding" type="tns:'.$this->service_name."Port">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
    ";
            //$serviceWSDL = '<service name="'.$this->service_name."">
    <documentation />
    <port name="".$this->service_name.'Port" binding="tns:'.$this->service_name."Binding"><soap:address location="http://".$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['PHP_SELF']."" />
    </port>
    </service>
    ";
            
            $serviceWSDL = '<service name="'.$this->service_name."">
    <documentation />
    <port name="".$this->service_name.'Port" binding="tns:'.$this->service_name."Binding"><soap:address location="{$ws_url}" />
    </port>
    </service>
    ";
            $messageWSDL = '';
            foreach ($methods as $method) {
                if ($method->isPublic() && !$method->isConstructor()) {
                    $portTypeWSDL.= '<operation name="'.$method->getName()."">
    ".'<input message="tns:'.$method->getName()."Request" />
    <output message="tns:".$method->getName()."Response" />
    </operation>
    ";
                    $bindingWSDL.= '<operation name="'.$method->getName()."">
    ".'<soap:operation soapAction="urn:'.$this->service_name.'#'.$this->class_name.'#'.$method->getName()."" />
    <input><soap:body use="encoded" namespace="urn:$this->service_name" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
    </input>
    <output>
    <soap:body use="encoded" namespace="urn:$this->service_name" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
    </output>
    </operation>
    ";
                    $messageWSDL.= '<message name="'.$method->getName()."Request">
    ";
                    $parameters = $method->getParameters();
                    foreach ($parameters as $parameter) {
                        $messageWSDL.= '<part name="'.$parameter->getName()."" type="xsd:string" />
    ";
                    }
                    $messageWSDL.= "</message>
    ";
                    $messageWSDL.= '<message name="'.$method->getName()."Response">
    ";
                    $messageWSDL.= '<part name="'.$method->getName()."" type="xsd:string" />
    ";
                    $messageWSDL.= "</message>
    ";
                }
            }
            $portTypeWSDL.= "</portType>
    ";
            $bindingWSDL.= "</binding>
    ";
            //return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>');
            $fso = fopen(dirname(__FILE__) . "/SoapService.wsdl", "w");
            fwrite($fso, sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>'));
        }
        
        /**
         * SoapDiscovery::getDiscovery() Returns discovery of WSDL.
         * 
         * @return string
         **/
        public function getDiscovery() {
            return "<?xml version="1.0" ?>
    <disco:discovery xmlns:disco="http://schemas.xmlsoap.org/disco/" xmlns:scl="http://schemas.xmlsoap.org/disco/scl/">
    <scl:contractRef ref="http://".$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['PHP_SELF']."?wsdl" />
    </disco:discovery>";
        }
    }
    View Code

    server端

    <?php
    namespace ApiController;
    use ThinkController;
    class IndexController extends Controller
    {public function ws()
        {
            ob_clean();
            $server = new SoapServer(dirname(dirname(dirname(__FILE__))) . '/ApiServiceSoapService.wsdl', array('soap_version' => SOAP_1_2, 'trace' => true, 'exceptions' => true));
            $server->setClass('ApiControllerServerController'); //注册ServerController类的所有方法 
           $server->handle(); //处理请求  
        } 
    }

    client端

    <?php
    namespace ApiController;
    
    use ThinkController;
    
    class IndexController extends Controller
    {
        public function testWsdl()
        {
            try {
                $soap = new SoapClient("http://127.0.0.102:80/index.php/api/index/ws?wsdl", array(
                    'soap_version' => SOAP_1_2,
                    'cache_wsdl'   => WSDL_CACHE_NONE,
                ));
                echo $soap->sum1(12, 2);
            } catch (Exction $e) {
                echo print_r($e->getMessage(), true);
            }
        }
    }

      (2)no-wsdl

    server

    <?php
    namespace ApiController;
    use ThinkController;
    class IndexController extends Controller
    {
        public function ws()
        {
            ob_clean();
            $arr = array('uri' => "abc");
            $server = new SoapServer(null, $arr);
            $server->setClass('ApiControllerServerController'); //注册Service类的所有方法
            $server->handle(); //处理请求
            exit(); 
        } 
    }

    client

    <?php
    namespace ApiController;
    use ThinkController;
    class IndexController extends Controller
    {
        public function testNonWsdl()
        {
            try {
                $soap = new SoapClient(null, array(
                    "location" => "http://127.0.0.102:80/index.php/api/index/ws",
                    "uri"      => "abc", //资源描述符服务器和客户端必须对应
                    "style"    => SOAP_RPC,
                    "use"      => SOAP_ENCODED,
                ));
                echo $soap->sum1(12, 2); 
            } catch (Exction $e) { 
                echo print_r($e->getMessage(), true); 
            }
        }
    }

    目录结构 

    补充:

    1. 报错looks like we got no XML document in

      (1)

    php.ini中的  always_populate_raw_post_data = -1 注释去掉

      (2)服务器端代码出错,只要有错,就会报上面的提示,仔细检查服务器端代码语法问题即可解决 

      (3)确保服务器端没有任何输出

    2.偶尔出现 Warning: SoapClient::SoapClient(): I/O warning : failed to load external entity

    在网上查找资料看到

      PHP程序作为 SOAP客户端 采用 WSDL 模式访问远端服务器的时候,PHP是通过调用 libcurl 实现的。至少在 PHP5.2.X 是这样的

      如果采用 non-WSDL 模式,就不需要 libcurl。除了 了ibcurl以外,至少还关联的库包括:libidn,ibgcc,libiconv,libintl,openssl

    但是我改成non-WSDL也没解决问题

    最后发现是,增加xml转化的函数里,增加了libxml_disable_entity_loader(true);

    所以才会出现,第一次调用成功,发送普通的字符串也没问题,只有发送xml数据才会出现错误

    3.输出需要请求的方法和携带的参数(适用于wsdl的形式)

    try {
         $client = new SoapClient(''http://127.0.0.102:80/index.php/api/index/ws?wsdl, array(
             'soap_version' => SOAP_1_2,
             'cache_wsdl'   => WSDL_CACHE_NONE,
         ));
        echo 'SOAP types';
        var_dump($client->__getTypes());
        echo 'SOAP Functions';
        var_dump($client->__getFunctions());
    } catch (Exction $e) { 
        echo print_r($e->getMessage(), true); 
    }

    4. 调用.net service方法必须传入命名参数;而调用php web服务方法,一定不能传入命名参数,只能按顺序传入

    调用net的webservice

    $params = [
           'strXml'=>$xml_data,
           'strType'=>$sType
    ];
    $result     = $client->HandleBIMInfo($params);

    调用php的webservice

    $result = $client->HandleBIMInfo($xml_data, $sType);
  • 相关阅读:
    delphi中屏蔽浏览器控件右键菜单
    书目:一些
    数据库ADONETDataAdapter对象参考
    数据库ADONET排序、搜索和筛选
    易语言数据类型及其长度
    易语言数据类型的初始值
    数据库ADONET使用DataAdapter对象
    ADONET使用DataSet处理脱机数据
    数据库ADONETOleDbParameter对象参考
    在项目中添加新数据集
  • 原文地址:https://www.cnblogs.com/baby123/p/9678244.html
Copyright © 2020-2023  润新知