Pergunta

Estou tendo problemas com PHP análise de resposta de um chamada SoapClient. Para alguns tipos de respostas, é o retorno matrizes de stdClass vazio objetos em vez de inicializado stdClass objetos.

O servidor é um webservice java implantado com axis2 em tomcat6. A assinatura Java da chamada de serviço problemático é Course public Course getCourseDetails(Long courseId) é um POJO padrão definido como:

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

    //etc...
}

Hole é um POJO padrão apenas com os membros primitivos.

Quando chamado com o PHP, o elemento de furos é uma matriz com o comprimento correcto, mas cada buraco está vazio.

$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

Imprimir o XML retornado com $soapClient->__getLastResponse() o que parece ser a representação correta:

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

Por que é cada buraco um stdClass vazio? Existem limitações conhecidas do número de níveis SoapClient vai analisar uma resposta?

Foi útil?

Solução 3

Este parece ser um bug no PHP. http://bugs.php.net/bug.php?id=49070

Infelizmente, o bug tracker não vai deixar-me comentar sobre ele.

Outras dicas

Eu tive um problema semelhante. Eu passei por cada iteração você passou. Por um acaso eu desativado caching "soap.wsdl_cache" seja alterando o arquivo PHP.INI ou ini_set('soap.wsdl_cache', WSDL_CACHE_NONE); e no meu próximo pedido todos os dados em falta foi povoada. Isso pode facilmente acontecer porque o "soap.wsdl_cache_ttl" é definido como "86400", por padrão, que é de 60 dias.

O que eu descobri foi que o servidor de sabão teve uma alteração de código. Criando um novo WSDL. wsdl em cache do cliente foi envelhecer nesse ponto. Você poderia pensar que, pelo menos, um hash de soma de verificação de algum tipo sairia com cada solicitação para verificar se o wsdl tinha mudado, mas isso não acontece.

Para resolver esse problema e ainda usar o cache Eu criei um arquivo WSDL que eu poderia consumir localmente.

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

Espero que isso ajude você ou qualquer outra coisa que acontece para parar perto e têm um problema semelhante.

Você descobrir isso tudo por depuração ou imprimir o conteúdo do objeto PHP (print_r, var_dump)?

Você tentou imprimir a seqüência de resposta SOAP real (não o objeto PHP)? Você pode fazer isso criando o SoapClient com o conjunto de opção de depuração:

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

Em seguida, quando você usa o cliente para fazer a sua chamada SOAP, você pode dar uma olhada em ambos o pedido e as cordas de resposta.

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

Isso pode ajudá-lo a descobrir o que SoapClient está fazendo quando é converter a resposta a um objeto PHP. Mais informações sobre __getLastResponse () .

Aqui vamos nós quase um ano e meio depois ...

Na minha experiência recente semi-similar este não era um bug php. É uma questão relacionada com a forma como o seu webservice está escrito e como PHP lê a saída. Eu estava enfrentando um problema semelhante (mesmo para baixo para getLastResponse retornar o XML correto) e veio para descobrir que ele não era tanto PHP ou minha função SOAP que tinha um problema, mas que o resultado da função "quebrado" não era um explicitamente cursor definido.

Exemplo de definição do cursor ruim:

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

Exemplo de boa definição cursor:

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

Aparentemente Java pode lidar com a saída explícita "mau" / não muito bem, mas PHP retorna uma matriz de objetos nulos.

Não sei se isso irá ajudá-lo, mas a definição da função de produção de serviços web como o "bom" caminho acima fixado o meu problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top