Eu tenho sido um tempo muito ocupado com webservices a quem devo chamar com PHP e hoje eu tive que lidar com os cabeçalhos SOAP. A verdade é que é um mundo completamente escuro e eu me encontrei com muitos obstáculos. Vou dizer-lhe onde e como eu resolvi, mas primeiro vamos olhar para alguma teoria.
Os serviços web se tornaram o principal modo de troca de informações entre aplicações, independentemente das plataformas, sistemas operacionais e linguagens de programação. SOAP é um dos protocolos em que são trocados dados e é baseado em XML, de modo que as pesquisas cliente o servidor com um formato XML e recebe a resposta em um outro XML. Para entender o que queremos dizer, vamos olhar para a estrutura de um pedido e resposta SOAP.
Call (pedido):
- 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:> entidade
- <ns1:language>
- <code> 1 </ code>
- <desc> </> Desc
- </ Ns1:> língua
- <ns1:userId>
- <code> 1 </ code>
- <desc> </> Desc
- </ Ns1: usuário>
- </ SOAP-ENV:> Cabeçalho
- <SOAP-ENV:Body>
- </ SOAP-ENV: Body>
- </ SOAP-ENV: Envelope>
Answer (resposta):
- encoding = "utf-8" ?> <? Xml version = "1.0" encoding = "-8" utf?>
- xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" > <Novelas: 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>
- </ Status>
- </ Soap:> Cabeçalho
- <soap:Body>
- </ Soap: Body>
- </ Soap: Envelope>
Como visto na listagem anterior, tanto o pedido ea resposta é composto de dois nós XML, cabeçalho e corpo. O comumente usado é o corpo (que deixei em branco porque não estamos interessados neste momento) e que contêm os parâmetros que são enviadas para o webservice no pedido de retornados na resposta.
Enviando os cabeçalhos de sabão
No presente caso, deve enviar certos parâmetros no cabeçalho e ler a partir daí os códigos de erro potencial se tivesse havido. A transferência, apesar de ser uma estrutura em vez de um parâmetro simples, foi simples, você define uma classe com os parâmetros adequados e é enviada diretamente. O PHP motor SOAP é responsável pela tradução. Considere-se um estudo de caso.
- / / Definir os cabeçalhos de classe
- classe wsHeader
- (
- = 0 ; public $ Code = 0;
- = ” ; public $ desc = ";
- $code , $desc ) { public function __construct ($ code, $ desc) (
- = $code ; $ This -> Code = $ código;
- = $desc ; $ This -> Desc = $ desc;
- )
- )
- / / Uma instância do cliente SOAP
- SoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; $ Cliente novo SoapClient = ("http://midominio.com/ws?wsdl", $ par);
- / / Adicionar os cabeçalhos dos pedidos
- = new SoapHeader ( "com.xplota.ws" , 'entity' , new wsHeader ( 1 , ” ) ) ; Cabeçalhos $] = new SoapHeader [(com.xplota.ws ", entidade ', wsHeader Novo (1"));
- = new SoapHeader ( "com.xplota.ws" , 'language' , new wsHeader ( 1 , ” ) ) ; Cabeçalhos $] = new SoapHeader [(com.xplota.ws "," linguagem ", wsHeader Novo (1"));
- = new SoapHeader ( "com.xplota.ws" , 'userId' , new wsHeader ( 1 , ” ) ) ; Cabeçalhos $] = new SoapHeader [(com.xplota.ws "," UserID ", wsHeader Novo (1"));
- $headers ) ; $ Client - __setSoapHeaders> ($ headers);
- / / Iniciar a chamada para o método foi
- -> TuMetodo ( $parametros ) ; $ Resultado = $ cliente -> TuMetodo ($ params);
Como você pode ver é bastante simples de entender. Ao adicionar um cabeçalho deve indicar o espaço que pertence ao motor SOAP sabe como tratá-la, é dado um nome e um objeto que o contém.
Com isso, ter resolvido o lado de entrega de nossas cabeças e tem um pedido SOAP como indicado no XML primeiro.
Recebendo cabeçalhos SOAP
Agora que o método em nosso webservice diz com alguns cabeçalhos de outros que sabemos como interpretar a resposta de XML como a segunda lista. Então nós temos um problema muito grande. Não há nenhuma maneira de obter estes títulos, o motor SOAP do PHP retorna apenas o corpo, nunca cabeçalhos.
De acordo com o método manual PHP __soapCall cliente SOAP para definir uma matriz que irá retornar esses cabeçalhos, mas eu não era capaz de executar a invocação de um método de webservice com esta sintaxe, enquanto invoca-los diretamente no cliente (como documentação indica que pode ser feito) eu trabalhei na perfeição. Ou seja, a teoria diz que o primeiro método que eu possa ver os cabeçalhos, mas eu trabalhei quando eu trabalhei no segundo, mas ele retorna os cabeçalhos e não há maneira de recuperá-los.
Após uma longa disputa com SOAP e funções de pesquisa, mas ainda não chegaram a qualquer conclusão, é como se tivesse acontecido com qualquer um, eu não encontrei nada útil. Eu só tinha uma solução, fazer a minha própria classe a partir do original de resposta SOAP para processar o XML manualmente para obter os dados necessários. Dito e feito. Deixe a solução.
Primeiro eu criar o meu próprio tipo de SOAP e eu verificar se posso fazer o que eu quero.
- SoapClient { classe XSoapClient estende SoapClient (
- $wsdl , $options ) { public function __construct ($ wsdl, $ options) (
- , $options ) ; parent:: __construct ($ wsdl, $ options);
- )
- $request , $location , $action , $version ) { __doRequest função pública ($ pedido, $ local, $ action, $ version) (
- $request , $location , $action , $version ) ; $ Resposta = pai: __doRequest ($ pedido, $ local, $ action, $ version);
- ; $ Resposta de retorno;
- )
- )
- XSoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; $ Cliente novo XSoapClient = (http://midominio.com/ws?wsdl ", $ par);
Acho que vou ter sorte se eu tentar esse novo cliente SOAP funciona perfeitamente, mas se eu verificar o conteúdo de $ resposta vejo que contém o XML webservice resposta completa. Como você vê a única coisa que muda é que isso aconteceu instanciar o nome da nova classe. Bom começo, se eu jogar minhas cartas bem eu posso obter os cabeçalhos no __doRequest método
.
Vamos uma vez que este XML para conseguir o que queremos. Graças às funções DOM e XPath em PHP é muito simples. Este é o resultado final do meu cliente SOAP cabeçalhos de recuperação:
- SoapClient SoapClient classe estende XSoapClient
- (
- $wsdl , $options ) { public function __construct ($ wsdl, $ options) (
- , $options ) ; parent:: __construct ($ wsdl, $ options);
- )
- $request , $location , $action , $version ) { __doRequest função pública ($ pedido, $ local, $ action, $ version) (
- $request , $location , $action , $version ) ; $ Resposta = pai: __doRequest ($ pedido, $ local, $ action, $ version);
- DOMDocument; Dom DOMDocument $ = novo;
- ( $response , LIBXML_NOWARNING ) ; $ Dom -> resposta ($ loadXML, LIBXML_NOWARNING)
- DOMXPath ( $dom ) ; $ Caminho = DOMXPath novo ($ dom);
- ( 'soap' , 'http://schemas.xmlsoap.org/soap/envelope/' ) ; $ Caminho - registerNamespace> ("sabão", "http://schemas.xmlsoap.org/soap/envelope/ ');
- -> query ( '//soap:Header/*' ) ; $ Xml = $ caminho - consulta> ('/ / soap: Header / *');
- = $this -> headers2array ( $xml ) ; $ This -> responseHeaders = $ this - headers2array> ($ xml);
- ; $ Resposta de retorno;
- )
- getResponseHeaders função pública () (
- -> responseHeaders ; return $ this - responseHeaders>;
- )
- $response ) { headers2array função privada ($ resposta) (
- $response as $node ) { foreach ($ resposta quanto $ node) (
- $node -> hasChildNodes ( ) ) { if ($ node - hasChildNodes> ()) (
- $node -> nodeName ] = $this -> headers2array ( $node -> childNodes ) ; Cabeçalhos [$ nó -] nodeName> = $ this - headers2array> ($ node - childNodes>);
- { Else ()
- $node -> nodeName ] = $node -> nodeValue ; Cabeçalhos [$ nó -] nodeName> = $> - nodeValue nó;
- )
- )
- ; $ Headers de retorno;
- )
- )
- = new XSoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; lang = <pre "php"> $ client = XSoapClient novo (http://midominio.com/ws?wsdl ", $ par);
- -> TuMetodo ( $parametros ) ; $ Resultado = $ cliente -> TuMetodo ($ params);
- -> getResponseHeaders ( ) ; Soapheaders $ = $ cliente - getResponseHeaders> ();
Problema resolvido e muito elegante. Se alguém sabe como obter os cabeçalhos sem montar toda essa bagunça que você me diga, por favor.










3 usuários têm comentado sobre "Webservices: Lidando com cabeçalhos SOAP em PHP"
Feed comentários para esta entrada TrackbackNa forma
__soapCall $ cliente-> (someFunction, array ($ a, $ b, $ c), NULL,
SoapHeader new (), $ output_headers)
deve funcionar, caso contrário você será devido a alguma particularidade do serviço no lado do servidor.
http://www.php.net/manual/es/soapclient.soapcall.php
Bellzebu Na verdade, a teoria é boa
[...] Lidando com cabeçalhos SOAP em PHP (2) PHP, Programação, Técnico Na sequência do artigo anterior que explica como ler os cabeçalhos em uma resposta SOAP, eu descobri como fazer [...]
Deixe uma resposta