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

PHP 內建 SOAP Client 實戰:WSDL 解析、多種呼叫方式與除錯技巧

     編輯:PHP 相關知識

前言:為何選擇內建 SoapClient?

PHP 5 起內建 SoapClient,無需額外擴展,支援 WSDL 1.1、SOAP 1.1/1.2,適合快速整合企業級 Web Service(ERP、CRM、物流追蹤、金流通知)。本文以「IP 轉國家」公開服務為例,示範從建立客戶端到多種呼叫風格的完整流程。

建立客戶端與啟用追蹤

<?php
$wsdl = 'https://www.ecubicle.net/iptocountry.asmx?wsdl';
$client = new SoapClient($wsdl, [
    'trace'      => true,           // 關鍵:啟用請求/回應記錄
    'exceptions' => true,           // 拋出 SoapFault 異常而非回傳 false
    'cache_wsdl' => WSDL_CACHE_MEMORY, // 開發期建議 MEMORY,正式環境可用 WSDL_CACHE_DISK
    // 'login' => 'user', 'password' => 'pass', // HTTP Basic Auth 若需
]);
?>

檢視可用方法(開發期必做)

<?php
print_r($client->__getFunctions());
/* 典型輸出:
Array (
    [0] => FindCountryAsStringResponse FindCountryAsString(FindCountryAsString $parameters)
    [1] => FindCountryAsStringResponse FindCountryAsString(string $V4IPAddress)
)
*/

四種呼叫風格對照(推薦風格 2)

<?php
$ip = '64.156.132.140';

// 風格 1:__soapCall 完整控制(最繁瑣)
$result = $client->__soapCall('FindCountryAsString', [
    'FindCountryAsString' => ['V4IPAddress' => $ip]
]);
echo $result->FindCountryAsStringResult;

// 風格 2:魔術方法直呼(最直觀,推薦)
$result = $client->FindCountryAsString(['V4IPAddress' => $ip]);
echo $result->FindCountryAsStringResult;

// 風格 3:SoapParam 封裝參數(需對應 WSDL 訊息部件名)
$param = new SoapParam(['V4IPAddress' => $ip], 'FindCountryAsStringSoapIn');
$result = $client->__soapCall('FindCountryAsString', [$param]);
echo $result->FindCountryAsStringResult;

// 風格 4:SoapParam + 魔術方法
$param = new SoapParam(['V4IPAddress' => $ip], 'FindCountryAsStringSoapIn');
$result = $client->FindCountryAsString($param);
echo $result->FindCountryAsStringResult;
?>

除錯三板斧:trace 開啟後可用

<?php
try {
    $result = $client->FindCountryAsString(['V4IPAddress' => $ip]);
} catch (SoapFault $e) {
    // 1. 最後發送的 XML 請求
    echo '<h3>Request XML</h3><pre>'.htmlspecialchars($client->__getLastRequest()).'</pre>';
    // 2. 最後請求 HTTP Header
    echo '<h3>Request Headers</h3><pre>'.htmlspecialchars($client->__getLastRequestHeaders()).'</pre>';
    // 3. 最後收到的 XML 回應
    echo '<h3>Response XML</h3><pre>'.htmlspecialchars($client->__getLastResponse()).'</pre>';
    // 4. 最後回應 HTTP Header
    echo '<h3>Response Headers</h3><pre>'.htmlspecialchars($client->__getLastResponseHeaders()).'</pre>';
    throw $e;
}

常見坑點與解決方案

現象原因解決
找不到函式/參數錯誤 WSDL 定義複雜型別、命名空間 用 __getTypes() 檢視型別結構,對應建立 SoapVar 或陣列
編碼亂碼 服務端非 UTF-8 建立客戶端時加 'encoding'=>'ISO-8859-1' 或轉碼
憑證驗證失敗 HTTPS 自簽憑證 加 'stream_context'=>stream_context_create(['ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]])(僅測試環境)
效能慢 每次請求下載 WSDL 正式環境設 'cache_wsdl'=>WSDL_CACHE_DISK,並定期清理 /tmp/wsdl-*

進階:自訂 SoapClient 註入 HTTP Header(如 Token 驗證)

<?php
class AuthSoapClient extends SoapClient {
    private string $token;
    public function __construct($wsdl, array $options, string $token) {
        $this->token = $token;
        parent::__construct($wsdl, $options);
    }
    protected function __doRequest($request, $location, $action, $version, $one_way = 0) {
        $headers = [
            "Authorization: Bearer {$this->token}",
            "Content-Type: text/xml; charset=utf-8",
        ];
        return parent::__doRequest($request, $location, $action, $version, $one_way, $headers);
    }
}
// 使用
$client = new AuthSoapClient($wsdl, ['trace'=>true], 'my-jwt-token');

總結

PHP SoapClient 功能完整但參數傳遞靈活度高導致易混淆。建議流程:1. 開啟 trace 2. 用 __getFunctions/__getTypes 理解結構 3. 先用魔術方法直呼 4. 失敗時用 __getLastRequest 對照 WSDL 調整參數結構。掌握此流程,整合任何 SOAP 服務皆可游刃有餘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved