Beste programmeurs,

Als basic programmeur ben ik al 2 dagen bezig om een groot probleem op te lossen die waarschijnlijk heel simpel is voor de programmeur experts onder ons. Het volgende is er aan de hand.

Via onderstaand stukje script roep ik de status op van een bepaalde zending:


 $WebserviceClient = new SoapClient("http://xxx/App_Services/xxx.asmx?wsdl");
 $parameters= array("Username"=>$username, "Password"=>$password, "Zending"=>$zending, "Postcode"=>$postocde, "Referentie"=>$referentie);
 $WebmethodResult = $WebserviceClient->GetShipmentStatus($parameters) or die('FOUT!');


Als ik vervolgens via PRINT_R het resultaat in $WebmethodResult op het scherm toon krijg ik een response terug die begint met stdClass Object en daarna alle informatie over die bepaalde zending.

mijn print_r ziet er als volgt uit:

echo "<pre>";
  print_r($WebmethodResult);
echo "</pre>";


Als ik de BRONCODE van de code op het scherm bekijk zie ik veel code staan zoals
<MovementID>225362222</MovementID><ShipmentID>18815421</ShipmentID><CompanyID>985</CompanyID><MovementType>Afgeleverd</MovementType>

Mijn vraag is hoe ik met PHP de response ($WebmethodResult) uit de SOAP request kan benaderen zodat ik het MovementType element kan declareren in een variable waarna ik een if/else constructie kan maken zoals:


if(MovementType=="Afgeleverd"){ 
 #mail versturen# 
}else{
 #niets doen#
}


Ik hoop dat ik het probleem goed geschetst heb. Alle feedback is welkom.
En dan bevat $json de waarden uit $WebmethodResult als ik het goed begrijp?
Ja
Hoe is het dan mogelijk dat ik de volgende foutmelding krijg bij deze functie:
Warning: json_decode() expects parameter 1 to be string, object given

$defarray = json_decode($WebmethodResult, true);

$WebmethodResult bestaat dus uit objecten welke ik niet kan decoden met json_decode($WebmethodResult, true);
$defarray = json_decode((array) $WebmethodResult, true);

Typecasting wilt soms wel eens een handje helpen.

Ik kwam ook dit tegen tijdens een zoektocht op internet:

function object_to_array($data)
{
    if (is_array($data) || is_object($data))
    {
        $result = array();
        foreach ($data as $key => $value)
        {
            $result[$key] = object_to_array($value);
        }
        return $result;
    }
    return $data;
}
Thnx voor je reactie. Ik heb de code gebruikt zoals je hebt aangegeven. Maar zoals ik al verwachtte nu de volgende foutmelding:

Warning: json_decode() expects parameter 1 to be string, array given in....

Er wordt dus een string verwacht en niet een array of object.
De gedefinieerde functie object_to_array had ik inderdaad ook al geprobeerd.
Laten we eens bij het begin beginnen.

In wezen doe je met $client->getShipmentStatus($parameters) een aanroep van __soapCall().

Hier staat (onder Return Values):
On error, if the SoapClient object was constructed with the exceptions option set to FALSE, a SoapFault object will be returned.

Ik weet niet of dit de default is, maar ik denk wel dat je er verstandig aan doet om ofwel een try-catch mechanisme te gebruiken, ofwel te controleren of er fouten optreden middels is_soap_fault(), afhankelijk van wat je instelt via de exceptions optie. Ook lijkt het mij handig en verstandig zoveel mogelijk expliciet te configureren, zodat je ook zeker weet dat de code ook op een voorgeschreven manier werkt want defaults zijn immers niet altijd de default.

Vervolgens geeft getShipmentStatus() iets terug. De documentatie van soapCall zegt hierover:
SOAP functions may return one, or multiple values. If only one value is returned by the SOAP function, the return value of __soapCall will be a simple value (e.g. an integer, a string, etc). If multiple values are returned, __soapCall will return an associative array of named output parameters.

Dus ik zou in eerste instantie een array verwachten. Maar jij zegt dat het een object is of zelfs XML. Wat is het nu? :p Heeft deze webservice ook een documentatie, staat daar in beschreven wat je terug kunt verwachten?

Maar het lijkt er dus op dat alles min of meer goed verloopt (foutafhandeling en configuratie daar gelaten) en je dus enkel een waarde ergens uit moet peuteren (een object? een lap XML? iets anders?), maar dat staat verder los van dit hele SOAP gebeuren lijkt mij.
Bedankt Thomas voor het diepgaande antwoord.

De aanroep die ik doe geeft inderdaad een response terug.
Via onderstaande code toon ik op m'n scherm wat er terugkomt, namelijk:

echo "<pre>";
  print_r($WebmethodResult);
echo "</pre>";


Op het scherm ziet dat er uit zoals:

stdClass Object
(
    [GetShipmentStatusResult] => stdClass Object
        (
            [schema] => 
            [any] => 18237421 2019-01-15AfgeleverdA47Rayon
        )

)


Als ik naar de Broncode kijk van deze response die ik op het scherm krijg ziet dat er als volgt uit:

<pre>stdClass Object
(
    [GetShipmentStatusResult] => stdClass Object
        (
            [schema] => <xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet"><xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true"> .....etc. etc..... </xs:schema>
            [any] => <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"><NewDataSet xmlns=""><Shipment diffgr:id="Shipment1" msdata:rowOrder="0"><ShipmentID>18237421</ShipmentID><Country>NL</Country><MovementType>Tijdvenster</MovementType><Code>00</Code>.....etc. etc.....</Shipment></NewDataSet></diffgr:diffgram>
        )

)
</pre>


Voor de toepassing die ik wil maken wil ik graag het element "MovementType" gaan uitlezen, omdat daarin een status wordt gegeven. Daarom moet ik dus op een correcte manier de variabele $WebmethodResult uitlezen in PHP.
Mja, maar daar zit dus blijkbaar geserialiseerde XML in, deze zou je dus apart moeten uitpakken. Dit ziet er een beetje onorthodox uit (misschien? heb hier verder weinig ervaring mee). Heb je documentatie die hier beweegredenen voor geeft of uitlegt hoe je hier data uit kunt peuteren?

Anyhow, het volgende lijkt ongeveer te doen wat jij wilt, bij wijze van proof of concept. Iets soortgelijks zou voor bovenstaande SOAP-response ook moeten werken:
<?php
// zorg dat output goed geencodeerd is
header('Content-Type: text/html; charset=UTF-8');

// voor het melden+weergeven van foutmeldingen voor debugging
error_reporting(E_ALL);
ini_set('display_startup_errors', true);
ini_set('display_errors', 'stdout');

// hulpfunctie voor het (veilig) dumpen van data
function dump($in) {
    if (is_array($in)) {
        $in = print_r($in, true);
    }
    echo '<pre>'.escape($in).'</pre>';
}

// hulpfunctie voor het escapen van output
function escape($in) {
    return htmlspecialchars($in, ENT_QUOTES, 'UTF-8');
}

// Test case, bouw een soortgelijk genest object met hierin een XML-string
$wrapper = new StdClass();

$subObj = new StdClass();

$subObj->xml = '<root><data>hoi</data></root>';

$wrapper->sub = $subObj;

// zet objecten om naar (geneste) arrays
$response = json_decode(json_encode($wrapper), true);

// inspecteer output
dump($response);

// selecteer de XML-string
$xml = $response['sub']['xml'];

// creeer hiermee een SimpleXMLElement object
$data = simplexml_load_string($xml);

// converteer dit wederom naar (geneste) arrays
$dataArray = json_decode(json_encode($data), true);

// And Bob's your uncle
dump($dataArray);
?>[end]

EDIT: als dat XML-ding onhandig in elkaar zit (met attributen enzo) dan zul je deze misschien wat verder uit elkaar moeten trekken m.b.v. SimpleXML, maar als je eenmaal het XML-deel bij zijn kladden hebt zou dat niet ingewikkeld moeten zijn.
Bedankt Thomas, ik ben zeker wel een stukje verder op weg met dit concept.
Echter krijg ik wederom de volgende foutmelding:

simplexml_load_string() expects parameter 1 to be string, array given in

Op basis van jouw concept krijg ik het volgende op mijn scherm (output):


Array
(
    [sub] => Array
        (
            [xml] => Array
                (
                    [GetShipmentStatusResult] => Array
                        (
                            [schema] => <xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet"> .... etc. etc. .... </xs:schema>
                            [any] => <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"><NewDataSet xmlns=""><Shipment diffgr:id="Shipment1" msdata:rowOrder="0"><ShipmentID>18237421</ShipmentID></Shipment></NewDataSet></diffgr:diffgram>
                        )

                )

        )

)


Echter krijg ik nog steeds geen echo van het element "ShipmentID" op m'n scherm op één of andere manier.
Dat moet je nog steeds extraheren uit je schema en any velden.

Reageren