2011-10-13 88 views
9

我試圖創建在PHP中使用本地SoapServer的類簡單的SOAP Web服務:http://www.php.net/manual/en/class.soapserver.phpPHP 5 SoapServer的用法?

但是,文檔是這個類很差,我對如何創建一個服務器不知道,只是一個客戶端。任何人都可以提供一些內容或示例代碼?

+1

2點要注意,可以節省您的時間;首先,花點時間瞭解這個bug:https://bugs.php.net/bug.php?id = 49169;其次,不要依賴模式驗證工作,根據我的經驗,並不是所有的XML模式規則都被檢查過。 – Robin

回答

9

我也一直在努力,尤其是獲得與.Net客戶端配合使用的代碼。我發現了一些適用於PHP客戶端的示例,但是當我嘗試從.Net客戶端調用服務時,這些示例往往失敗。我仍然爲此而努力,所以我這個問題,要求與返回一個字符串值,一個簡單的PHP SoapServer的例子幫助:

String values returned by PHP SoapServer not received by .Net client

不過,雖然我不能獲得工作這個基本的例子中,我設法得到了一個返回一個自定義對象數組的例子,所以我將在這裏分享這個例子,希望對其他人有所幫助。這個例子定義了一個單一的操作getUsers這需要一個字符串參數消息,只是爲了演示消息傳遞。該操作返回一個數組用戶對象。對象也有一個字段消息其中我將收到的值傳回服務,僅用於測試目的。我會發布完整的例子; wsdl文檔,PHP服務器代碼和C#客戶端代碼。

WSDL文檔

<?xml version="1.0" encoding="UTF-8"?> 
<wsdl:definitions 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
    xmlns:tns="http://test-uri/soap/export/" 
    xmlns:s="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
    targetNamespace="http://test-uri/soap/export/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> 

<wsdl:types> 
<s:schema targetNamespace="http://test-uri/soap/export/" elementFormDefault="qualified"> 
    <s:import namespace="http://microsoft.com/wsdl/types/"/> 

    <s:element name="getUsers"> 
     <s:complexType> 
      <s:sequence> 
       <s:element minOccurs="1" maxOccurs="1" name="message" type="s:string"/> 
      </s:sequence> 
     </s:complexType> 
    </s:element> 

    <s:element name="getUsersResponse"> 
     <s:complexType> 
      <s:sequence> 
       <s:element name="getUsersArray" type="tns:getUsersArray"/> 
      </s:sequence> 
     </s:complexType> 
    </s:element> 

    <s:complexType name="getUsersArray"> 
     <s:sequence> 
      <s:element minOccurs="0" maxOccurs="unbounded" name="User" nillable="true" type="tns:User" /> 
     </s:sequence> 
    </s:complexType> 

    <s:complexType name="User"> 
     <s:sequence> 
      <s:element minOccurs="1" maxOccurs="1" name="id" type="s:string"/> 
      <s:element minOccurs="1" maxOccurs="1" name="firstname" type="s:string"/> 
      <s:element minOccurs="1" maxOccurs="1" name="surname" type="s:string"/> 
      <s:element minOccurs="1" maxOccurs="1" name="message" type="s:string"/> 
     </s:sequence> 
    </s:complexType> 
</s:schema> 
</wsdl:types> 

<wsdl:message name="getUsersSoapIn"> 
<wsdl:part name="parameters" element="tns:getUsers"/> 
</wsdl:message> 
<wsdl:message name="getUsersSoapOut"> 
<wsdl:part name="parameters" element="tns:getUsersResponse"/> 
</wsdl:message> 

<wsdl:portType name="TestSoap"> 
<wsdl:operation name="getUsers"> 
    <wsdl:documentation xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'> 
     Function ("getUsers") 
    </wsdl:documentation> 
    <wsdl:input message="tns:getUsersSoapIn"/> 
    <wsdl:output message="tns:getUsersSoapOut"/> 
</wsdl:operation> 
</wsdl:portType> 

<wsdl:portType name="TestSoap12"> 
<wsdl:operation name="getUsers"> 
    <wsdl:documentation xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'> 
     Function ("getUsers") 
    </wsdl:documentation> 
    <wsdl:input message="tns:getUsersSoapIn"/> 
    <wsdl:output message="tns:getUsersSoapOut"/> 
</wsdl:operation> 
</wsdl:portType> 

<wsdl:binding name="TestSoap" type="tns:TestSoap"> 
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/> 
<wsdl:operation name="getUsers"> 
    <soap:operation soapAction="http://test-uri/soap/export/getUsers" style="document"/> 
    <wsdl:input> 
     <soap:body use="literal"/> 
    </wsdl:input> 
    <wsdl:output> 
     <soap:body use="literal"/> 
    </wsdl:output> 
</wsdl:operation> 
</wsdl:binding> 

<wsdl:binding name="TestSoap12" type="tns:TestSoap12"> 
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/> 
<wsdl:operation name="getUsers"> 
    <soap12:operation soapAction="http://test-uri/soap/export/getUsers" style="document"/> 
    <wsdl:input> 
     <soap12:body use="literal"/> 
    </wsdl:input> 
    <wsdl:output> 
     <soap12:body use="literal"/> 
    </wsdl:output> 
</wsdl:operation> 
</wsdl:binding> 

<wsdl:service name="TestService"> 
<wsdl:port name="TestPort" binding="tns:TestSoap"> 
    <soap:address location="http://url/to/test_server.php"/> 
</wsdl:port> 
<wsdl:port name="TestSoap12" binding="tns:TestSoap12"> 
    <soap12:address location="http://url/to/test_server.php"/> 
</wsdl:port> 
</wsdl:service> 

</wsdl:definitions> 

PHP服務器代碼

<?php 
function getUsers($args) { 
    $args = (array)$args; 
    return array("getUsersArray" => array( 
             array("id"=>"1", 
              "firstname"=>"Barney", 
              "surname"=>"Rubble", 
              "message"=>$args["message"]), 
             array("id"=>"2", 
              "firstname"=>"Fred", 
              "surname"=>"Flintstone", 
              "message"=>$args["message"]) 
            ) 
       ); 
} 
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache 
$server = new SoapServer("test.wsdl"); 
$server->addFunction("getUsers"); 
try { 
    $server->handle(); 
} 
catch (Exception $e) { 
    $server->fault('Sender', $e->getMessage()); 
} 
?> 

C#客戶端代碼

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      WebReference.TestService srv = new WebReference.TestService(); 
      WebReference.User[] users = srv.getUsers("says hello"); 
      foreach (WebReference.User user in users) 
      { 
       MessageBox.Show(user.firstname+" "+user.message); 
      } 
     } 
    } 
} 

就是這樣。我希望這個例子對別人有用,並節省他們花費我的時間!

+0

只是爲了跟上這一點。我還設法得到了一個使用PHP soap服務的例子,該服務返回一個* single *對象而不是一個數組。取而代之的是從WSDL中刪除_getUsersArray_ _c​​omplexType_,並用_User_替換這個複雜類型的引用。然後在服務器代碼中,擺脫User數組的一個數組和包裝數組。所以像這樣:return array(「getUsersArray」=> array(「id」=>「1」,「firstname」=>「Barney」,「surname」=>「Rubble」,「message」=> $ args [信息」]) );顯然,_getUsersArray_可以被改變成更合適的名字;只需在WSDL中進行更改即可。 – BruceHill

2

假設你打算提供的PHP服務器功能WSDL上市, 我認爲這個鏈接教程是完美的: php servers

很簡單,短,說,你所需要的一切。

... 創建簡單的服務器後,只有你可能有問題的事情是「複雜類型」,本教程採用的「新SoapParam」建議解決的主要問題。 PHP返回的關聯數組將在某些java/asp客戶端生成器中生成預期的OBJECTS。

因此,PHP肥皂服務器將適用於phpclients,c#-asp,java-axis,soapUI ...用PHP SoapServer手動編寫wsdl的效果很好。

我不知道爲什麼,但它真的好像在網上缺乏這方面的信息......忽略了「使用文檔 - 文字而不是rpc編碼」的帖子 - 這是愚蠢的,未經證實的或者至少在開始時並不重要。

+0

鏈接已損壞。 – whoan