4 Stimmen

PHP SoapClient Aufruf Antwort fehlen Teile der Antwort

Ich habe Probleme mit dem PHP-Parser des Antwortaufrufs eines SoapClients. Für einige Arten von Antworten gibt es anstelle von initialisierten stdClass-Objekten Arrays leerer stdClass-Objekte.

Der Server ist ein Java-Webservice, der mit Axis2 auf Tomcat6 bereitgestellt wird. Die Java-Signatur des problematischen Service-Aufrufs lautet public Course getCourseDetails(Long courseId). Course ist ein standardmäßiges POJO, das wie folgt definiert ist:

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

    //usw...
}

Hole ist ein standardmäßiges POJO mit nur primitiven Elementen.

Bei Verwendung von PHP ist das holes-Element ein Array mit der korrekten Länge, aber jedes Loch ist leer.

$args = array();
$args["courseId"] = $courseId;
$response = $client->getCourseDetails($args);
$course = $response->return;
//course hat alle seine primitiven Elemente korrekt gesetzt: gut
$holes = $course->holes;
//holes ist ein Array mit count = 18: gut
$hole = $holes[0];
//hole ist ein leeres stdClass: schlecht

Beim Ausdrucken des zurückgegebenen XML mit $soapClient->__getLastResponse() sieht es wie die richtige Darstellung aus:

Faketown, VA
Fake Links
2003-01-02
114345
223150
335502
444345
554345
664345
774345
884345
994345
10104345
11114345
12124345
13134345
14144345
15154345
16164345
17174345
18184345
1
68.5
113
Blue

Warum sind alle Löcher leere stdClass-Objekte? Gibt es bekannte Einschränkungen für die Anzahl der Ebenen, die ein SoapClient analysiert?

0 Stimmen

Ich habe das gleiche Problem. Ich habe einen Kommentar zum Bug hinzugefügt. Ich hatte Schwierigkeiten, einen Kommentar zum Bug hinzuzufügen aufgrund von bugs.php.net/bug.php?id=48126

4voto

Brant Messenger Punkte 1421

Ich hatte ein ähnliches Problem. Ich bin durch jede Iteration gegangen, die du durchgemacht hast. Aus Versehen habe ich das Caching "soap.wsdl_cache" deaktiviert, entweder durch Änderung der PHP.INI-Datei oder ini_set('soap.wsdl_cache', WSDL_CACHE_NONE); und bei meinem nächsten Aufruf waren alle fehlenden Daten ausgefüllt. Das kann leicht passieren, weil "soap.wsdl_cache_ttl" standardmäßig auf "86400" gesetzt ist, was 60 Tage entspricht.

Was ich herausgefunden habe, war, dass der Soap-Server eine Code-Änderung hatte. Eine neue wsdl-Datei wurde erstellt. Die gecachte wsdl des Clients war zu diesem Zeitpunkt veraltet. Man würde denken, dass zumindest ein Prüfsummen-Hash von irgendeiner Art bei jedem Aufruf mitgeschickt wird, um zu überprüfen, ob sich die wsdl geändert hat, aber das ist nicht der Fall.

Um dieses Problem zu lösen und trotzdem Caching zu nutzen, habe ich eine wsdl-Datei erstellt, die ich lokal verwenden konnte.

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

    // Entferne $newWsdl, wenn nötig
    // unset($newWsdl);

Ich hoffe, das hilft dir oder jedem anderen, der vorbeikommt und ein ähnliches Problem hat.

1voto

Chris Williams Punkte 10329

Hast du das alles durch Debugging oder durch Ausgeben des Inhalts des PHP-Objekts (print_r, var_dump) herausgefunden?

Hast du versucht, den tatsächlichen SOAP-Antwortstring (nicht das PHP-Objekt) auszugeben? Dies können Sie tun, indem Sie den SoapClient mit der Debug-Option erstellen:

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

Dann, wenn du den Client benutzt, um deinen SOAP-Aufruf zu tätigen, kannst du dir sowohl die Anfrage- als auch die Antwortstrings ansehen.

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

Dies könnte Ihnen helfen herauszufinden, was der SoapClient tut, wenn er die Antwort in ein PHP-Objekt konvertiert. Mehr Informationen zu __getLastResponse().

0voto

Ryan Ahearn Punkte 7766

Dies scheint ein Fehler in PHP zu sein. http://bugs.php.net/bug.php?id=49070

Leider erlaubt mir der Fehler-Tracker nicht, dazu einen Kommentar abzugeben.

0voto

Luke H Punkte 1

Hier sind wir fast anderthalb Jahre später...

In meiner kürzlichen halbähnlichen Erfahrung war dies kein PHP-Bug. Es handelt sich um ein Problem im Zusammenhang mit der Art und Weise, wie Ihr Webservice geschrieben ist und wie PHP die Ausgabe liest. Ich hatte ein ähnliches Problem (sogar bis hin zur Rückgabe des richtigen XML durch getLastResponse) und stellte fest, dass es nicht so sehr PHP oder meine SOAP-Funktion war, die ein Problem hatte, sondern dass das Ergebnis der "defekten" Funktion kein explizit definierter Cursor war.

Beispiel für eine schlechte Cursor-Definition:

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

Beispiel für eine gute Cursor-Definition:

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

Angeblich kann Java mit der "schlechten"/nicht expliziten Ausgabe gut umgehen, aber PHP gibt ein Array von Null-Objekten zurück.

Ich weiß nicht, ob Ihnen das hilft, aber das Definieren der Ausgabe der Webservice-Funktion auf die "gute" Weise wie oben hat mein Problem behoben.

0voto

Robin Brackez Punkte 1

Um dies zu lösen, können Sie den XML-String der Soap-Antwort abrufen und in ein Objekt umwandeln.

$soapClient = new \SoapClient($wsdl, ['trace' => 1]); // trace ist wichtig, um den lastResponse-String zu erhalten
$soapClient->__call($function_name, $arguments);
$soapResponse = $soapClient->__getLastResponse();
$filteredSoapResponse = str_ireplace("soap:", "", $soapResponse); // Entfernen Sie den "soap:"-Namespace
$responseObject = simplexml_load_string($filteredSoapResponse);

Alle Daten sollten im $responseObject vorliegen, auch die Daten, die Sie zuvor nicht sehen konnten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X