Como faço para capturar dados do conteúdo XML de uma solicitação SOAP em um SOAPServer php?
Pergunta
Estou tentando configurar um serviço SOAP em php.Declarei uma função php de servidor e posso chamar essa função com uma solicitação http do tipo SOAP, onde o conteúdo é meu envelope SOAP.
O conteúdo XML do corpo SOAP é o argumento da função que assumo, mas não sei como acessar as informações contidas nele no meu código php.
Notei que o argumento da função é uma instância de stdClass
por padrão, e eu realmente me pergunto por que não é lançado em um XML
ou DOM
object por php - é uma chamada SOAP, não é?Mas tudo bem, agora cabe a mim retirar as informações do objeto, o que não é fácil porque não há métodos atribuídos a ele. stdClass
, então terão que ser funções php padrão.Então eu tentei serialize
, mas isso me deu algum lixo, não a string XML que eu esperava.
O que fazer?
EDITAR
observe que abaixo não há código de exemplo do que desejo fazer - obter alguns dados detalhados do conteúdo XML da solicitação SOAP - porque não sei como codificar para obtê-los do objeto stdClass
A pedido de David, aqui estão alguns detalhes.
código php:
<?php
function mi102($arg) {
$txt = serialize ($arg);
$result = new SoapVar ($txt, XSD_ANYXML);
return($result);
}
ini_set( "soap.wsdl_cache_enabled", "0");
$server = new SoapServer ("test.wsdl");
$server -> addFunction ("mi102");
try {
$server -> handle();
}
catch (Exception $e) {
$server -> fault ('Client', $e -> getMessage());
}
?php>
a solicitação http é construída por um aplicativo que eu uso;o cabeçalho http e o envelope soap + corpo são gerados em torno do XML que eu alimento:
Conteúdo do corpo da solicitação SOAP:
<mi102 xmlns="http://pse">
<cdhead cisprik="21"/>
<instr>
<insid>
<bcdt>20120930</bcdt>
</insid>
</instr>
</mi102>
O WSDL usado é o seguinte:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://pse/" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="PSE" targetNamespace="http://pse/">
<types>
<xs:schema>
<xs:import namespace="http://pse/" schemaLocation="PSE.xsd"/>
</xs:schema>
</types>
<message name="MI102Req">
<part name="cdhead" type="tns:cdhead_T"/>
<part name="instr" type="tns:instr_T"/>
</message>
<message name="Res">
<part name="cdhead" type="tns:cdhead_T"/>
</message>
<portType name="MIPortType">
<operation name="mi102">
<input message="tns:MI102Req"/>
<output message="tns:Res"/>
</operation>
</portType>
<binding name="MIBinding" type="tns:MIPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="mi102">
<soap:operation soapAction="http://testServerURL/test_soap.php#mi102"/>
<input>
<soap:body use="literal" namespace="http://pse/"/>
</input>
<output>
<soap:body use="literal" namespace="http://pse/"/>
</output>
</operation>
</binding>
<service name="PSE">
<port name="MIPortType" binding="tns:MIBinding">
<soap:address location="http://testServerURL/test_soap.php"/>
</port>
</service>
</definitions>
E o XML resultante (novamente, extraído do corpo SOAP pela aplicação que uso), é
Resposta SOAP:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:mi102Response xmlns:ns1="http://pse/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">O:8:"stdClass":2:{s:7:"cisprik";i:21;s:7:"version";s:2:"13";}</ns1:mi102Response>
Não é legal.
Solução
Acabei encontrando a resposta em outros tópicos do SO, como obter-recebido-xml-do-php-soap-server
A solução é usar o seguinte:
$inp = file_get_contents ('php://input');
Observação:Não consegui encontrar nenhuma função que possa atuar no stdClass
argumento de entrada e pode recuperar o conteúdo do corpo XML SOAP dele.
Portanto, a melhor opção é usar a variável de entrada padrão do php.Observe que isso tem a seguinte estrutura: Envelope/Body/..inputXML..
, que é o conteúdo exato da solicitação http postado no servidor.
Observação: http_get_request_body
pode funcionar também, mas meu servidor php não suportava esta função.eu penso isso file_get_contents
é suportado em todos os servidores php de alguma versão em diante.
Outras dicas
Isso não vai começar como uma resposta completa, mas eu queria a formatação.Explique o que você configurou.Geralmente, você terá um método PHP com argumentos regulares (não XML) que deseja expor como um serviço web.Um exemplo básico de como fazer isso está aqui:
http://www.phpeveryday.com/articles/Web-Services-WSDL-Creating-SOAP-Server-P484.html
O conteúdo XML do corpo SOAP é o argumento da função que presumo
Não, o conteúdo XML do corpo SOAP é o representação do método com seus argumentos, mas seus argumentos são o que você quiser.Você não deverá ter que lidar com XML manualmente se configurá-lo com SoapServer e SoapClient do PHP.
EDITAR:Você está pegando seu argumento, que é uma representação simples de array PHP do corpo da sua solicitação SOAP, serializando-o e enviando-o de volta como uma resposta (que é o que você observa).É isso que você quer fazer?Você não quer fazer algo com os dados da solicitação?Além disso, você pode postar o esquema importado do WSDL?
Você está tendo aquela representação "nada legal" de um objeto porque está retornando o objeto serializado (a serialização está convertendo o objeto e seu estado em uma representação de string).Se você deseja ter uma representação xml do objeto retornado, você deve alterar o tipo de parâmetro de retorno da sua função para um objeto.Porque agora está retornando uma string.
Eu recomendo que você use os componentes Zend_Soap_Server e Zend_Soap_Autodiscover do framework zend.
Com Zend_Soap_Autodiscover você pode gerar sua definição de serviço web (wsdl) dinamicamente, apenas escrevendo os docblocks de suas funções.E Zend_Soap_Server também é muito legal.
Se você usar esses componentes e documentar seus tipos e sua função para retornar um tipo específico sem serializá-lo, você receberá a representação xml de acordo com a definição WSDL.Além disso, cada tipo criado é convertido automaticamente pelo Zend_Soap_Autodiscover em um ComplexType no wsdl gerado.
Amostra:
public class Person{
public $id;
public $name;
}
public class MyService {
/**
*
* @param integer $UserID
* @return Person
*/
function mi102($UserID) {
$output = new Person();
$output->id = 2;
$output->name = 'Peter';
return $output;
}
}
// Generate WSDL relevant to code
if (isset($_GET['wsdl'])){
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setClass('MyService');
$autodiscover->handle();
} else {
$server = new Zend_Soap_Server($serviceURL . "?wsdl");
$server->setClass('MyService');
$server->setObject(new MyService());
$server->handle();
}