問題(在 PHP5 下使用 SOAP 擴充功能時)傳輸包含物件或物件陣列的物件。巢狀物件將無法傳輸。
解決方案
這個類別是由我透過反覆試驗開發出來的。因此,這 23 行程式碼對於大多數在 PHP5 下編寫程式的開發人員來說,解決了使用 SOAP 擴充功能的命運。
<?php
/*
根據 PHP5 中 SOAP 類別的組織流程特性,我們必須將複雜物件包裝在 SoapVar 類別中。否則物件將無法正確編碼,並且無法在遠端 SOAP 處理程式上載入。
函式 "getAsSoap" 用於編碼物件以進行傳輸。編碼後即可正確傳輸。
*/
abstract class SOAPable {
public function getAsSOAP() {
foreach($this as $key=>&$value) {
$this->prepareSOAPrecursive($this->$key);
}
return $this;
}
private function prepareSOAPrecursive(&$element) {
if(is_array($element)) {
foreach($element as $key=>&$val) {
$this->prepareSOAPrecursive($val);
}
$element=new SoapVar($element,SOAP_ENC_ARRAY);
}elseif(is_object($element)) {
if($element instanceof SOAPable) {
$element->getAsSOAP();
}
$element=new SoapVar($element,SOAP_ENC_OBJECT);
}
}
}
// ------------------------------------------
// 抽象範例
// ------------------------------------------
class PersonList extends SOAPable {
protected $ArrayOfPerson; // 變數必須是 protected 或 public!
}
class Person extends SOAPable {
//任何資料
}
$client=new SoapClient("test.wsdl", array( 'soap_version'=>SOAP_1_2, 'trace'=>1, 'classmap' => array('Person' => "Person", 'PersonList' => "PersonList") ));
$PersonList=new PersonList;
// 一些操作
$PersonList->getAsSOAP();
$client->someMethod($PersonList);
?>
因此,每個要透過 SOAP 傳輸的類別都必須繼承自 SOAPable 類別。
如您在上面的程式碼中所見,函式 prepareSOAPrecursive 會在父物件或陣列中搜尋其他巢狀物件,如果找到,則會嘗試呼叫函式 getAsSOAP() 來準備巢狀物件,然後再透過 SoapVar 類別進行包裝。
所以在傳輸前的程式碼中,只需呼叫 $obj->getAsSOAP()