1

我正在尝试在 php 中设置 SOAP 服务。我声明了一个服务器 php 函数,我可以使用 SOAP 类型的 http 请求调用该函数,其中内容是我的 SOAP 信封。

SOAP 主体的 XML 内容是我假设的函数的参数,但我不知道如何在我的 php 代码中访问其中的信息。

我注意到函数参数是stdClass默认情况下的一个实例,我实际上想知道为什么它没有被 php 强制转换为XMLorDOM对象 - 它是一个 SOAP 调用,不是吗?但是好的,现在由我来从对象中获取信息,这并不容易,因为没有分配给 的方法stdClass,所以它必须是标准的 php 函数。所以我尝试serialize了,但这给了我一些垃圾,而不是我期望的 XML 字符串。

该怎么办?

编辑

请注意,下面没有我想做的示例代码 - 从 SOAP 请求的 XML 内容中获取一些详细数据 - 因为我不知道如何编写代码从 stdClass 对象中获取它

应大卫的要求,这里有一些细节。

php代码:

<?php
    function mi102($arg) {
        $txt = serialize ($arg);
        $result = new SoapVar ($txt, XSD_ANYXML);
        return($result);
    }
    ini_set( "soap.wsdl_cache_enabled", "0");
    $server = new SoapServer ("test.wsdl");
    $server -> addFunction ("mi102");
    try {
        $server -> handle();
    }
    catch (Exception $e) {
        $server -> fault ('Client', $e -> getMessage());
    }
?php>

http请求是由我使用的应用程序构造的;http标头和soap信封+正文是围绕我提供的XML生成的:

SOAP 请求正文内容:

<mi102 xmlns="http://pse">
  <cdhead cisprik="21"/>
  <instr>
    <insid>
      <bcdt>20120930</bcdt>
    </insid>
  </instr>
</mi102>

使用的 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>
            <xs:import namespace="http://pse/" schemaLocation="PSE.xsd"/>
        </xs:schema>
    </types>
    <message name="MI102Req">
        <part name="cdhead" type="tns:cdhead_T"/>
        <part name="instr" type="tns:instr_T"/>
    </message>
    <message name="Res">
        <part name="cdhead" type="tns:cdhead_T"/>
    </message>
    <portType name="MIPortType">
        <operation name="mi102">
            <input message="tns:MI102Req"/>
            <output message="tns:Res"/>
        </operation>
    </portType>
    <binding name="MIBinding" type="tns:MIPortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="mi102">
            <soap:operation soapAction="http://testServerURL/test_soap.php#mi102"/>
            <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="MIPortType" binding="tns:MIBinding">
            <soap:address location="http://testServerURL/test_soap.php"/>
        </port>
    </service>
</definitions>

生成的 XML(同样,由我使用的应用程序从 SOAP 主体中提取)是

SOAP 响应:

<?xml version="1.0" encoding="UTF-8"?>
<ns1:mi102Response xmlns:ns1="http://pse/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">O:8:"stdClass":2:{s:7:"cisprik";i:21;s:7:"version";s:2:"13";}</ns1:mi102Response>

不太好。

4

3 回答 3

3

我最终在 SO 上的其他线程中找到了答案,例如get-recieved-xml-from-php-soap-server

解决方案是使用以下内容:

$inp = file_get_contents ('php://input');

注意:我找不到任何可以作用于stdClass输入参数并可以从中检索 XML SOAP 正文内容的函数。
所以最好的选择是使用标准的 php 输入变量。请注意,它具有以下结构:Envelope/Body/..inputXML..,这是发布到服务器的确切 http 请求内容。

注意:http_get_request_body可能也可以,但我的 php 服务器不支持此功能。我认为file_get_contents从某个版本开始,每个 php 服务器都支持这一点。

于 2012-10-05T07:37:16.840 回答
0

这不会作为一个完整的答案开始,但我想要格式化。请详细说明您设置了什么。通常,您将拥有一个带有常规参数(不是 XML)的 PHP 方法,您希望将其公开为 Web 服务。有关如何执行此操作的基本示例如下:

http://www.phpeveryday.com/articles/Web-Services-WSDL-Creating-SOAP-Server-P484.html

SOAP 主体的 XML 内容是我假设的函数的参数

不,SOAP 主体的 XML 内容是带有您的参数的方法的表示,但您的参数是您想要的任何东西。如果使用 PHP 的 SoapServer 和 SoapClient 设置 XML,则不必手动处理 XML。

编辑:您正在接受您的论点,这是您的 SOAP 请求主体的简单 PHP 数组表示,将其序列化并将其作为响应发送回(这是您观察到的)。这是你想做的吗?你不想对请求数据做点什么吗?另外,您能否发布从 WSDL 导入的模式?

于 2012-10-02T15:14:02.293 回答
0

您拥有对象的“不好”表示,因为您正在返回序列化的对象(序列化正在将对象及其状态转换为字符串表示)。如果您想要返回对象的 xml 表示,您应该将函数的返回参数类型更改为对象。因为现在正在返回一个字符串。

我建议您使用 zend 框架的 Zend_Soap_Server 和 Zend_Soap_Autodiscover 组件。

使用 Zend_Soap_Autodiscover,您可以动态生成 W​​eb 服务定义 (wsdl),只需编写函数的文档块。Zend_Soap_Server 也很酷。

如果您使用这些组件并记录您的类型和函数以返回特定类型而不对其进行序列化,那么您将根据 wsdl 定义接收 xml 表示。此外,您创建的每个类型都由 Zend_Soap_Autodiscover 自动转换为生成的 wsdl 中的 ComplexType。

样本:

 public class Person{
         public $id;
         public $name;
    }

    public class MyService {
     /**
     *
     * @param integer $UserID
     * @return Person
     */
    function mi102($UserID) {

         $output = new Person();
         $output->id = 2;
         $output->name = 'Peter';        

        return $output;
    }
}


// Generate WSDL relevant to code
if (isset($_GET['wsdl'])){

    $autodiscover = new Zend_Soap_AutoDiscover();
    $autodiscover->setClass('MyService');
    $autodiscover->handle();

} else {

    $server = new Zend_Soap_Server($serviceURL . "?wsdl");
    $server->setClass('MyService');
    $server->setObject(new MyService());
    $server->handle();

}
于 2012-10-02T16:05:12.907 回答