4

SoapClient 呼び出しの応答の PHP 解析に問題があります。一部のタイプの回答では、初期化された stdClass オブジェクトではなく、空の stdClass オブジェクトの配列が返されます。

サーバーは、tomcat6 の axis2 でデプロイされた Java Web サービスです。問題のあるサービス呼び出しの Java シグネチャはpublic Course getCourseDetails(Long courseId) Course であり、次のように定義された標準 POJO です。

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

    //etc...
}

Hole は、基本メンバーのみを持つ標準 POJO です。

PHP で呼び出すと、holes メンバーは正しい長さの配列になりますが、各 hole は空です。

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

各穴が空の標準クラスであるのはなぜですか? SoapClient が応答を解析するレベルの数に既知の制限はありますか?

4

6 に答える 6

4

同様の問題がありました。私はあなたが経験したすべての反復を経験しました。まぐれで、PHP.INIファイルを変更するかini_set('soap.wsdl_cache', WSDL_CACHE_NONE);、次のリクエストで不足しているすべてのデータが入力されることで、「soap.wsdl_cache」のキャッシュを無効にしました。これは、「soap.wsdl_cache_ttl」がデフォルトで「86400」(デフォルトでは60日)に設定されているため、簡単に発生する可能性があります。

私が見つけたのは、soapサーバーのコードが変更されていることです。新しい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);

これがあなたや他の誰かが立ち寄って同様の問題を抱えているのに役立つことを願っています。

于 2011-05-05T17:59:59.890 に答える
1

PHP オブジェクト (print_r、var_dump) の内容をデバッグまたは出力して、これをすべて把握しましたか?

(PHP オブジェクトではなく) 実際の SOAP 応答文字列を出力してみましたか? これを行うには、デバッグ オプションを設定して 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 が何をしているのかを理解するのに役立ちます。__getLastResponse() の詳細

于 2009-12-02T05:44:37.167 に答える
0

ここで私たちはほぼ1年半後に行きます...

私の最近の半類似の経験では、これはphpのバグではありませんでした。これは、Webサービスの記述方法と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は「悪い」/明示的でない出力をうまく処理できるようですが、PHPはnullオブジェクトの配列を返します。

これが役立つかどうかはわかりませんが、Webサービス関数の出力を上記の「適切な」方法として定義すると、問題が解決しました。

于 2011-03-23T18:32:30.247 に答える
0

これは PHP のバグのようです。 http://bugs.php.net/bug.php?id=49070

残念ながら、バグトラッカーではコメントできません。

于 2010-01-04T20:13:20.993 に答える