quarta-feira, 12 de janeiro de 2011

WebService with NuSOAP

É um conjunto de classes PHP que permite aos desenvolvedores criar e consumir serviços Web baseados em SOAP 1.1, 1.1 e WSDL HTTP 1.0/1.1. Pode ser feito download a partir da página: 
http://sourceforge.net/projects/nusoap/

Instalação:
Depois de ter baixado uma cópia do nusoap.php, basta colocá-lo em sua árvore de código para que você possa incluí-lo em seu código PHP. Alguns usuários colocaram nele um diretório separado lib. Para o meu exemplo, eu coloquei-o no mesmo diretório como o código de exemplo em si.

Exemplos:
Vamos começar com o exemplo simples "Hello world". Isso vai demonstrar a base de clientes de codificação NuSOAP e servidores.
Vamos começar com o código do servidor, já que sem um servidor, não há necessidade de ter qualquer cliente. O servidor SOAP expõe um método único chamado Hello, o que leva um parâmetro de seqüência única de entrada e retorna um string. Felizmente, os comentários dentro do código fornecer uma explicação suficiente! Para os serviços mais simples, tudo o que vai mudar são as funções a ser definido e registrado. 

Nomeie um arquivo como server.php. Seu conteúdo segue abaixo.  
 
require_once('nusoap.php');
// Cria uma instancia do servidor
$server = new soap_server;
// Registrando o metodo criado
$server->register('hello');
// Define o metodo 
function hello($name) {
    return 'Hello, ' . $name;
}
// Usar o request para invocar o servico
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
 O cliente para este serviço segue abaixo. Existem algumas coisas importantes a serem observadas.  
Primeiro, quando a instância do soapclient é criado, o parâmetro especificado é o URL para o serviço. No meu caso, server.php é acessado a partir http://localhost/projeto/webservice. Os serviços que você consome, é claro, estarão localizados em URLs diferentes. 
Em segundo lugar, ao chamar o serviço, o primeiro parâmetro é o nome do serviço. Este deve corresponder ao nome case-sensítive de um método disponível no servidor. Neste exemplo, ele deve corresponder ao método registrados no server.php.  
Finalmente, o segundo parâmetro na chamada é um array de parâmetros que serão passados para o método de serviço SOAP. Como o método de server.php Hello requer um único parâmetro, esse array tem um elemento.

require_once('nusoap.php');
// Criar uma instancia do client
$client = new soapclient('http://localhost/projeto/webservice/server.php');
//Chama o metodo call do SOAP
$result = $client->call('hello', array('name' => 'Scott'));
// exibe o resultado
print_r($result);

// checando faults
if ($client->fault) {
    echo '<p><b>Fault: ';
    print_r($result);
    echo '</b></p>';
} else {
    // Checando erros
    $err = $client->getError();
    if ($err) {
        echo '<p><b>Error: ' . $err . '</b></p>';
    } else {
        print_r($result);
    }
}

//Debugando 
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
Outro exemplo mais completo, que envolve o cadastro de dados de 
clientes no banco de dados. O arquivo server.php segue abaixo:
 
$server = new soap_server();
$server->debug_flag = true;
$server->configureWSDL('MeuNameSpace', 'WSDL');
$server->wsdl->schemaTargetNameSpace='urn:MeuNameSpace';

$server->register('cadastrar', array('entrada'=>'tns:arrCadastro'),  
        array('return'=>'xsd:string'),
 'urn:MeuNameSpace',
 'urn:MeuNameSpace#cadastrar',
 'rpc',
 'encoded',
 ''
); 
$server->wsdl->addComplexType('arrCadastro', 'complexType', 'struct', 'all','',
array(
  'full_name'=>array('name'=>'full_name','type'=>'xsd:string')
  ,'email'=>array('name'=>'email','type'=>'xsd:string')
  ,'dat_nascimento'=>array('name'=>'dat_nascimento','type'=>'xsd:string')
  ,'cpf'=>array('name'=>'cpf','type'=>'xsd:string')
 )
);
function cadastrar($dados=array()){
 $objCliente = new Cliente();
 if($objCliente)
  $id = $objCliente->cadastroWebService($dados);
 return "$id";
}

$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
E o client para testes: client.php
 
$client = new nusoap_client('http://localhost/projeto/webservice/server.php?wsdl&debug=1', 'wsdl');
$err = $client->getError();
if ($err) {
 echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
 echo '<h2>Debug</h2>';
 echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
 exit();
}

$dados = array(
  'full_name' => 'Ademir Braga',
  'dat_nascimento' => '30/01/1984',
  'cpf' => '11111111222',
  'email' => 'ademirbraga100@yahoo.com.br',
  ); 
$result = $client->call('cadastrar', array('entrada' => $dados));

if ($client->fault) {
 echo '<h2>Fault</h2><pre>';
 print_r($result);
 echo '</pre>';
} else {
 $err = $client->getError();
 if ($err) {
  echo '<h2>Error</h2><pre>' . $err . '</pre>';
 } else {
  echo '<h2>Result</h2><pre>';
  // Decode the result: it so happens we sent Latin-1 characters
  if (isset($result['return'])) {
   $result1 = utf8_decode($result['return']);
  } elseif (!is_array($result)) {
   $result1 = utf8_decode($result);
  } else {
   $result1 = $result;
  }
  print_r($result1);
  echo '</pre>';
 }
}
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';

 Este exemplo mostra o cadastro de um cliente no banco de dados, usando o metodo cadastroWebService 
contido na classe Cliente via webservice.

Conclusão:
Usando webservices podemos integrar sistemas diferentes e independentes definindo apenas os campos necessários para utilização do lado do client.