Web service é um sistema de software projetado para suportar interações máquina-máquina interoperáveis através de uma rede. No contexto de aplicações Web geralmente refere-se a um conjunto de APIs que podem ser acessadas através da Internet e executadas em um sistema remoto que hospeda o serviço solicitado. Por exemplo, um cliente baseado em Flex, poderá chamar uma função implementada no lado do servidor rodando uma aplicação Web baseada em PHP. Web Service se baseia em SOAP como a camada principal da pilha de protocolo de comunicação.
O Yii fornece as classes CWebService e CWebServiceAction para simplificar o trabalho de implementação de Web Service em uma aplicação Web. As APIs são agrupadas dentro de classes chamadas de prestadores de serviço. O Yii irá gerar para cada classe uma especificação WSDL que descreve quais APIs estão disponíveis e como elas devem ser chamadas pelo cliente. Quando uma API é chamada por um cliente, o Yii irá instanciar o prestador de serviço correspondente e chamar a API requisitada para executar a requisição.
Nota: A classe CWebService é depende da Extensão PHP SOAP. Tenha certeza que você possui ela habilitada antes de testar os exemplos disponíveis nesta seção.
Como mencionado acima, o prestador de serviços é uma classe que define os métodos que podem ser chamados remotamente. O Yii se baseia em comentários de documentação e reflexão de classes para identificar quais métodos podem ser chamados remotamente e quais são os seus parâmetros e valores retornados.
Vamos iniciar com um simples serviço de cotação de ações. Este serviço
permite uma requisição de um cliente para cotar uma ação específica.
Definimos o prestador de serviços como a seguir. Note que definimos a classe
prestadora de serviço StockController
como extensão de CController. Isto
não é obrigatório. Explicaremos mais adiante por que fazemos dessa forma.
class StockController extends CController
{
/**
* @param string símbolo da ação
* @return float preço da ação
* @soap
*/
public function getPrice($symbol)
{
$prices=array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol])?$prices[$symbol]:0;
//...retorna o preço da ação para o $symbol
}
}
Acima declaramos o método getPrice
para ser a API do Web Service, marcando-o
com a tag @soap
no comentário de documentação. Contamos com a documentação de
comentário para especificar o tipo de dados dos parâmetros de entrada e dos valores
de retorno. APIs adicionais podem ser declaradas de forma semelhante.
Uma vez definido o prestador de serviço, precisamos fazer com que ele esteja
disponível para os clientes. Particularmente, precisamos criar uma ação de controle
para expor este serviço. Isto pode ser feito facilmente declarando uma ação
CWebServiceAction na classe de controle. Para exemplificar, colocamos ela na classe
StockController
.
class StockController extends CController
{
public function actions()
{
return array(
'quote'=>array(
'class'=>'CWebServiceAction',
),
);
}
/**
* @param string símbolo da ação
* @return float preço da ação
* @soap
*/
public function getPrice($symbol)
{
//...retorna o preço da ação para o $symbol
}
}
Isto é tudo o que precisamos para criar um Web Service!
Se tentar acessar a ação através da URL http://hostname/path/to/index.php?r=stock/quote
,
vamos ver um monte de conteúdo XML que é o WSDL para o Web Service que definimos .
Dica: Por padrão, CWebServiceAction assume que o controller corrente é o prestador de serviço. É por isso que definimos o método
getPrice
dentro da classeStockController
.
Para completar o exemplo, vamos criar um cliente que utiliza o Web Service
que acabamos de criar. O cliente de exemplo é escrito em PHP, porém, ele
poderia ser em outra linguagem como Java
, C#
, Flex
, etc.
$client=new SoapClient('http://hostname/path/to/index.php?r=stock/quote');
echo $client->getPrice('GOOGLE');
Executando o script acima em modo Web ou console e veremos que 350
é o preço
para GOOGLE
.
Quando declaramos métodos e propriedades de classes que são acessadas remotamente, precisamos especificar o tipo de dados dos parâmetros de entrada e saída. A seguir, os tipos de dados mais primitivos que podemos utilizar:
xsd:string
;xsd:int
;xsd:float
;xsd:boolean
;xsd:date
;xsd:time
;xsd:dateTime
;xsd:string
;xsd:struct
;xsd:anyType
.Se um tipo não é um dos descritos acima, ele será considerado como um
tipo composto que consiste de propriedades. Um tipo composto é representado
em termos de uma classe e suas propriedades como variáveis públicas da classe,
marcadas com a tag @soap
em seu comentário de documentação.
Podemos utilizar também o tipo array adicionando []
no final do tipo primitivo
ou composto. Isto poderia especificar um array de um tipo específico.
Abaixo um exemplo que define a Web API getPosts
que retorna um array de
objetos Post
.
class PostController extends CController
{
/**
* @return Post[] uma lista de Post
* @soap
*/
public function getPosts()
{
return Post::model()->findAll();
}
}
class Post extends CActiveRecord
{
/**
* @var integer ID do post
* @soap
*/
public $id;
/**
* @var string título do post
* @soap
*/
public $title;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
Para receber parâmetros de tipo composto de um cliente, um aplicativo precisa declarar o mapeamento de tipos WSDL para as classes PHP correspondentes. Isto é realizado configurando a propriedade classMap de CWebServiceAction.
class PostController extends CController
{
public function actions()
{
return array(
'service'=>array(
'class'=>'CWebServiceAction',
'classMap'=>array(
'Post'=>'Post', // ou simplesmente 'Post'
),
),
);
}
......
}
Com a implementação da interface IWebServiceProvider, um prestador de serviço pode interceptar chamadas a método remoto. Em IWebServiceProvider::beforeWebMethod, o prestador de serviços pode recuperar o estado atual da instância de CWebService e obter o nome do método que está sendo chamado atualmente através de CWebService::methodName. Ele pode retornar false se o método remoto não pode ser chamado por algum motivo (por exemplo, acesso não autorizado).
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.