iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Software Development

一套真實運作中的 Laravel 系統,拆解它的原生機制系列 第 18

Day 18:跟外部系統對接——SOAP 協議在 2026 年怎麼用 PSR-18 包起來用

  • 分享至 

  • xImage
  •  

前言:SOAP 已經是老技術了,為什麼現在還要學怎麼接?

「SOAP 不是很多年前的技術了嗎?現在講外部整合,大家講的都是 REST 或 GraphQL,為什麼還要花一篇講 SOAP?」

答案很現實:你不一定能選擇要接什麼協議。這個系統要對接的外部系統,是一個已經運作多年、不受這邊控制的既有系統,它對外開放的介面就是 SOAP,沒有商量的餘地。今天要看的不是「SOAP 語法怎麼寫」,是「在一個現代化的 Laravel 專案裡,怎麼用符合當代慣例的方式,把一個老派協議包裝起來」。

今日目標

  • 理解為什麼「協議老舊」不代表「接線方式也要老舊」
  • 看這個系統怎麼用 phpro/soap-client 搭配 PSR-18 的傳輸層來接 SOAP
  • 認識 Factory::factory() 這種組裝方式,把建構複雜度收斂到一個地方
  • 建立「不管協議多舊,介面化的原則不變」的意識

本文主體

SOAP 依然存在,只是接的方式可以現代化

不少既有的機構級系統(校務、金融、政府系統),因為建置年代早、又要求高度穩定性,至今仍然對外提供 SOAP 介面。要跟這類系統整合,沒辦法要求對方換一套協議,只能想辦法在自己這一側,把 SOAP 的複雜度包裝成跟現代 HTTP client 差不多好用的樣子。

這個系統選用的是 phpro/soap-client 這個套件——它讓 SOAP 呼叫可以透過 PSR-18 相容的 HTTP client 傳輸層來發送,而不是直接依賴 PHP 原生的 SoapClient 擴充功能。這代表:昨天講的「介面化、可替換底層實作」的原則,在 SOAP 這種老派協議上一樣適用,不會因為協議本身老舊,就必須放棄現代化的架構原則。

組裝方式:把複雜度收斂進 Factory

昨天看到的 DataGatewayClientFactory::factory(),實際組裝過程大致是:接收一個 Psr18Transport 和 WSDL 位址,內部用套件提供的 Engine Factory 建出處理 SOAP 通訊細節的物件,再包一層事件分派器(讓每次 SOAP 呼叫可以被監聽、記錄),最後組出一個對外呼叫端只需要呼叫方法名稱、不需要理解底層通訊細節的 Client 物件。

這種「把建構過程的複雜度收斂進一個靜態 Factory 方法」的做法,好處是呼叫端完全不需要知道 SOAP engine、事件分派器這些底層物件怎麼兜起來——只要呼叫 DataGatewayClientFactory::factory($transport, $wsdl),就拿到一個可以直接用的 Client。這跟直接在需要的地方手動組裝一大串物件比起來,可讀性跟可維護性都好上不少。

對外呼叫端看到的樣子

從呼叫端的角度看,跟 SOAP Client 溝通就像呼叫一個普通物件的方法——例如取得某個清單資料時,呼叫端只需要 $client->getAssigners(),回傳的是解析過的 SOAP 回應物件,呼叫端完全不需要碰到底層的 XML 序列化/反序列化。這正是介面化的價值所在:對接的協議是 SOAP,但寫呼叫這段程式碼的人,體驗上跟呼叫一般的 API Client 沒有太大差別。

對照:直接處理 SOAP 底層細節 vs 包裝成乾淨的 Client 介面

呼叫端直接處理 SOAP 底層細節

$client = new SoapClient($wsdl, ['connection_timeout' => 5]);
$response = $client->__soapCall('GetAssigners', []);
// 呼叫端要理解 SOAP 特有的呼叫慣例,跟其他一般 API 整合的寫法完全不一致

透過 Factory 組裝,呼叫端只看到乾淨的方法呼叫

$client = DataGatewayClientFactory::factory($transport, $wsdl);
$assigners = $client->getAssigners();
// 呼叫端不需要知道底層是 SOAP,寫法跟呼叫任何一般物件的方法一樣

這篇想傳達的事

跟外部系統整合時,「這個外部系統用什麼協議」跟「我這邊的程式碼要寫成什麼樣子」是兩件可以分開處理的事。協議可能老舊、可能受限於外部系統,但自己這一側的架構原則——介面化、不寫死實作、把複雜度收斂到明確的組裝點——不需要因此打折扣。這也是為什麼這篇不是一篇「SOAP 語法教學」,而是想講清楚「怎麼把一個老派協議,用符合現代慣例的方式接進一個現代化的 Laravel 專案」。

今日思考題

你的專案裡有沒有需要對接一個技術比較舊、你沒辦法要求它改變的外部系統?回想一下你目前的接線方式,有沒有因為「協議本身老舊」而讓自己這一側的程式碼也跟著變得難以維護、難以測試?

今日重點回顧

  • 對接的外部系統用什麼協議,不代表自己這一側的架構原則要跟著打折扣
  • phpro/soap-client 搭配 PSR-18 傳輸層,讓 SOAP 呼叫也能走介面化、可替換底層實作的路線
  • 用靜態 Factory 方法收斂建構複雜度,讓呼叫端不需要理解底層物件怎麼兜起來
  • 對外呼叫端看到的是乾淨的方法呼叫,體驗上跟呼叫一般 API Client 沒有太大差別

明日預告

明天要看這個 SOAP 對接的一段真實演進過程——一開始只顧著「能動」,後來才補上逾時控制,這中間發生了什麼。


上一篇
Day 17:Service Container 實戰——SOAP Client 怎麼用 Factory 綁定
下一篇
Day 19:SOAP 逾時防護——從「先能動」到「補上超時控制」的真實演進
系列文
一套真實運作中的 Laravel 系統,拆解它的原生機制20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言