PHP 5 內建 ext/soap (C 實現,效能優於純 PHP 的 NuSOAP),支援 SOAP 1.1/1.2、WSDL 自動解析、類映射、異常處理。本文從協議基礎到雙端完整實作,並解決常見 WSDL 生成與命名空間衝突問題。
Header (擴展:認證、事務) 與 Body (實際 payload)。literal 模式,型別對應 XML Schema (xsd:string, xsd:int, 陣列、複雜型別)。SOAPAction Header 指定操作。<?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 (舊文常見錯誤)。SoapFault 回傳標準 SOAP Fault,客戶端可 catch (SoapFault $e)。<?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()}";
}
?>
PHP 無內建動態 WSDL 生成,**必須離線生成**。推薦工具:
soap:address location (實際服務 URL)。composer require wsdl2phpgenerator/wsdl2phpgenerator 由類反向生成。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>
message/part name,位置參數會失敗。classmap 選項將 XML 型別對應到 PHP 類:['classmap' => ['UserType' => 'App\\DTO\\User']]。targetNamespace 需唯一;客戶端可用 SoapClient(..., ['uri' => 'custom_ns']) 區分。'cache_wsdl' => WSDL_CACHE_NONE 或刪除 /tmp/wsdl-*。php.ini 取消註解 extension=soap,需 libxml2 支援。wsHttpBinding (WS-Security、可靠傳訊) **不相容** PHP SOAP;需改 basicHttpBinding。nillable="true" 欄位 PHP 端傳 null 或不傳該鍵。xsd:dateTime 對應 PHP DateTime 物件或 'YYYY-MM-DDTHH:MM:SS' 字串。