SOAP服务器未接收到所有参数。

7

我正在使用PHP,并且我使用的是PHP捆绑的SOAP类。我一整天都在尝试弄明白为什么这不起作用。

我在客户端上编写了以下内容:

 $client = new SoapClient("Audit.wsdl");                              
 $params=array('SerialNumber'=>'PB4LAX6JLJT7M','PercentProgress'=>'50','ResultID'=>'5');
 $result=$client->__soapCall('HardDriveStatusUpdate',array($params));

我在服务器端编写了以下内容:
function HardDriveStatusUpdate($sn, $p, $rs)
{
    $serialNumber=$sn->SerialNumber;
    $percentProgress=$p->PercentProgress;
    $resultID=$rs->ResultID; 
    // process with variables 
    return array('HardDriveStatusUpdateResult' => '$result');
}

$server=new SoapServer('Audit.wsdl');
$server->addFunction('HardDriveStatusUpdate');
$server->handle();

我注意到什么都没有发生。为了调试,我让该函数用"$serialNumber, $percentProgress, $resultID"写入文件。结果只获取了第一个参数,而第二个和第三个参数为空。(它显示为"PB4LAX6JLJT7M,,") 为什么?
WSDL说:
 <s:element name="HardDriveStatusUpdate">
    <s:complexType>
      <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" name="SerialNumber" type="s:string" />
        <s:element minOccurs="1" maxOccurs="1" name="PercentProgress" type="s:int" />
        <s:element minOccurs="1" maxOccurs="1" name="ResultID" type="s:int" />
      </s:sequence>
    </s:complexType>
  </s:element>

我构造参数的方式有问题吗?

使用__getLastRequest()进行测试:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://127.0.0.1/soap/">
     <SOAP-ENV:Body>
         <ns1:HardDriveStatusUpdate>
             <ns1:SerialNumber>PB4LAX6JLJT7M</ns1:SerialNumber>
             <ns1:PercentProgress>50</ns1:PercentProgress>
             <ns1:ResultID>5</ns1:ResultID>
         </ns1:HardDriveStatusUpdate>
     </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

真正的问题肯定是在服务器端。即使所有参数都已经在SOAP请求中发送,但该函数仍未获取到这些参数。为什么会这样?我尝试了另一种方法,仍然无法获得第二个参数。只有第一个参数有效。


"PercentProgress"和"ResultID"在wsdl中的类型是int,但你正在发送一个字符串? - Anas
当在客户网页上回显getLastResponse/request时,它们为空白...但问题是 - 当我回显$result->HardDriveStatusUpdateResult时,它显示1(如果返回0则不显示) UPDATE:刚刚发现我需要为这些函数打开跟踪。 - netrox
1
你尝试过使用SOAPui进行测试吗? - Alfabravo
你应该尝试使用SoapUI来调试服务器端,将一些 die(); 放入你的代码中,它们会在SoapUI中显示。 - Anas
如果您能提供WSDL文件,那么我就可以在本地进行测试! - Anas
显示剩余2条评论
4个回答

5

我使用您提供的wsdl测试了您的代码,参数被发送到一个单一的对象中,因此这里是您需要进行的更改:

function HardDriveStatusUpdate($myObject)
{
    $serialNumber = $myObject->SerialNumber;
    $percentProgress = $myObject->PercentProgress;
    $resultID = $myObject->ResultID; 
    // process with variables 
    return array('HardDriveStatusUpdateResult' => true);
}

我在SoapUi中进行了测试(使用print_r($myObject); die();),这是结果:

:enter image description here


4

当我尝试学习SOAP时,遇到了巨大的问题,纯粹为了扩展知识而已。以下是我最终采用的方法:

步骤1: 从PHPClasses.org下载PHP2WSDL类

步骤2: 使用以下代码生成WSDL require_once("PHPClasses/PHP2WSDL/WSDLCreator.php");

$test = new WSDLCreator("WSDLTester", "http://localhost/soap/SoapServer/");
//$test->includeMethodsDocumentation(false);

$test->addFile("servicefunctions.php");

$test->addURLToClass("servicefunctions", "http://localhost/soap/SoapServer/server.php");

//$test->ignoreMethod(array("example1_1"=>"getEx"));

$test->createWSDL();
$test->saveWSDL("/path/to/dir/SoapServer/test.wsdl");

我把上面的内容存储在一个名为wsdl.php的文件中,您可以在浏览器中访问该文件以生成wsdl文件。注意:重要的是将您的类和您创建的soap服务器的URL作为addURLToClass中的URL放置——因为这是您的服务器进入wsdl以被正确调用的方式 完整的ServiceFunctions.php代码如下:
class servicefunctions {

    /**
     * stringifies
     *
     * @param string $string
     * @return string
     */
    public function stringify(string $string) {
        return "I took the " . $string . " and stringified it";
    }

    /**
     * Adds two numbers
     *
     * @param int $number1
     * @param int $number2
     * @return string
     */
    public function addify(int $number1,int $number2) {
        $answer = ($number1 + $number2);
        $string = "the answer is " . $answer;
        return (string)$string;
    }

}

请注意使用注释输入变量类型,这将被PHP2WSDL使用并在生成的WSDL文件中使用。
然后创建服务器:
try {
  $server = new SOAPServer("/home/liam/DevEnv/SoapServer/test.wsdl",array('cache_wsdl'=>WSDL_CACHE_NONE));
  $server->setClass("servicefunctions");
  $server->handle();
  }

catch (SOAPFault $f) {
  print "ERROR".$f->faultstring;
}

这是客户端:
try {
$client = new SoapClient("/home/liam/DevEnv/SoapServer/test.wsdl",array('cache_wsdl'=>WSDL_CACHE_NONE));
echo print_r($client->__getFunctions(),true) . "<br/>";
echo $client->stringify("test new");
}
catch (SOAPFault $f) {
  print "ERROR" . $f->faultstring;
}

输出:

Array ( [0] => string addify(integer $number1, integer $number2) [1] => string stringify(string $string) )
I took the test new and stringified it

我相信你可以轻松将这个转换为你的类。


1
@netrox 不知道你是否看到了这个答案 - 你认为你可以很容易地转换它吗 - 将类名更改为你的类和 URL 等,大约需要 10 分钟的时间吧? - Liam Bailey
嗨,Liam - 我刚刚查看了这个...奇怪的是我没有收到你的答复通知。让我在几个小时内测试它,然后告诉你它的运行情况。祈求好运 - netrox
生成的 WSDL 不完整 - 缺少绑定,甚至没有操作或参数。 - netrox
刚刚发现 servcefunctions.php 有我的额外注释,导致无法正确解析。我删除了注释后就可以工作了。但是当我运行 client.php 时,它仍然会显示“ERROR Function 'stringify' doesn't exist”,但生成的 WSDL 显示了该函数。 - netrox
array('cache_wsdl'=>WSDL_CACHE_NONE) 这个参数在SOAPServer()中真的为我节省了很多时间,再次感谢。 - Sean
显示剩余2条评论

0

0

您正在将数据作为数组的1个参数发送(array($params)),这意味着服务器只接收到一个参数。您可以更改函数签名以仅接受1个参数,或更改调用函数的方式。

如果您想使用一系列键=>值参数来调用它,则可以将$params更改为:

array(array("SerialNumber" => 'PB4LAX6JLJT7M'), array('PercentProgres' .... ));

然后使用$result=$client->__soapCall('HardDriveStatusUpdate',$params);进行调用。

在您的接收函数中,您试图使用对象属性语法检索参数,而您应该使用数组语法,例如$sn["SerialNumber"]


那不起作用。我使用了数组中的数组,并使用了数组语法,但它生成了“无法将stdClass类型的对象用作数组”的错误 - 当我使用语法“serialnumber->serialnumber”时,它可以工作,只是没有得到额外的参数。 - netrox
奇怪,你正在运行哪个版本的PHP? - Kristoffer Sall-Storgaard
我正在使用的PHP版本是5.2.9。 - netrox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接