如何从 PHP 发布 SOAP 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/471115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:52:09  来源:igfitidea点击:

How to post SOAP Request from PHP

phpweb-servicessoap

提问by Jin Yong

Anyone know how can I post a SOAP Request from PHP?

任何人都知道如何从 PHP 发布 SOAP 请求?

回答by Ivan Krechetov

In my experience, it's not quite that simple. The built-in PHP SOAP clientdidn't work with the .NET-based SOAP server we had to use. It complained about an invalid schema definition. Even though .NET client worked with that server just fine. By the way, let me claim that SOAP interoperability is a myth.

根据我的经验,事情并没有那么简单。内置的PHP SOAP 客户端不适用于我们必须使用的基于 .NET 的 SOAP 服务器。它抱怨无效的架构定义。即使 .NET 客户端与该服务器一起工作也很好。顺便说一下,让我声明 SOAP 互操作性是一个神话。

The next step was NuSOAP. This worked for quite a while. By the way, for God's sake, don't forget to cache WSDL! But even with WSDL cached users complained the damn thing is slow.

下一步是NuSOAP。这工作了很长一段时间。顺便说一句,看在上帝的份上,不要忘记缓存 WSDL!但即使使用 WSDL 缓存,用户也抱怨该死的东西很慢。

Then, we decided to go bare HTTP, assembling the requests and reading the responses with SimpleXMLElemnt, like this:

然后,我们决定使用裸 HTTP,组装请求并使用 读取响应SimpleXMLElemnt,如下所示:

$request_info = array();

$full_response = @http_post_data(
    'http://example.com/OTA_WS.asmx',
    $REQUEST_BODY,
    array(
        'headers' => array(
            'Content-Type' => 'text/xml; charset=UTF-8',
            'SOAPAction'   => 'HotelAvail',
        ),
        'timeout' => 60,

    ),
    $request_info
);

$response_xml = new SimpleXMLElement(strstr($full_response, '<?xml'));

foreach ($response_xml->xpath('//@HotelName') as $HotelName) {
    echo strval($HotelName) . "\n";
}

Note that in PHP 5.2 you'll need pecl_http, as far as (surprise-surpise!) there's no HTTP client built in.

请注意,在 PHP 5.2 中,您将需要 pecl_http,因为(出乎意料!)没有内置 HTTP 客户端。

Going to bare HTTP gained us over 30% in SOAP request times.And from then on we redirect all the performance complains to the server guys.

使用裸 HTTP 使我们在 SOAP 请求时间上增加了 30% 以上。从那时起,我们将所有性能投诉重定向到服务器人员。

In the end, I'd recommend this latter approach, and not because of the performance. I think that, in general, in a dynamic language like PHP there's no benefitfrom all that WSDL/type-control. You don't need a fancy library to read and write XML, with all that stubs generation and dynamic proxies. Your language is already dynamic, and SimpleXMLElementworks just fine, and is so easy to use. Also, you'll have less code, which is always good.

最后,我推荐后一种方法,而不是因为性能。我认为,一般来说,在像 PHP 这样的动态语言中,所有 WSDL/类型控制都没有任何好处。您不需要花哨的库来读取和编写 XML,以及所有存根生成和动态代理。你的语言已经是动态的,而且SimpleXMLElement工作得很好,而且很容易使用。此外,您将拥有更少的代码,这总是好的。

回答by Sharj

PHP has SOAP support. Just call

PHP 有 SOAP 支持。打电话就行

$client = new SoapClient($url);

to connect to the SoapServer and then you can get list of functions and call functions simply by doing...

连接到 SoapServer,然后您只需执行以下操作即可获取函数列表和调用函数...

$client->__getTypes();      
$client->__getFunctions();  

$result = $client->functionName();  

for more http://www.php.net/manual/en/soapclient.soapclient.php

更多http://www.php.net/manual/en/soapclient.soapclient.php

回答by Tim Duncklee

I needed to do many very simple XML requests and after reading @Ivan Krechetov's comment about the speed hit of SOAP, I tried his code and discovered http_post_data() is not built into PHP 5.2. Not really wanting to install it, I tried cURL which is on all my servers. Although I do not know how fast cURL is compared to SOAP, it sure was easy to do what I needed. Below is a sample with cURL for anyone needing it.

我需要执行许多非常简单的 XML 请求,在阅读了@Ivan Krechetov 关于 SOAP 速度影响的评论后,我尝试了他的代码并发现 http_post_data() 没有内置到 PHP 5.2 中。不是真的想安装它,我尝试了我所有服务器上的 cURL。尽管我不知道 cURL 与 SOAP 相比有多快,但确实很容易完成我需要的工作。下面是一个带有 cURL 的示例,供任何需要它的人使用。

$xml_data = '<?xml version="1.0" encoding="UTF-8" ?>
<priceRequest><customerNo>123</customerNo><password>abc</password><skuList><SKU>99999</SKU><lineNumber>1</lineNumber></skuList></priceRequest>';
$URL = "https://test.testserver.com/PriceAvailability";

$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);


print_r($output);

回答by senanqerib

We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.

我们可以使用 PHP cURL 库来生成简单的 HTTP POST 请求。以下示例向您展示了如何使用 cURL 创建一个简单的 SOAP 请求。

Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.

创建soap-server.php,它将SOAP 请求写入web 文件夹中的soap-request.xml。

We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.

Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.


<?php
  $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
  $f = fopen("./soap-request.xml", "w");
  fwrite($f, $HTTP_RAW_POST_DATA);
  fclose($f);
?>


The next step is creating the soap-client.php which generate the SOAP request using the cURL library and send it to the soap-server.php URL.

<?php
  $soap_request  = "<?xml version=\"1.0\"?>\n";
  $soap_request .= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n";
  $soap_request .= "  <soap:Body xmlns:m=\"http://www.example.org/stock\">\n";
  $soap_request .= "    <m:GetStockPrice>\n";
  $soap_request .= "      <m:StockName>IBM</m:StockName>\n";
  $soap_request .= "    </m:GetStockPrice>\n";
  $soap_request .= "  </soap:Body>\n";
  $soap_request .= "</soap:Envelope>";

  $header = array(
    "Content-type: text/xml;charset=\"utf-8\"",
    "Accept: text/xml",
    "Cache-Control: no-cache",
    "Pragma: no-cache",
    "SOAPAction: \"run\"",
    "Content-length: ".strlen($soap_request),
  );

  $soap_do = curl_init();
  curl_setopt($soap_do, CURLOPT_URL, "http://localhost/php-soap-curl/soap-server.php" );
  curl_setopt($soap_do, CURLOPT_CONNECTTIMEOUT, 10);
  curl_setopt($soap_do, CURLOPT_TIMEOUT,        10);
  curl_setopt($soap_do, CURLOPT_RETURNTRANSFER, true );
  curl_setopt($soap_do, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($soap_do, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($soap_do, CURLOPT_POST,           true );
  curl_setopt($soap_do, CURLOPT_POSTFIELDS,     $soap_request);
  curl_setopt($soap_do, CURLOPT_HTTPHEADER,     $header);

  if(curl_exec($soap_do) === false) {
    $err = 'Curl error: ' . curl_error($soap_do);
    curl_close($soap_do);
    print $err;
  } else {
    curl_close($soap_do);
    print 'Operation completed without any errors';
  }
?>


Enter the soap-client.php URL in browser to send the SOAP message. If success, Operation completed without any errors will be shown and the soap-request.xml will be created.

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
  <soap:Body xmlns:m="http://www.example.org/stock">
    <m:GetStockPrice>
      <m:StockName>IBM</m:StockName>
    </m:GetStockPrice>
  </soap:Body>
</soap:Envelope>


Original - http://eureka.ykyuen.info/2011/05/05/php-send-a-soap-request-by-curl/

回答by Filip Ekberg

You might want to look hereand here.

你可能想看看这里这里

A Little code example from the first link:

第一个链接中的一个小代码示例:

<?php
// include the SOAP classes
require_once('nusoap.php');
// define parameter array (ISBN number)
$param = array('isbn'=>'0385503954');
// define path to server application
$serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter';
//define method namespace
$namespace="urn:xmethods-BNPriceCheck";
// create client object
$client = new soapclient($serverpath);
// make the call
$price = $client->call('getPrice',$param,$namespace);
// if a fault occurred, output error info
if (isset($fault)) {
        print "Error: ". $fault;
        }
else if ($price == -1) {
        print "The book is not in the database.";
} else {
        // otherwise output the result
        print "The price of book number ". $param[isbn] ." is $". $price;
        }
// kill object
unset($client);
?>

回答by Saber Daagi

If the XML have identities with same name in different levels there is a solution. You don′t have to ever submit a raw XML (this PHP SOAP object don′t allows send a RAW XML), so you have to always translate your XML to a array, like the example below:

如果 XML 在不同级别具有相同名称的标识,则有一个解决方案。您不必提交原始 XML(此 PHP SOAP 对象不允许发送原始 XML),因此您必须始终将 XML 转换为数组,如下例所示:

$originalXML = "
<xml>
  <firstClient>
      <name>someone</name>
      <adress>R. 1001</adress>
  </firstClient>
  <secondClient>
      <name>another one</name>
      <adress></adress>
  </secondClient>
</xml>"

//Translate the XML above in a array, like PHP SOAP function requires
$myParams = array('firstClient' => array('name' => 'someone',
                                  'adress' => 'R. 1001'),
            'secondClient' => array('name' => 'another one',
                                  'adress' => ''));

$webService = new SoapClient($someURL);
$result = $webService->someWebServiceFunction($myParams);

or

或者

$soapUrl = "http://privpakservices.schenker.nu/package/package_1.3/packageservices.asmx?op=SearchCollectionPoint";

$xml_post_string = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><SearchCollectionPoint xmlns="http://privpakservices.schenker.nu/"><customerID>XXX</customerID><key>XXXXXX-XXXXXX</key><serviceID></serviceID><paramID>0</paramID><address>Riksv?gen 5</address><postcode>59018</postcode><city>Mantorp</city><maxhits>10</maxhits></SearchCollectionPoint></soap12:Body></soap12:Envelope>';

$headers = array(
"POST /package/package_1.3/packageservices.asmx HTTP/1.1",
"Host: privpakservices.schenker.nu",
"Content-Type: application/soap+xml; charset=utf-8",
"Content-Length: ".strlen($xml_post_string)
); 

$url = $soapUrl;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch); 
curl_close($ch);

$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);

$parser = simplexml_load_string($response2);

回答by Cato Minor

Below is a quick example of how to do this (which best explained the matter to me) that I essentially found at this website. That website link also explains WSDL, which is important for working with SOAP services.

下面是我基本上在这个网站上找到的如何做到这一点的快速示例(这对我最好地解释了这个问题)。该网站链接还解释了 WSDL,这对于使用 SOAP 服务很重要。

However, I don't think the API address they were using in the example below still works, so just switch in one of your own choosing.

但是,我认为他们在下面的示例中使用的 API 地址仍然有效,因此只需切换到您自己选择的一个即可。

$wsdl = 'http://terraservice.net/TerraService.asmx?WSDL';

$trace = true;
$exceptions = false;

$xml_array['placeName'] = 'Pomona';
$xml_array['MaxItems'] = 3;
$xml_array['imagePresence'] = true;

$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$response = $client->GetPlaceList($xml_array);

var_dump($response);