Sono stato un periodo molto impegnato con i webservices a chi devo chiamare con PHP e oggi ho avuto a che fare con le intestazioni SOAP. La verità è che è un mondo abbastanza scuro e ho incontrato molti ostacoli. Vi dirò dove e come ho risolto, ma prima diamo un'occhiata a qualche teoria.
I servizi web sono diventati il principale modo di scambio di informazioni tra le applicazioni a prescindere di piattaforme, sistemi operativi e linguaggi di programmazione. SOAP è uno dei protocolli su cui sono scambiati dati e si basa su XML, in modo che i sondaggi client al server con un formato XML e riceve la risposta in un altro XML. Per capire cosa intendiamo vediamo la struttura di una richiesta SOAP e risposta.
Call (richiesta):
- encoding = "UTF-8" ?> <? Xml version = "1.0" encoding = "UTF-8"?>
- xmlns:ns1= "com.xplota.ws" > Xmlns: SOAP-ENV = "http://schemas.xmlsoap.org/soap/envelope/" xmlns: ns1 = <SOAP-ENV:Envelope "com.xplota.ws">
- <SOAP-ENV:Header>
- <ns1:entity>
- <code> 1 </ code>
- <desc> </ Desc>
- </ NS1: ente>
- <ns1:language>
- <code> A </ code>
- <desc> </ Desc>
- </ NS1: language>
- <ns1:userId>
- <code> 1 </ code>
- <desc> </ Desc>
- </ NS1:> userid
- </ SOAP-ENV:> Header
- <SOAP-ENV:Body>
- </ SOAP-ENV:> Body
- </ SOAP-ENV:> Busta
Risposta (risposta):
- encoding = "utf-8" ?> <? Xml version = "1.0" encoding = "utf-8"?>
- xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" > <Sapone: Envelope xmlns: soap = "http://schemas.xmlsoap.org/soap/envelope/" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = " http://www.w3.org/2001/XMLSchema ">
- <soap:Header>
- > Xmlns = <status "com.xplota.ws">
- <code> 0 </ code>
- <desc> Ok </ desc>
- </ Stato>
- </ Soap:> Header
- <soap:Body>
- </ Soap: Corpo>
- </ Soap:> Busta
Come si è visto nelle inserzioni precedenti, sia la richiesta e la risposta è costituito da due nodi XML, intestazione e corpo. Comunemente utilizzato è il corpo (che ho lasciato in bianco, perché non ci interessa in questo periodo) e che contengono sia i parametri che vengono inviati al webservice nella richiesta come restituito nella risposta.
Invio di intestazioni SOAP
Nel caso in esame era quella di inviare alcuni parametri nell'intestazione e leggere da lì i codici di errore potenziale se vi fosse stato. La spedizione, nonostante sia una struttura invece di un semplice parametro, era semplice, si definisce una classe con i parametri appropriati e viene inviato direttamente. Il SOAP motore PHP è responsabile per la traduzione. Consideriamo un caso di studio.
- / / Definisce le intestazioni di classe
- wsHeader classe
- (
- = 0 ; pubblico $ codice = 0;
- = ” ; pubblico $ desc = ";
- $code , $desc ) { pubblica funzione __construct ($ code, $ desc) (
- = $code ; $ Questo -> codice = $ codice;
- = $desc ; $ Questo -> Desc = $ desc;
- )
- )
- / / Un esempio del client SOAP
- SoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; $ Nuovo Cliente SoapClient = ("http://midominio.com/ws?wsdl", $ par);
- / / Aggiungo le intestazioni delle richieste
- = new SoapHeader ( "com.xplota.ws" , 'entity' , new wsHeader ( 1 , ” ) ) ; $ Intestazioni [] = SOAPHeader nuovo (com.xplota.ws ", 'entità', wsHeader nuovo (1"));
- = new SoapHeader ( "com.xplota.ws" , 'language' , new wsHeader ( 1 , ” ) ) ; $ Intestazioni [] = SOAPHeader nuovo (com.xplota.ws ',' linguaggio ', wsHeader nuovo (1 "));
- = new SoapHeader ( "com.xplota.ws" , 'userId' , new wsHeader ( 1 , ” ) ) ; $ Intestazioni [] = new SOAPHeader ("com.xplota.ws ',' userid ', wsHeader nuovo (1"));
- $headers ) ; $ Client - __setSoapHeaders> ($ intestazioni);
- / / Varata la chiamata al metodo di stato
- -> TuMetodo ( $parametros ) ; $ Risultato = $ client -> TuMetodo ($ params);
Come potete vedere è abbastanza semplice da capire. Con l'aggiunta di un header deve indicare lo spazio dei nomi a cui appartiene il motore SOAP sa come trattarlo, viene assegnato un nome e l'oggetto che lo contiene.
Con questo abbiamo risolto il lato consegna delle nostre teste e hanno una richiesta SOAP Come abbiamo indicato nel primo XML.
Ricezione intestazioni SOAP
Ora che il metodo nel nostro webservice dice con alcuni altri header che sappiamo come interpretare la risposta XML come seconda voce. Poi abbiamo un problema molto grande. Non vi è alcun modo per ottenere queste intestazioni, il motore SOAP di PHP restituisce solo il corpo, mai intestazioni.
Secondo il manuale PHP metodo __soapCall client SOAP per definire una matrice che restituirà queste intestazioni, ma non ero in grado di eseguire l'invocazione di un metodo webservice con questa sintassi mentre li invoca direttamente sul client (come precisa documentazione che si può fare) mi ha funzionato perfettamente. Cioè, la teoria dice che il primo metodo posso ottenere le intestazioni, ma ho lavorato, mentre il secondo ho lavorato ma restituisce le intestazioni e non c'è modo di recuperarli.
Dopo una lunga contesa con SOAP e le funzioni di ricerca, ma non ancora giunti a nessuna conclusione, è come se fosse accaduto a nessuno, non ho trovato nulla di utile. Avevo solo una soluzione, rendere la mia stessa classe dall'originale risposta SOAP per elaborare i dati XML a mano per ottenere i dati necessari. Detto e fatto. Lasciate che la soluzione.
Per prima cosa ho creato proprio il mio genere di SOAP e verificare se posso fare quello che voglio.
- SoapClient { classe XSoapClient estende SoapClient (
- $wsdl , $options ) { pubblica funzione __construct ($ wsdl, $ opzioni) (
- , $options ) ; parent:: __construct ($ wsdl, $ opzioni);
- )
- $request , $location , $action , $version ) { __doRequest pubblica funzione ($ richiesta, $ posizione, $ action, $ version) (
- $request , $location , $action , $version ) ; Risposta = $ parent:: __doRequest ($ richiesta, $ posizione, $ action, $ version);
- ; return $ risposta;
- )
- )
- XSoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; Client = $ XSoapClient nuovo (http://midominio.com/ws?wsdl ", $ par);
Penso di essere fortunato se provo questo nuovo client SOAP funziona perfettamente, ma anche se posso controllare il contenuto di $ risposta vedo che contiene l'intero risposta webservice XML. Come vedete l'unica cosa che cambia è che è successo istanziare il nome della nuova classe. Buon inizio, se gioco bene le mie carte posso ottenere le intestazioni nel metodo __doRequest
.
Vediamo perché questo XML per ottenere ciò che vogliamo. Grazie alle funzioni DOM e XPath in PHP è molto semplice. Questo è il risultato finale del mio recupero intestazioni SOAP client:
- SoapClient SoapClient classe estende XSoapClient
- (
- $wsdl , $options ) { pubblica funzione __construct ($ wsdl, $ opzioni) (
- , $options ) ; parent:: __construct ($ wsdl, $ opzioni);
- )
- $request , $location , $action , $version ) { __doRequest pubblica funzione ($ richiesta, $ posizione, $ action, $ version) (
- $request , $location , $action , $version ) ; Risposta = $ parent:: __doRequest ($ richiesta, $ posizione, $ action, $ version);
- DOMDocument; Dom $ = DOMDocument nuovo;
- ( $response , LIBXML_NOWARNING ) ; $ Dom -> loadXML ($ risposta, LIBXML_NOWARNING)
- DOMXPath ( $dom ) ; $ Path = DOMXPath nuovo ($ dom);
- ( 'soap' , 'http://schemas.xmlsoap.org/soap/envelope/' ) ; Percorso $ - registerNamespace> ('sapone', 'http://schemas.xmlsoap.org/soap/envelope/');
- -> query ( '//soap:Header/*' ) ; $ Path = $ Xml - query> ('/ / soap: Intestazione / *');
- = $this -> headers2array ( $xml ) ; $ Questo -> = $ this responseHeaders -> headers2array ($ XML);
- ; return $ risposta;
- )
- getResponseHeaders funzione pubblica () (
- -> responseHeaders ; return $ questo - responseHeaders>;
- )
- $response ) { headers2array private function ($ risposta) (
- $response as $node ) { foreach ($ risposta come nodo $) (
- $node -> hasChildNodes ( ) ) { if ($ nodo - hasChildNodes> ()) (
- $node -> nodeName ] = $this -> headers2array ( $node -> childNodes ) ; Intestazioni $ [$ nodo ->] nodeName = $ this - headers2array> ($ nodo - childNodes>);
- { Else ()
- $node -> nodeName ] = $node -> nodeValue ; Intestazioni $ [$ nodo ->] = $ nodeName nodo - nodeValue>;
- )
- )
- ; $ Intestazioni di ritorno;
- )
- )
- = new XSoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; lang = <pre "php"> $ client = XSoapClient nuovo (http://midominio.com/ws?wsdl ", $ par);
- -> TuMetodo ( $parametros ) ; $ Risultato = $ client -> TuMetodo ($ params);
- -> getResponseHeaders ( ) ; Soapheaders $ = $ client - getResponseHeaders> ();
Problema risolto e molto elegante. Se qualcuno sa come ottenere le intestazioni senza montaggio tutto questo casino mi dite per favore.










3 utenti hanno commentato "Webservices: Gestire le intestazioni SOAP in PHP"
Feed commenti per questa voce TrackbackNella forma
__soapCall $ Client-> ("someFunction, array ($ a, $ b, $ c), NULL,
SOAPHeader new (), $ output_headers)
dovrebbe funzionare, altrimenti sarà a causa di alcune peculiarità del servizio sul lato server.
http://www.php.net/manual/es/soapclient.soapcall.php
Bellzebu In effetti, la teoria è buona
[...] Trattare con intestazioni SOAP in PHP (2) PHP, Programmazione, tecnica successiva alla precedente articolo che spiega come leggere le intestazioni in una risposta SOAP, ho scoperto come fare [...]
Lascia una risposta