php.de

php.de (http://www.php.de/)
-   PHP-Fortgeschrittene (http://www.php.de/php-fortgeschrittene/)
-   -   [Erledigt] Php - soap - delphi (http://www.php.de/php-fortgeschrittene/4618-erledigt-php-soap-delphi.html)

10.07.2004 03:00

[Erledigt] Php - soap - delphi
 
@all

Ich möchte voarausschicken, das meine PHP Kentnisse im Gegensatz zu meinen Delphi Kenntnissen weit zurückstehen und wahrscheinlich aus diesem Grunde meine Schwierigkeiten resultieren.

Zum Problem:

Ich möchte einen PHP-Webservice erstellen und mit einem Delphi-Client ansprechen.

Zu diesem Zweck habe ich eine WSDL-Datei generiert (erledigt Delphi automatisch) einen Webservice sowie einen Client in Delphi geschrieben und die Funktion überprüft.

Dann habe ich die Umsetzung als PHP-Webservice in Angriff genommen, aber leider erhalte ich nur folgenden Response:

Code:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Client</faultcode><faultstring>looks like we got &quot;Body&quot; with several functions call</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

Der Request der an den Service gerichtet ist:

Code:

Soap-Method: Signup
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:NS2="urn:FloSrvIntf"><NS1:Signup xmlns:NS1="urn:FloSrvIntf-IFloSrv"><SignupData href="#1"/></NS1:Signup><NS2:TSignupData id="1"><Username>Test</Username><Password>NoPassword</Password></NS2:TSignupData></SOAP-ENV:Body></SOAP-ENV:Envelope>

Die zugehörige WSDL-Datei:

Code:

<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="IFloSrvservice" targetNamespace="http://tempuri.org/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns1="urn:FloSrvIntf">
  <types>
    <xs:schema targetNamespace="urn:FloSrvIntf" xmlns="urn:FloSrvIntf">
      <xs:complexType name="TSignupData">
        <xs:sequence>
          <xs:element name="Username" type="xs:string"/>
          <xs:element name="Password" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </types>
  <message name="Signup0Request">
    <part name="SignupData" type="ns1:TSignupData"/>
  </message>
  <message name="Signup0Response">
    <part name="return" type="xs:boolean"/>
  </message>
  <portType name="IFloSrv">
    <operation name="Signup">
      <input message="tns:Signup0Request"/>
      <output message="tns:Signup0Response"/>
    </operation>
  </portType>
  <binding name="IFloSrvbinding" type="tns:IFloSrv">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="Signup">
      <soap:operation soapAction="urn:FloSrvIntf-IFloSrv#Signup" style="rpc"/>
      <input message="tns:Signup0Request">
        <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:FloSrvIntf-IFloSrv"/>
      </input>
      <output message="tns:Signup0Response">
        <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:FloSrvIntf-IFloSrv"/>
      </output>
    </operation>
  </binding>
  <service name="IFloSrvservice">
    <port name="IFloSrvPort" binding="tns:IFloSrvbinding">
      <soap:address location="http://localhost/flo/TestServer.php"/>
    </port>
  </service>
</definitions>

Die Delphi Typendeclaration des complexen Datentyps (automatisch generiert):

Code:

  // ************************************************************************ //
  // Namespace : urn:FloSrvIntf
  // ************************************************************************ //
  TSignupData = class(TRemotable)
  private
    FUsername: WideString;
    FPassword: WideString;
  published
    property Username: WideString read FUsername write FUsername;
    property Password: WideString read FPassword write FPassword;
  end;


Der PHP-Webservice:

Code:

<?php

  $Wsdl = 'http://localhost/flo/FloSrv.wsdl';
  $Signup = array("Username" => "", "Password" => "");
  function Signup($Signup)
  {
    if ($Signup["Username"] == "ValidatedName")
    {
      Return True;
    }
    else
    {
      Return False;
    }
  }
  ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
  $server = new SoapServer($Wsdl);
  $server->addFunction("Signup");
  $server->handle();
?>

Bei einfachen Datentypen wie Strings, Integer oder ähnliches funktioniert alles einwandfrei. Das Problem liegt meiner Vermutung nach im Complexen Datentyp.

Schon einmal ein herzliches Dankeschön vorab für eure Hilfe.

Highway

11.07.2004 00:57

hi,

worin genau liegt nun dein problem ?

das du z.b. keine complexen datentypen darüber schicken kannst ?

greetings,
warl0rd

11.07.2004 10:54

@warl0rd

Exakt! Das ist genau das Problem. :(

11.07.2004 12:21

hi,

um z.b. ein array per webservices zu übertragen solltest do folgendes machen....

Code:

<?php

function GETstmt( $sql )
{
        $data = "";
        $result = "";
       
        $db_host = "";       
        $db_user = "";
        $db_pass = "";
        $db      = "";
       
        $conn  = mysql_connect( $db_host, $db_user, $db_pass );
        mysql_select_db( $db );
        $query = mysql_query( $sql );
       
        $i=0;
            while( $result = mysql_fetch_object( $query ))
            {
                      $data[$i] = $result;
                      $i++;
            }
        return $data;
}

include( "soap/Server.php" );
$server  = new SOAP_Server();
$server->_auto_translation = TRUE;
$service = new Service();
$server->addObjectMap( $service, "urn:soapservice");

if( isset( $_SERVER["REQUEST_METHOD"] ) &&
          $_SERVER["REQUEST_METHOD"] == "POST" )
{
        $server->Service( $HTTP_RAW_POST_DATA );
}
else
{
        include( "soap/Disco.php" );
        $disco = new SOAP_DISCO_Server( $server, "Bezeichnung" );
        if( isset( $_SERVER["QUERY_STRING"] ) &&
        strcasecmp( $_SERVER["QUERY_STRING"], "wsdl" ) == 0 )
        {
                header("Content-type: text/xml");
                print $disco->getWSDL();
        }
}


Class Service
{
        var $__dispatch_map = array();
        var $data;
       
        function Service()
        {
               
                $this->__dispatch_map["ShowNews"] =
                array( "in"  => array( "id" => "string" ),
                      "out" => array( "meldung" => "string" ) );
        }
       
        function __dispatch( $methode )
        {
                if( isset( $this->__dispatch_map[ $methode ] ) )
                {
                        return $this->__dispatch_map[ $methode ];
                }
                else
                {
                        return NULL;
                }       
        }
       
               
        function ShowNews( $id )
        {
                $data = GETstmt( "SELECT meldung FROM news WHERE id = '" . $id . "'" );
                if( !$data )
                {
                        return "Keinen Eintrag gefunden";
                }
                else
                {
                        $ret->array = $data[0]->meldung;
                        return $ret;
                }
        }
       

}

?>

siehe bei der Funktion ShowNews() das return $ret; da wird vorher die Variable $ret->array mit einem Array gefüllt....

hab dir mal den meinen kompl. source geschickt damit man alles besser sehen kann...

und die abfrage der funktion sieht dann in php so aus:

Code:

<?php

include( "soap/Client.php" );
$wsdl    = new SOAP_WSDL( "http://localhost/test/wsdlserver.php?wsdl" );
$proxy    = $wsdl->getProxy();

$news = $proxy->ShowNews( "1" );
print( $news->array );

?>

kopier dir am besten mal beide codeteile und spiel damit rum, ist im prinzip ganz einfach z.b. ein array oder ähnliches per WebService weiterzugeben oder zu verarbeiten...

greetings,
warl0rd

11.07.2004 12:46

@warl0rd

Erst mal herzlichen Dank.

Mich beschleicht aber das Gefühl, dass wir ein wenig aneinander vorbeireden.

Ich habe nicht erwähnt, das ich PHP 5 benutze (native SOAP support).

Den Code den du gepostet hast sieht mir nach PHP 4 Code aus wenn ich mich nicht irre.

Vielleicht hilft die Fehlermeldung weiter:


Zitat:

looks like we got "Body" with several functions call
Unklar ist auch warum die Konstellationen:

Delphi-Service / Delphi-Client - funktioniert
Delphi-Service / PHP-Client - funktioniert
PHP-Service / PHP-Client - funktioniert
PHP-Service / Delphi-Client - FEHLER (Bei komplexen Datentypen)
PHP-Service / Delphi-Client - funktioniert (Bei einfachen Datentypen)

und das wohlgemerkt immer mit der gleichen WSDL-Datei. :(

Ich habe auch mit Absicht nichts relevantes hart kodiert, damit es mit der Definition der Datentype keinen Ärger gibt.

Das der Fehler im Delphi-Client liegt ist eher unwahrscheinlich, da er in Verbindung mit dem Delphi-Service und auch fremden, im Netz stehenden, Werservices funktioniert. (Auch mit komplexen Datentypen)

Ich gehe fest von einer missinterpretation der Daten im PHP-Service aus, weil ich da etwas falsch gemacht habe. :(

Ich habe im obenstehenden Posting den SOAP-Request gepostet. Kann aber keinen Fehler entdecken. Das ist für mich SOAP Konform.

Trotzdem weißt der PHP-Service den Request mit einer Fehlermeldung ab!? :?

Da hänge ich nun schon seit 3 Tagen dran und finde keine Lösung, auch nicht im Netz. :(


Alle Zeitangaben in WEZ +2. Es ist jetzt 22:08 Uhr.

Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0