首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP SOAP 擴展實現 WebService 客戶端與伺服端完整教學

     編輯:PHP 相關知識

PHP SOAP 擴展實現 WebService 客戶端與伺服端完整教學

PHP 5 內建 ext/soap (C 實現,效能優於純 PHP 的 NuSOAP),支援 SOAP 1.1/1.2、WSDL 自動解析、類映射、異常處理。本文從協議基礎到雙端完整實作,並解決常見 WSDL 生成與命名空間衝突問題。

一、SOAP 協議核心概念速覽

  • Envelope:根元素,含 Header (擴展:認證、事務) 與 Body (實際 payload)。
  • WSDL:Web Services Description Language,XML 定義服務介面 (操作、訊息、型別、綁定、端點)。**PHP SOAP 要求 WSDL 預先存在** (不像 Java 可動態生成)。
  • 資料編碼:預設 literal 模式,型別對應 XML Schema (xsd:string, xsd:int, 陣列、複雜型別)。
  • 傳輸:HTTP POST,SOAPAction Header 指定操作。

二、伺服端實作 (SoapServer)

<?php
// math.wsdl 需預先生成 (見下文)
class MathService {
    /** @param int $a @param int $b @return int */
    public function add($a, $b) { return $a + $b; }
    
    /** @param int $a @param int $b @return int */
    public function sub($a, $b) { return $a - $b; }
    
    /** @param int $a @param int $b @return float */
    public function div($a, $b) {
        if ($b == 0) throw new SoapFault('Server', 'Division by zero');
        return $a / $b;
    }
}

$server = new SoapServer('math.wsdl', ['soap_version' => SOAP_1_2]);
$server->setClass('MathService'); // 將類掛載為服務
$server->handle(); // 處理請求
?>

關鍵點:

  • setClass 而非 addClass (舊文常見錯誤)。
  • 方法需 **PHPDoc @param/@return** 供 WSDL 生成工具解析型別。
  • 拋出 SoapFault 回傳標準 SOAP Fault,客戶端可 catch (SoapFault $e)。

三、客戶端呼叫 (SoapClient)

<?php
try {
    $client = new SoapClient('https://localhost/soap/math.wsdl', [
        'trace'      => 1,           // 除錯用:$client->__getLastRequest()
        'exceptions' => true,        // 拋出 SoapFault
        'cache_wsdl' => WSDL_CACHE_MEMORY, // 開發關閉快取
    ]);
    
    // 呼叫方式:命名參數陣列 (鍵需與 WSDL message part 名一致)
    $result = $client->div(['a' => 8, 'b' => 2]);
    echo "Result: {$result->divResult}"; // 物件屬性名 = 操作名 + Result
    
} catch (SoapFault $e) {
    echo "SOAP Fault: {$e->getMessage()}";
}
?>

四、WSDL 生成與部署 (關鍵難點)

PHP 無內建動態 WSDL 生成,**必須離線生成**。推薦工具:

  • Zend Studio / PhpStorm:右鍵類 → Generate WSDL,需正確填寫 soap:address location (實際服務 URL)。
  • wsdl-php-generator (Composer 套件):composer require wsdl2phpgenerator/wsdl2phpgenerator 由類反向生成。
  • 手寫/修改:理解 WSDL 結構 (types, message, portType, binding, service) 手動調整。

WSDL 片段關鍵配置:

<service name="MathService">
  <port binding="typens:MathBinding" name="MathPort">
    <soap:address location="https://localhost/soap/server.php"/> <!-- 必須指向實際處理端點 -->
  </port>
</service>

五、常見坑點與解決方案

  1. 命名參數強制:PHP SoapClient **要求關聯陣列鍵名** 對應 WSDL message/part name,位置參數會失敗。
  2. 複雜型別映射:用 classmap 選項將 XML 型別對應到 PHP 類:['classmap' => ['UserType' => 'App\\DTO\\User']]。
  3. 命名空間衝突:多服務合併部署時,WSDL targetNamespace 需唯一;客戶端可用 SoapClient(..., ['uri' => 'custom_ns']) 區分。
  4. WSDL 快取:開發期設 'cache_wsdl' => WSDL_CACHE_NONE 或刪除 /tmp/wsdl-*。
  5. 大量資料/附件:SOAP 不適合傳大檔;改用 MTOM (Message Transmission Optimization Mechanism) 或改 REST + multipart。
  6. Windows PHP 啟用 SOAP:php.ini 取消註解 extension=soap,需 libxml2 支援。

六、對接 .NET / Java 服務實戰提醒

  • .NET WCF 預設 wsHttpBinding (WS-Security、可靠傳訊) **不相容** PHP SOAP;需改 basicHttpBinding。
  • Java (CXF/Axis2) 通常相容;注意 nillable="true" 欄位 PHP 端傳 null 或不傳該鍵。
  • 日期時間:WSDL xsd:dateTime 對應 PHP DateTime 物件或 'YYYY-MM-DDTHH:MM:SS' 字串。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved