2009-12-02 2 views
3

PHP가 SoapClient 호출의 응답을 구문 분석하는 데 문제가 있습니다. 일부 유형의 응답의 경우 초기화 된 stdClass 객체 대신 빈 stdClass 객체의 배열을 반환합니다.PHP SoapClient 호출 응답의 응답 부분이 누락되었습니다.

서버는 tomcat6에 축 2와 함께 배포 된 Java 웹 서비스입니다.

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

    //etc... 
} 

구멍은 원시적 인 회원들과 표준 POJO입니다 : 문제가있는 서비스 호출의 자바 서명 public Course getCourseDetails(Long courseId) 코스로 정의 된 표준 POJO입니다.

PHP에서 호출 할 때 구멍 구성원은 올바른 길이의 배열이지만 각 구멍은 비어 있습니다. $soapClient->__getLastResponse()에 반환 된 XML 밖으로

$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 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

동일한 문제가 있습니다. 나는 버그에 코멘트를 추가했다. http://bugs.php.net/bug.php?id=48126 –

답변

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를 작성하여이 작업을 수행 할 수 있습니다

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

을 그리고 당신이 당신의 SOAP 호출을 만들기 위해 클라이언트를 사용할 때, 당신은 요청 및 응답 문자열을 모두 살펴볼 수 있습니다.

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

이렇게하면 응답을 PHP 개체로 변환 할 때 SoapClient가 수행중인 작업을 파악하는 데 도움이 될 수 있습니다. More info on __getLastResponse().

+0

감사합니다. 도움을 주셔서 감사합니다. 불행히도 $ soapClient -> getLastResponse()는 브라우저에서 가져온 xml과 똑같아 보이므로 문제는 파싱 문제로 남아 있습니다. –

+0

돌아 오는 구멍이 빈 StdClass 객체라고 확신합니까? 인쇄하거나 디버깅하고 있습니까? xdebug의 특정 버전에서 빈 StdClass 객체가 실제로 속성을 설정할 때 표시되는 문제가있었습니다. –

+0

인쇄 중입니다. echo $ holes [0] -> id는 var_dump ($ holes [0]) 결과가 stdClass {}가됩니다. –

0

는 여기에서 우리는 거의 일년에 가서 반 이후 ... 내 최근 반 비슷한 경험에서

이 PHP는 버그는 아니 었습니다. 웹 서비스 작성 방법 및 PHP가 출력을 읽는 방법과 관련된 문제입니다. 비슷한 문제 (올바른 XML을 반환하는 getLastResponse까지도)가 발생하여 PHP 또는 SOAP 함수에 문제가 있지만 "broken"함수의 결과가 명시 적으로 아니라는 것을 알게되었습니다 정의 커서. 나쁜 커서 정의의

예 : 좋은 커서 정의의

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 ... 
분명히 자바는 잘 "나쁜"/ 비 명시 적으로 출력을 처리 할 수 ​​있지만, PHP는 배열을 반환

null 객체의

이것이 도움이 될지 모르지만 웹 서비스 기능 출력을 위의 "좋은"방법으로 정의하면 내 문제가 해결됩니다.

+1

허 - getLastResponse가 제대로 표시 될 수있는 것처럼 보입니다. 실제로 데이터베이스 커서로 돌아가는 지점을 지나야합니다. 자바는 응답을 직렬화하고 유선을 통해 전송할 때 이미이를 정리해야합니다. –

4

비슷한 문제가있었습니다. 나는 당신이 겪은 모든 반복을 겪었습니다. 우연히 나는 PHP.INI 파일 또는 ini_set('soap.wsdl_cache', WSDL_CACHE_NONE);을 변경하여 "soap.wsdl_cache"캐싱을 비활성화했으며 다음 요청시 모든 누락 된 데이터가 채워졌습니다. 이는 "soap.wsdl_cache_ttl"이 기본적으로 60 일인 "86400"으로 설정되어 있기 때문에 쉽게 발생할 수 있습니다.

내가 발견 한 것은 비누 서버에 코드가 변경되었다는 것입니다. 새 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

브랜트에게 고맙습니다. 같은 문제가 있었는데 ini_set ('soap.wsdl_cache', WSDL_CACHE_NONE); – Jack

관련 문제