2009-12-02 67 views
3

我在PHP解析SoapClient調用的響應時遇到了問題。對於某些類型的答案,它返回的是空stdClass對象的數組,而不是初始化的stdClass對象。PHP SoapClient調用響應缺少答案部分

該服務器是在tomcat6上與axis2一起部署的java webservice。有問題的服務調用的Java的簽名是public Course getCourseDetails(Long courseId)場定義爲一個標準的POJO:

public class Course { 
    private Long id; 
    private List<Hole> holes; 
    private String name; 
    private String tees; 

    //etc... 
} 

洞是一個標準的POJO,只有靈長類動物的成員。

使用PHP調用時,孔成員是一個長度正確的數組,但每個孔都是空的。

$args = array(); 
$args["courseId"] = $courseId; 
$response = $client->getCourseDetails($args); 
$course = $response->return; 
//course has all of its primitive members set correctly: good 
$holes = $course->holes; 
//holes is an array with count = 18: good 
$hole = $holes[0]; 
//hole is an empty stdClass: bad 

打印出返回的XML與$soapClient->__getLastResponse()什麼樣子的正確表示:

<?xml version='1.0' encoding='utf-8'?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
<soapenv:Body> 
<ns:getCourseDetailsResponse xmlns:ns="http://webservice.golfstats"> 
<ns:return xmlns:ax21="http://datastructures.server.golfstats/xsd" xmlns:ax22="http://util.java/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ax24="http://uuid.eaio.com/xsd" xsi:type="ax21:Course"> 
<ax21:courseLocation>Faketown, VA</ax21:courseLocation> 
<ax21:courseName>Fake Links</ax21:courseName> 
<ax21:dateAdded>2003-01-02</ax21:dateAdded> 
<ax21:holes><ax21:id>1</ax21:id><ax21:number>1</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>2</ax21:id><ax21:number>2</ax21:number><ax21:par>3</ax21:par><ax21:yardage>150</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>3</ax21:id><ax21:number>3</ax21:number><ax21:par>5</ax21:par><ax21:yardage>502</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>4</ax21:id><ax21:number>4</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>5</ax21:id><ax21:number>5</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>6</ax21:id><ax21:number>6</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>7</ax21:id><ax21:number>7</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>8</ax21:id><ax21:number>8</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>9</ax21:id><ax21:number>9</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>10</ax21:id><ax21:number>10</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>11</ax21:id><ax21:number>11</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>12</ax21:id><ax21:number>12</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>13</ax21:id><ax21:number>13</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>14</ax21:id><ax21:number>14</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>15</ax21:id><ax21:number>15</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>16</ax21:id><ax21:number>16</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>17</ax21:id><ax21:number>17</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:holes><ax21:id>18</ax21:id><ax21:number>18</ax21:number><ax21:par>4</ax21:par><ax21:yardage>345</ax21:yardage></ax21:holes> 
<ax21:id>1</ax21:id> 
<ax21:rating>68.5</ax21:rating> 
<ax21:slope>113</ax21:slope> 
<ax21:tees>Blue</ax21:tees> 
</ns:return> 
</ns:getCourseDetailsResponse> 
</soapenv:Body> 
</soapenv:Envelope> 

爲什麼每個洞空stdClass的? SoapClient將解析響應的級別數是否存在限制?

+0

我有同樣的問題。我爲這個bug添加了一條評論。 由於http://bugs.php.net/bug.php?id=48126 – 2010-06-08 13:05:41

回答

0

這似乎是PHP中的一個錯誤。 http://bugs.php.net/bug.php?id=49070

不幸的是,錯誤跟蹤器不會讓我評論它。

+0

讓我知道如果http://stackoverflow.com/questions/1830801/php-soapclient-call-response-missing-parts-of-answer/5902160#5902160 –

1

你是否已經通過調試或打印出PHP對象(print_r,var_dump)的內容來完成這一切?

您是否嘗試過打印出實際的SOAP響應字符串(不是PHP對象)?你可以通過調試選項集創建SoapClient的做到這一點:當您使用的客戶端,讓您的SOAP調用

$soapClient = new SoapClient("http://your.soap.server.com/services/yourWsdl.wsdl", array("trace" => 1)); 

然後,你可以看看的請求和響應串兩者。

$response = $soapClient->getCourseDetails($params); 
$requestAsString = $soapClient->__getLastRequest(); 
$responseAsString = $soapClient->__getLastResponse(); 

這可能會幫助您找出SoapClient在將響應轉換爲PHP對象時正在執行的操作。 More info on __getLastResponse()

+0

感謝您的幫助,我無法添加評論。不幸的是,$ soapClient - > __ getLastResponse()看起來和我從瀏覽器中得到的xml非常相似,所以問題仍然是解析問題。 –

+0

你如何確定返回的洞是空的StdClass對象?你打印出來還是調試?我在使用特定版本的xdebug時遇到了問題,它們顯示空的StdClass對象實際上具有屬性設置。 –

+0

打印出來。 echo $ holes [0] - > id var_dump($ holes [0])結果stdClass {} –

0

在這裏,我們走了近一年半的時間過去了......

在我最近的半類似的經驗,這不是一個PHP錯誤。這是一個與您的web服務的編寫方式有關的問題,以及PHP如何讀取輸出。我遇到了一個類似的問題(甚至只能得到最終響應返回正確的XML),並發現它不是PHP或我的SOAP函數那麼多,但有一個問題,但「破」功能的結果不是明確的定義光標。壞光標定義的

舉例:好的遊標定義的

PROCEDURE GetBlahByBlahID(IN IN_BLAH_ID VARCHAR, IN IN_BLAHPKG VARCHAR,          
OUT result CURSOR 
) BEGIN ... 

例子:

PROCEDURE GetBlahByBlahID(IN IN_BLAH_ID VARCHAR, IN IN_BLAHPKG VARCHAR,          
OUT result CURSOR ( BLAH VARCHAR(250), 
        BLAH2 VARCHAR(250), 
        BLAH_DATE DATE, 
        BLAH3 VARCHAR(250))) BEGIN ... 

顯然,Java可以處理的「壞」 /無明確的輸出就好了,但PHP返回數組的空對象。

不確定這是否會對您有所幫助,而是將Web服務功能輸出定義爲「解決我的問題」的「良好」方式。

+1

嗯 - 似乎如果getLastResponse可以看到它,但它很好超過了實際返回到數據庫遊標的點。當Java將答案序列化並通過線路發送時,Java應該已經清除了這個問題。 –

4

我有類似的問題。我經歷了你經歷的每一次迭代。在僥倖我禁用緩存「soap.wsdl_cache」通過更改PHP.INI文件或ini_set('soap.wsdl_cache', WSDL_CACHE_NONE);並在我的下一個請求中填充所有缺少的數據。這很容易發生,因爲「soap.wsdl_cache_ttl」默認設置爲「86400」,即60天。

我發現的是,肥皂服務器有一個代碼更改。創建一個新的wsdl。客戶端的緩存wsdl在那時已經陳舊了。您會認爲,至少每種請求都會附帶一種校驗和散列,以驗證wsdl是否發生了變化,但是沒有發生變化。

要解決此問題並仍然使用緩存,我創建了一個我可以在本地使用的wsdl文件。

$cache = Services_Utilities::getCacheResource(); 
    if (!$cache->test(self::CACHE_KEY)) { 
     $data = file_get_contents($wsdl); 
     $cache->save($data, self::CACHE_KEY); 
     file_put_contents($newWsdl, $data); 
     if (file_exists($newWsdl)) { 
      $wsdl = $newWsdl; 
     } 
    } else { 
     if (file_exists($newWsdl)) { 
      $wsdl = $newWsdl; 
     } 
    } 

    // Remove $newWsdl when necessary 
    // unset($newWsdl); 

希望這可以幫助你或任何碰巧遇到類似問題的人。

+0

謝謝Brant,我曾經遇到同樣的問題,我用ini_set('soap.wsdl_cache',WSDL_CACHE_NONE)解決了這個問題。 – Jack