Web service é uma solução utilizada para integração e comunicação entre diferentes aplicações. Por meio de um web service você pode disponibilizar funções ou mensagens para qualquer outra aplicação na internet ou em aplicações corporativas internamente.

Além disso, também é possível acessar (consumir) funções e mensagens de outros web services. A comunicação é realizada através do formato XML usando o protocolo HTTP. Através do XML, que é um formato universal, é possível que aplicações rodando em plataformas diferentes se comuniquem, simplesmente traduzindo seus dados para XML antes da comunicação. Já o protocolo HTTP é o mais utilizado na internet. É através desse protocolo que você pode navegar pelos sites usando seu navegador de preferência.

Neste contexto, o PHP nos fornece funções para trabalhar com web services de forma simples e fácil. Os dois principais tipos de comunicação com Web Service são SOAP e REST. Neste artigo iremos abordar como fazer a comunicação com esses dois tipos de Web Service.

SOAP

SOAP é um protocolo de comunicação baseado em XML que permite que aplicações troquem informações utilizando o protocolo HTTP. Mais especificamente, SOAP é um protocolo para acessar um Web Service. SOAP significa “Simple Object Access Protocol”. Por seguir um padrão W3C , é independente de plataforma e independente de linguagem de programação. É simples e extensível. Por trabalhar com o protocolo HTTP, que é o protocolo mais comum utilizado na internet, ele facilita a comunicação evitando que a transmissão seja bloqueada por um firewall ou proxy.

A descrição da interface de um web service SOAP é especificado em um documento XML chamado de WSDL (Web Services Description Language). O WSDL descreve o Web service e contém informações de como acessá-lo. Ele especifica a localização do serviço e quais são os seus métodos disponíveis. Portanto, caso esteja criando um web service que deseja disponibilizar para outros programas, será preciso criar o arquivo WSDL.

Existem diversas bibliotecas escritas em PHP para criação de web services SOAP. Porém, a melhor é a extensão SOAP nativa para PHP. Esta extensão requer outra extensão chamada libxml, que já vem instalada por padrão nas versões mais recentes do PHP. Portanto, para instalar a extensão SOAP no Linux basta compilar o php com a opção -enable-soap (compilando a partir do código fonte) ou para instalar a extensão SOAP no Ubuntu basta fazer sudo apt-get install php-soap. No Windows, a extensão SOAP já vem habilitada por padrão.

O PHP disponibiliza duas principais classes para trabalhar com SOAP:

    SoapClient: classe cliente para acessar web services disponíveis por outras aplicações;
  • SoapServer: para criar novos webservices e disponibilizá-los para outros aplicativos.

Neste artigo vamos criar uma pequena aplicação SOAP exemplificando a comunicação entre cliente e servidor. Como vimos anteriormente, nosso servidor SOAP precisa de um arquivo XML, chamado de WSDL, que especifica os métodos presentes em nosso web service. Porém, criar um arquivo WSDL manualmente é muito complexo. Infelizmente a classe nativa do PHP SoapServer não gera o arquivo WSDL automaticamente.

No PHP é possível operar no modo não WSDL, ou seja, sem a necessidade de existir um arquivo WSDL. Neste modo, o cliente de web service não conseguirá obter informações importantes, por exemplo o tipo de dados, formatação, etc. Assim, operar no modo não WSDL não é recomendado. Muitas plataformas como .NET, Java ou Ruby, necessitam de um WSDL para poderem funcionar.

No PHP, para gerar WSDL você tem disponível algumas ferramentas que auxiliam esse trabalho. Recomendo usar o IDE Zend Studio ou a classe Zend_Soap_AutoDiscover distribuída com o Zend Framework. Na sessão sobre Zend_Soap mais adiante neste artigo iremos demonstrar a utilização do Zend_Soap_AutoDiscover para geração do WSDL.

Vamos agora ao exemplo de uma aplicação SOAP simples. O exemplo apresentado na Listagem 1 temos o nosso servidor SOAP operando no modo não WSDL. Portanto, especificamos a opção “uri” e passamos “null” para o primeiro parâmetro do construtor da classe SoapServer. Depois disponibilizamos a classe SoapServerExemplo no web service contendo as funções “mensagem()” e “soma()”.

Listagem 1: Utilizando SOAP sem WSDL - Servidor

 'http://127.0.0.1/soap/server/');
$server = new SoapServer(null, $options);

/* 
 * Informamos a classe em que o webservice irá se basear.
 * Podemos usar também o método addFunction() para adicionar 
 * funções em nosso webservice. 
 */
$server->setClass('SoapServerExemplo');
/*
 * O método handle() processa a requisição SOAP e envia uma resposta 
 * para o cliente.
 */
$server->handle();

/*
 * A classe SoapServerExemplo será disponibilizada em nosso 
 * webservice. Portanto temos disponíveis no webservice os métodos 
 * mensagem e soma.
 */
class SoapServerExemplo {
	
	public function mensagem($nome)
	{
		return "Boas Vindas $nome !";
	}

	public function soma($a, $b)
	{
		return $a + $b;
	}
}

Em seguida, na Listagem 2 temos o código responsável pelo cliente de nosso web service. Ele irá acessar as funções que o nosso servidor disponibiliza. Nesta listagem temos o script que irá consumir o web service criado anteriormente. Ele está trabalhando no modo não WSDL, portanto é necessário especificar os parâmetros “location” e “uri” e passar null para o primeiro parâmetro do construtor da classe SoapClient. Após isso já é possível utilizarmos as funções do web service: “mensagem()” que irá retornar uma string de “Boas Vindas” usando o parâmetro $nome e a função “soma” que retorna a soma dos dois parâmetros especificados na função.

Listagem 2: Utilizando SOAP sem WSDL - Cliente

 'http://127.0.0.1/soap/server/server.php',
	'uri' => 'http://127.0.0.1/soap/server/'
);

$client = new SoapClient(null, $options);

/*
 * No Objeto $client podemos usar os métodos da classe 
 * SoapServerExemplo disponível em nosso webservice.
 */
echo $client->mensagem('Douglas') . "
"; echo $client->soma(3, 5) . "
"

Ao acessar nosso primeiro web service obtemos o resultado apresentado na Figura 1.

Acesso inicial ao web service

Figura 1: Acesso inicial ao web service

Para enriquecer nosso conhecimento em relação a web services SOAP vamos agora demonstrar a comunicação com o site usando a API SOAP do PHP. Neste exemplo iremos construir um cliente de web service em php que conecta no amazon.com e nos traz o resultado de uma pesquisa de livros referente ao assunto PHP5.

Para podermos trabalhar com web services na Amazon é necessário antes fazer um cadastro no site deles e obter determinadas chaves que serão usadas em nosso web service como uma espécie de credencial. Para isso, acesse o site e faça o seu cadastro selecionando a opção Sign Up Now.

Após o cadastro, faça o login no site e copie as chaves necessárias para nosso web service. Para isso, primeiro clique em Account -> Security Credentials (ver Figura 2).

Recuperando as credenciais

Figura 2: Recuperando as credenciais

Role a página até a sessão “Access Credentials” e copie as chaves “Access Key ID” e “Secret Access Key” (ver Figura 3).

Recuperando as credenciais Access Key ID e Secret Access Key

Figura 3: Recuperando as credenciais Access Key ID e Secret Access Key

Após copiar as chaves necessárias já estamos prontos para criar nosso web service. O código necessário para esta atividade está apresentado na Listagem 3. Nesta listagem, temos um script que conecta no web service do site da amazon. Para autenticação é necessário especificar as chaves obtidas no site de web service da amazon conforme descrito anteriormente. Para consumir este web service é necessário configurar alguns cabeçalhos para a requisição SOAP: Timestamp, Acces Key ID e Signature. A signature é criada a partir de um algoritmo especificado na documentação sobre web service no site da amazon. Após isso, fazemos a chamada para a função “itemSearch”. Nos parâmetros da chamada especificamos o tipo de pesquisa que desejamos: Livros que contenham a palavra-chave “PHP5”. O retorno da função é um array de objetos contendo diversas informações sobre os itens encontrados pela pesquisa. Desses dados utilizamos somente alguns para serem exibidos na tela: Título do livro, autores, preço, imagem da capa, link para o site da amazon.

Listagem 3: Acessando o web service da Amazon

 'Books',
'ResponseGroup' => 'Large',
'Keywords' => 'PHP5');

$params = array(
'Request' => array($request)
);

/*
Cabeçalhos SOAP necessários para comunicação com amazon
*/
$soapheaders = array (
new soapheader("http://security.amazonaws.com/doc/2007-01-01/", "Signature", $signature),
new soapheader("http://security.amazonaws.com/doc/2007-01-01/", "Timestamp", $timestamp),
new soapheader("http://security.amazonaws.com/doc/2007-01-01/", "AWSAccessKeyId", ACCESS_KEY_ID)
);

/*
Setando os headers SOAP
*/
$client->__setSoapHeaders($soapheaders);
/*
Executando a pesquisa
*/
$livros = $client->__soapCall('itemSearch', array($params));

/*
Iterando nos itens encontrados referente a busca
realizada
*/
foreach($livros->Items->Item as $item) {
/*
Obtem o nome dos autores
*/
$autores = is_array($item->ItemAttributes->Author) 
? implode(" e ", $item->ItemAttributes->Author) 
: $item->ItemAttributes->Author;

/* Preço do livro */	
$preco = @$item->ItemAttributes->ListPrice->FormattedPrice 
?: "-"; 

/*
Exibindo os dados dos livros encontrados
*/
echo <<< _HTML_
{$item->ItemAttributes->Title}
Por {$autores}
Preço: {$preco}
_HTML_; }

Agora, ao acessar nossa pequena aplicação, o resultado é realmente muito interessante como podemos observar na Figura 4.

Novo acesso ao web service

Figura 4: Novo acesso ao web service

Vale destacar aqui que o Amazon Web Service disponibiliza diversas funcionalidades. Utilizamos nesse exemplo apenas uma pequena amostra dessa poderosa ferramenta. Existem bibliotecas, que nos poupam bastante trabalho, disponíveis em várias linguagens de programação, inclusive PHP. Segue o link caso queira se aprofundar mais na área de desenvolvimento de web service para Amazon: http://aws.amazon.com/articles/4261.

Até aqui conhecemos uma das formas que o PHP fornece para trabalhar com web services, o SOAP. A partir de agora analisaremos a outra possibilidade: REST.

REST

REST é abreviação de Representational State Transfer ou, em português, Transferência de Estado Representacional. O REST difere bastante de outros métodos de web service como SOAP ou XML-RPC. Primeiro que ele não é um padrão W3C ou qualquer outro. REST não possui WSDL. Não existem frameworks, classes nativas ou extensões PHP para criação de servidores ou clientes REST.

Web services REST (RESTful é um outro termo para definir web service REST) utilizam os próprios recursos do protocolo HTTP (GET, POST, PUT, HEAD) para comunicação entre cliente e servidor. A arquitetura REST é focada principalmente em Recursos e Interfaces. Recursos representam uma funcionalidade geralmente representada por uma única URL e os métodos HTTP funcionam como uma interface para acessar os recursos. Por exemplo, a URL pode ser um recurso. Chamar essa URL através do método GET representa que queremos obter detalhes desse usuário. Já chamá-la através do método POST indica que queremos criar um novo usuário. Por sua vez, chamá-la através do método PUT indica que queremos atualizar o registro de um usuário e o método DELETE pode ser usado para excluir determinado usuário.

Normalmente as respostas de web services REST são no formato XML. A extensão SimpleXML do PHP provê a melhor interface para interagir com esses dados. A extensão SimpleXML permite uma maneira muito simples e fácil para converter dados XML para um objeto que pode ser facilmente manipulado através de propriedades ou iteração como um array.

Vamos agora a um exemplo bastante interessante de web service REST. O web service irá conectar-se a uma api REST do site delicious.com. Para quem não conhece o site delicious, ele permite criar e gerenciar bookmarks on-line. Caso não tenha uma conta no delicious e queira testar o web service abaixo, acesse o site e crie uma conta nova.

Segue na Listagem 4 o código para acessar o web service da delicious. Nesta listagem, temos um web service que conecta na API do site delicious, através de uma requisição HTTP GET, autenticando com os dados baseados no cadastro que você realizou. Essa requisição HTTP é feita diretamente pela classe SimpleXMLElement que já cria um objeto baseado no retorno da requisição que já vem no formato XML. Os dados retornados são os links favoritos que estão cadastrados na sua conta do site delicious. Na requisição GET estamos especificando o parâmetro tag com o valor “php”. Esse parâmetro indica que queremos trazer a lista de favoritos que contenham a tag “php”. Por fim, exibimos a lista obtida na tela.

Listagem 4: Acessando o web service da delicious

Ao acessar o web service criado, temos o retorno apresentado na Figura 5. Como podemos observar, a página retorna todos os links de favoritos tagueados com o termo “php”.

Página de retorno do web service

Figura 5: Página de retorno do web service

Web Service REST e SOAP no Zend Framework

Para quem não conhece o Zend framework, ele é um dos principais frameworks em PHP existente no momento. Seu foco é permitir que os desenvolvedores criem aplicações web 2.0 modernas. Além disso, disponibiliza diversas APIs de consumo de web services para Google, Amazon, Yahoo!, Flickr, Twiiter, entre outros. Essas APIs poupam um tempo de trabalho imenso caso o desenvolvedor tivesse que criar web services diretamente pelas funções da extensão SOAP ou diretamente usando REST.

Além das APIs desses serviços já prontas, o framework da Zend disponibiliza classes para que o desenvolvedor possa criar e consumir web services SOAP e REST. Vamos ver alguns exemplos dessas classes disponibilizadas pelo framework.

A principal utilização do Zend framework é a criação de aplicações MVC (Model-View-Controller). O MVC é um padrão de arquitetura de software que visa separar a lógica de negócio da lógica de apresentação, permitindo o desenvolvimento, teste e manutenção isolado de ambos. O modelo (model) é usado para definir e gerenciar o domínio da informação e notificar observadores sobre mudanças nos dados. Ele é uma representação detalhada da informação que a aplicação opera. A lógica de negócio adiciona valor semântico aos dados, e quando há mudança de estado o modelo notifica seus observadores. A visão (view) apresenta o modelo num formato adequado ao utilizador, na saída de dados, e diferentes visões podem existir para um mesmo modelo, para diferentes propósitos. Já o controlador (controller) recebe a entrada de dados e inicia a resposta ao utilizador ao invocar objetos do modelo. Ele também é responsável pela validação e filtragem da entrada de dados.

Entretanto, o framework nos possibilita trabalhar fora do padrão MVC. Nos próximos exemplos iremos trabalhar com o Zend Framework sem utilizar o MVC.

Para baixar o zend framework acesse o link de download (apresentado na seção links e baixe a última versão do pacote zip versão minimal.

Descompacte a pasta em um diretório qualquer e após descompactar mova a pasta Zend que está dentro de library para o diretório em que desejar trabalhar os exemplos criados a seguir.

Zend_Soap

No exemplo da Listagem 5 temos o web service SOAP utilizando a classe Zend_Soap_Server do framework. Este web service simplesmente disponibiliza a função metodo1() que retorna uma string baseada no parâmetro enviado pelo cliente que está consumindo este web service. Além do web service, o script tem a função de retornar o WSDL caso seja requisitado o parâmetro GET “wsdl”. Este exemplo é muito parecido com o nosso web service anterior onde usamos a extensão SOAP do PHP. A principal diferença é que estamos usando agora o SOAP no modo WSDL.

Para gerar o WSDL usamos a classe Zend_Soap_AutoDiscover que faz todo o trabalho complexo da criação do WSDL. Perceba que sua utilização é muito simples. É interessante o uso de WSDL quando existem clientes SOAP criados em outras linguagens em que o uso de WSDL é obrigatório.

Caso deseje mais informações sobre a classe Zend_Soap_Server, acesse o link http://framework.zend.com/manual/en/zend.soap.server.html.

Listagem 5: Utilizando a classe Zend_Soap_Server

setClass('ServerClass');
	$wsdl->handle();
} else {
	/*
	 * Código para criar o web service SOAP. Dessa
	 * vez no modo WSDL. Simplesmente passe a URL
	 * do WSDL como primeiro parâmetro para o 
	 * construtor.
	 */
	require_once('Zend/Soap/Server.php');
	$server = new Zend_Soap_Server('http://127.0.0.1/zf_soap_server.php?wsdl');
	$server->setClass('ServerClass');
	$server->handle();
}

/*
 * Os métodos da classe ServerClass serão disponibilizados
 * pelo web service REST. O bloco de comentário é utilizado
 * pelo Zend_Soap_AutoDiscover para criar o WSDL
 */
class ServerClass {
	/**
	 * @param string $input
	 * @return string
	 */
	public function metodo1($input) {
		return "Recebido via SOAP: $input";
	}
}

Já na Listagem 6 temos o código para consumir o web service criado anteriormente. Veja que com a utilização do SOAP no modo WSDL nosso código fica bem mais simples.

Listagem 6: Consumindo o web service definido na Listagem 5

metodo1("ZF Rulez");

Ao acessar o cliente do web service obtemos a tela da Figura 6 como resultado.

Retorno do acesso ao novo web service

Figura 6: Retorno do acesso ao novo web service

A grande vantagem de utilizar o framework da ZEND em nossos web services em SOAP é a facilidade para criar o WSDL. Para mais detalhes sobre a classe Zend_Soap_AutoDiscover acesse o link http://framework.zend.com/manual/en/zend.soap.autodiscovery.html.

Zend_Rest

O Zend Framework disponibiliza uma classe rica e simples para criarmos e consumir web services REST chamada Zend_Rest.

Na Listagem 7 temos um exemplo de web service em REST implementado através da classe Zend_Rest_Server do Zend Framework. Este web service simplesmente disponibiliza a função metodo1() que retorna uma string baseado no parâmetro enviado pelo cliente que esta consumindo este web service. A implementação é muito simples e parecida com que já vimos anteriormente. Para mais detalhes sobre essa classe acesse o link http://framework.zend.com/manual/en/zend.rest.server.html.

Listagem 7: Utilizando a classe Zend_Rest_Server

addFunction('metodo1');
$server->handle();

Na Listagem 8 temos o código que irá consumir o web service REST criado anteriormente, dessa vez implementado através da classe Zend_Rest_Client que funciona como um consumidor de web services REST. Maiores detalhes podem ser obtidos no link http://framework.zend.com/manual/en/zend.rest.client.html.

O propósito do web service abaixo é simplesmente executar a função metodo1() disponível pelo web service http://127.0.0.1/zf_rest_server.php.

Listagem 8: Consumindo o web service definido na Listagem 7

metodo1("ZF Rulez")->get();

Ao acessarmos o nosso cliente teremos o resultado apresentado na Figura 7.

Página de retorno do web service REST

Figura 7: Página de retorno do web service REST

Perceba que em nosso exemplo da classe Zend_Rest_Client fizemos uma requisição GET no link http://127.0.0.1/zf_rest_server.php. A classe Zend_Rest_Client também disponibiliza outros métodos referentes ao protocolo HTTP como post(), put(), delete(). A explicação sobre a utilização desses métodos já foi citada anteriormente neste artigo, na sessão onde falamos sobre o REST.

Como vimos anteriormente, o REST trabalha diretamente em cima do protocolo HTTP sem nenhuma outra linguagem embutida. Portanto, a nossa chamada para o metodo1() na Listagem 8 iria gerar uma query string parecida com: ?method=metodo1&arg1=ZF%20Rulez

Além dessa query string, o web service REST pode ser acessado também utilizando a query string "?method=metodo1&input=ZF%20Rulez". Isso é possível quando temos conhecimento do nome do parâmetro passado para o metodo1().

O Zend Framework contém classes já prontas que facilitam o consumo de web services dos principais serviços de comunicação na internet. Entre eles estão: Amazon, Akismet, Delicious, Ebay, Flickr, SlideShare, Twitter, Yahoo, entre outros. Para maiores detalhes acesse a documentação dessas classes através do link http://framework.zend.com/manual/en/zend.service.html.

Conclusão

A construção de webservices SOAP e REST em PHP, tanto criando quanto consumindo, é simples e eficiente. A produtividade é alta, pois o programador está focado realmente nas regras de negócio e não em detalhes técnicos dos protocolos que acontecem por trás da comunicação.

REST é conhecido por ser mais simples e fácil de trabalhar do que SOAP. A maioria dos web services na Internet utilizam REST: Twitter, Yahoo!, Flickr, del.icio.us, etc. Alguns utilizam SOAP e REST como Amazon e eBay. Já o SOAP é mais utilizado em aplicações corporativas e sistemas legados.

Cada um possui suas vantagens e desvantagens. Por exemplo, REST é mais leve e fácil de criar, não necessita de bibliotecas. SOAP tem validações, bibliotecas de desenvolvimento e é fácil de consumir. Cabe a você agora escolher entre REST e SOAP e começar a criar e consumir seus próprios web services.