2009-12-02 4 views
3

У меня возникли проблемы с разбором PHP ответа на вызов SoapClient. Для некоторых типов ответов он возвращает массивы пустых объектов stdClass вместо инициализированных объектов stdClass.Ответ на вызов SoapClient PHP Отсутствующие части ответа

Сервер представляет собой веб-сервис java, развернутый с осью 2 на tomcat6. Java подпись вызова проблемной службы является public Course getCourseDetails(Long courseId) курсом является стандартной POJO определяется как:

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

    //etc... 
} 

Hole является стандартным 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

У меня такая же проблема. Я добавил комментарий к ошибке. Мне не удалось добавить комментарий к ошибке из-за 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 с включенной опцией отладки:

$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(); 

Это может помочь вам разобраться в том, что делает 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. Это проблема, связанная с тем, как написан ваш веб-сервис и как PHP читает результат. Я столкнулся с аналогичной проблемой (вплоть до getLastResponse, возвращающей правильный 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 может справиться с "плохой"/Non явный вывод просто отлично, но PHP возвращает массив нулевых объектов.

Не уверен, что это вам поможет, но определение функции веб-службы выводится как «хороший» путь выше фиксированной моей проблемы.

+1

Huh - похоже, если getLastResponse может это увидеть, это хорошо мимо точки фактического возврата к курсу базы данных. 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

Спасибо, Брант, у меня была такая же проблема, и я решил ее с помощью ini_set ('soap.wsdl_cache', WSDL_CACHE_NONE); – Jack

Смежные вопросы