Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何填充复合消息并作为SoapServer响应XML返回?_Php_Xml_Web Services_Soap_Soapserver - Fatal编程技术网

Php 如何填充复合消息并作为SoapServer响应XML返回?

Php 如何填充复合消息并作为SoapServer响应XML返回?,php,xml,web-services,soap,soapserver,Php,Xml,Web Services,Soap,Soapserver,我正在设置一个SOAP web服务,它将返回一条复合消息。 此消息的有效实例如下所示: <dl190Response xmlns="http://pse/"> <cdhead cisprik="5563167"/> <mvts> <mvts_S att="a1"> <x>x1</x> <w>w1</w> &

我正在设置一个SOAP web服务,它将返回一条复合消息。
此消息的有效实例如下所示:

<dl190Response xmlns="http://pse/">
    <cdhead cisprik="5563167"/>
    <mvts>
        <mvts_S att="a1">
            <x>x1</x>
            <w>w1</w>
        </mvts_S>
        <mvts_S>
            <x>x2</x>
            <w>w2</w>
        </mvts_S>
    </mvts>
</dl190Response>

x1
w1
x2
w2
所有这些都在wsdl中定义得很清楚:

<?xml version="1.0" encoding="UTF-8"?>
<definitions
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://pse/"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    name="PSE"
    targetNamespace="http://pse/">
    <types>
        <xs:schema xmlns="http://pse/" targetNamespace="http://pse/">
            <xs:complexType name="cdhead_T">
                <xs:attribute name="cisprik" type="xs:long"/>
            </xs:complexType>
            <xs:complexType name="mvts_T">
                <xs:sequence>
                    <xs:element name="mvts_S" type="mvts_S_T" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:complexType>
            <xs:complexType name="mvts_S_T">
                <xs:sequence>
                    <xs:element name="x" type="xs:string"/>
                    <xs:element name="w" type="xs:string"/>
                </xs:sequence>
                <xs:attribute name="att" type="xs:string" use="optional"/>
            </xs:complexType>
        </xs:schema>
    </types>
    <message name="DL190Req">
        <part name="cdhead" type="tns:cdhead_T"/>
    </message>
    <message name="DL190Res">
        <part name="cdhead" type="tns:cdhead_T"/>
        <part name="mvts" type="tns:mvts_T"/>
    </message>
    <portType name="DLPortType">
        <operation name="dl190">
            <input message="tns:DL190Req"/>
            <output message="tns:DL190Res"/>
        </operation>
    </portType>
    <binding name="DLBinding" type="tns:DLPortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="dl190">
            <soap:operation soapAction="http://www.testServer.com/test_soap.php#dl190"/>
            <input>
                <soap:body use="literal" namespace="http://pse/"/>
            </input>
            <output>
                <soap:body use="literal" namespace="http://pse/"/>
            </output>
        </operation>
    </binding>
    <service name="PSE">
        <port name="DLPortType" binding="tns:DLBinding">
            <soap:address location="http://www.testServer.com/test_soap.php"/>
        </port>
    </service>
</definitions>

我一直在无休止地进行服务器端测试_soap.php以使其正确,但没有成功。 在返回XML之前,部分工作正常,如下所示:

<?php
    class PSE {
        function dl190 ($arg) {
            //I don't need to extract the input data just now

            mysql_connect('127.0.0.1:3306', 'user', 'password');
            mysql_select_db('myDatabase');

            $xml = new SimpleXMLElement('<dl190Res/>');
            $xml -> addChild('cdhead');
            $mvts = $xml -> addChild('mvts');

            $rows = mysql_query('select * from trx');
            while($data = mysql_fetch_assoc($rows)) {
                $mvts_S = $mvts -> addChild('mvts_S'); 
                foreach($data as $key => $value) {
                    if ($key == 'att') { $mvts_S -> addAttribute($key, $value);}
                    else    {$mvts_S -> addChild($key, $value);}
                }
            };

            $dom = dom_import_simplexml ($xml) -> ownerDocument;

            // now respond to the request and return the XML
        }

    };
    ini_set( "soap.wsdl_cache_enabled", "0");
    $server = new SoapServer ("test.wsdl");
    $server -> setClass ('PSE');
    $server -> setObject (new PSE());
    $server -> handle();    
?>

我不是SOAP专家,但不得不在一些项目上使用SOAP与第三方服务器进行交互,这是一场噩梦,部分原因是服务器实现不太好,而我自己也不知道这是什么原因。但我记得在尝试按原样使用类时遇到了很多问题,然后我转而使用,这样做更容易,解决了很多我遇到的奇怪问题。所以我的建议是使用像NuSOAP这样的工具包,看看事情是否更有意义

这还不错,但我认为它已经不再被使用了,而且它太脏了,使用起来很痛苦。该系统甚至被弃用和退役。是的,如果你能走另一条路,我会的

比如说,你可以走这条路

REST通过允许不同服务之间的松散耦合来促进web服务器之间的事务。REST的强类型性不如其对应的SOAP。REST语言基于名词和动词的使用,强调可读性。与SOAP不同,REST不需要XML解析,也不需要与服务提供者之间的消息头。这最终使用更少的带宽。REST错误处理也不同于SOAP使用的错误处理


我尝试并设置了您的最小SoapServer,下面是我所做的:

  • 将wsdl和PHP脚本复制到文件夹中
  • 更改wsdl位置引用以指向php脚本
  • 将WSDL导入-强烈推荐,它是免费的
  • 我试着打电话给服务部
  • 这是我的电话请求:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pse="http://pse/">
       <soapenv:Header/>
       <soapenv:Body>
          <pse:dl190>
             <cdhead cisprik="0"/>
          </pse:dl190>
       </soapenv:Body>
    </soapenv:Envelope>
    
    然后,您可以更轻松地准备响应:

    $fakeResult = new PSE_DL190_Response();
    $fakeResult->cdhead = new PSE_cdhead_T(); // Set the one cdhead structure
    $fakeResult->mvts[] = new PSE_mvts_S_T(); // Add one mvts structure;
    
    这很可能会导致您的XML响应发生变化——不过,我无法评估其影响


    最后一个想法:有一些用于PHP的WSDL代码生成器,您可以尝试一下。它们将自动生成类映射所需的类。上次我尝试它们时,它们似乎可以工作,但并不是所有我测试的WSDL文件都可以。Soap定义似乎太复杂了,无法正确定义。但是如果它能工作,那就值得去做,而不是手动创建它们。

    当然也必须有一种方法来实现我使用SoapServer的目标——我希望先走这条路。此外,我需要一个更详细的答案,包含正确方向的示例代码,或者需要遵循的步骤的详细列表。我肯定需要SOAP类型的响应,因此XML包含(无标题)信封/正文/响应/两个子消息部分。听起来不错,今天晚些时候我将对此进行详细研究。我觉得赏金即将到来:-)好的,我测试过了,一切都好了-非常感谢-我会尝试将这扩展到现实中更复杂的问题,但至少我现在有了一个开始!最后我看到了wsdl细节是如何影响返回元素名称值的——这也是我想知道的好东西。
    <?php
    class PSE
    {
        public function dl190($arg)
        {
            //var_dump($arg) is:
            //object(stdClass)#3 (1) {
            //   ["cisprik"]=> int(0)
            //}
    
            $fakeResult = array();
    
            $fakeResult[0] = new stdClass();
            $fakeResult[0]->cisprik = 23;
    
            $fakeResult[1] = array();
    
            $fakeResult[1][0] = new stdClass();
            $fakeResult[1][0]->att = "a1";
            $fakeResult[1][0]->x = "x1";
            $fakeResult[1][0]->w = "w1";
    
            $fakeResult[1][1] = new stdClass();
            //$fakeResult[1][1]->att = "a1";
            $fakeResult[1][1]->x = "x2";
            $fakeResult[1][1]->w = "w2";
    
            return $fakeResult;
        }
    }
    
    //ini_set("soap.wsdl_cache_enabled", "0");
    
    $server = new SoapServer ("wsdl.xml");
    $server->setObject(new PSE());
    $server->handle();
    
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://pse/">
       <SOAP-ENV:Body>
          <ns1:dl190Response>
             <cdhead cisprik="23"/>
             <mvts>
                <mvts_S att="a1">
                   <x>x1</x>
                   <w>w1</w>
                </mvts_S>
                <mvts_S>
                   <x>x2</x>
                   <w>w2</w>
                </mvts_S>
             </mvts>
          </ns1:dl190Response>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    
    <?php
    class PSE
    {
        public function dl190(PSE_cdhead_T $arg)
        {
            //  var_dump($arg) is:
            //  object(PSE_cdhead_T)#3 (1) {
            //      ["cisprik"]=> int(0)
            //  }
    
            $fakeResult = array();
            $fakeResult[0] = new PSE_cdhead_T();
            $fakeResult[0]->cisprik = 23;
    
            $fakeResult[1] = array();
    
            $fakeResult[1][0] = new PSE_mvts_S_T();
            $fakeResult[1][0]->att = "a1";
            $fakeResult[1][0]->x = "x1";
            $fakeResult[1][0]->w = "w1";
    
            $fakeResult[1][1] = new PSE_mvts_S_T();
            //$fakeResult[1][1]->att = "a1";
            $fakeResult[1][1]->x = "x2";
            $fakeResult[1][1]->w = "w2";
    
            return $fakeResult;
        }
    }
    
    class PSE_cdhead_T {
        /**
         * @var int
         */
        public $cisprik;
    }
    
    
    class PSE_mvts_S_T {
        /**
         * @var string
         */
        public $att;
    
        /**
         * @var string
         */
        public $x;
    
        /**
         * @var string
         */
        public $w;
    }
    
    //ini_set("soap.wsdl_cache_enabled", "0");
    
    $classmap = array(
        'cdhead_T' => 'PSE_cdhead_T',
        'mvts_S_T' => 'PSE_mvts_S_T',
    );
    
    $serverOptions = array(
        'encoding' => 'utf-8',
        'classmap' => $classmap,
        'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
    );
    
    $server = new SoapServer ("wsdl.xml", $serverOptions);
    
    $server->setObject(new PSE());
    $server->handle();
    
    class PSE_DL190_Response
    {
        /**
         * @var PSE_cdhead_T
         */
        public $cdhead;
        /**
         * @var PSE_mvts_S_T[]
         */
        public $mvts;
    }
    
    $fakeResult = new PSE_DL190_Response();
    $fakeResult->cdhead = new PSE_cdhead_T(); // Set the one cdhead structure
    $fakeResult->mvts[] = new PSE_mvts_S_T(); // Add one mvts structure;