PD
Disponibilizando Web Services pelo Adianti Framework com REST
Fechado
Durante o desenvolvimento de um sistema, é comum termos de disponibilizar algumas de suas rotinas para que estas sejam executadas por aplicativos externos. O caminho mais utilizado para tal é por meio de Web Services, e REST é um dos meios para se obter isto. Imagine que você desenvolveu todo um sistema que controla produtos, e agora precisa que outros sistemas possam consultar informações a respeito destes produtos. Neste artigo veremos como disponibilizar métodos criados no Adianti Framework por meio de Web Services. Neste artigo, trabalharemos com a classe de Produtos, e criaremos um Web Service para retornar X produtos, sendo a partir de um intervalo definido (from, to).
Bom, em primeiro lugar, provavelmente você já tem uma série de classes de modelo representando suas tabelas na pasta app/model. Junto ao tutor, temos por exemplo a classe Product. Agora, queremos criar um Web Service para retornar X produtos. Para tal, precisamos criar uma classe de serviço. Uma classe de serviço age criando uma camada que interage com uma funcionalidade interna da aplicação e expõe esta funcionalidade para o mundo externo. Neste caso, vamos chamar a classe de ProductService e salvar em app/service/ProductService.php. Veja que a classe em questão, utiliza a classe Product, já existente em app/model/Product.php, e também usa a conexão "samples", existente em app/config/samples.ini
A classe ProductService terá o método getBetween() que retornará todos os produtos cujo ID está entre dois valores informados. Para tal, este método receberá o request HTTP como um parâmetro (array) com cada um dos parâmetros da chamada do Web Service. Neste exemplo, estes parâmetros identificam o código inicial (['from']) e final (['to']) dos produtos a serem obtidos.
app/service/ProductService.php
O próximo passo é habilitar um servidor REST no Adianti Framework. Para tal, basta salvarmos o arquivo a seguir no diretório raíz da aplicação com o nome de rest.php. Este script NÃO FAZ PARTE da instalação default do framework por questões de segurança. Como este arquivo disponibiliza as classes do framework para utilização externa, é IMPRESCINDÍVEL implementar um mecanismo de controle, ou seja, filtrar somente as requisições válidas. Para tal, foi colocado ali no arquivo um lembrete (// aqui implementar mecanismo de controle).
Não abordaremos aqui como adicionar segurança à chamada REST, mas uma das formas, é passando uma chave de segurança ou utilizar Token-Based Authorization. Por enquanto, faremos apenas um filtro para permitir somente algumas classes (in_array).
/rest.php
Agora que já temos a classe de serviço criada, basta invocarmos o Web Service pela linha de comando. Neste caso, basta copiarmos este trecho de arquivo e salvarmos com um nome qualquer (ex: rest_client.php), e executarmos ele pela linha de comando. Antes, lembre de substituir a variável location pelo caminho de sua aplicação
rest_client.php
Pronto, você obterá como resultado os produtos 1 a 4 na forma de um array retornado pelo serviço.
Você também poderá fazer uma chamada Javascript, dessa maneira:
PS: Ao criarmos uma camada específica para serviços (ProductService), desoneramos a classe de modelo (ProductService), e também evitamos de colocar lá chamadas para bibliotecas externas, o que não é recomendado para uma camada de modelo.
Bom, em primeiro lugar, provavelmente você já tem uma série de classes de modelo representando suas tabelas na pasta app/model. Junto ao tutor, temos por exemplo a classe Product. Agora, queremos criar um Web Service para retornar X produtos. Para tal, precisamos criar uma classe de serviço. Uma classe de serviço age criando uma camada que interage com uma funcionalidade interna da aplicação e expõe esta funcionalidade para o mundo externo. Neste caso, vamos chamar a classe de ProductService e salvar em app/service/ProductService.php. Veja que a classe em questão, utiliza a classe Product, já existente em app/model/Product.php, e também usa a conexão "samples", existente em app/config/samples.ini
A classe ProductService terá o método getBetween() que retornará todos os produtos cujo ID está entre dois valores informados. Para tal, este método receberá o request HTTP como um parâmetro (array) com cada um dos parâmetros da chamada do Web Service. Neste exemplo, estes parâmetros identificam o código inicial (['from']) e final (['to']) dos produtos a serem obtidos.
app/service/ProductService.php
- <?php
- class ProductService
- {
- /**
- * Retorna todos produtos entre $from e $to
- * @param $request HTTP request
- */
- public static function getBetween( $request )
- {
- TTransaction::open('samples');
- $response = array();
- // define o critério
- $criteria = new TCriteria;
- $criteria->add(new TFilter('id', '>=', $request['from']));
- $criteria->add(new TFilter('id', '<=', $request['to']));
- // carrega os produtos
- $all = Product::getObjects( $criteria );
- foreach ($all as $product)
- {
- $response[] = $product->toArray();
- }
- TTransaction::close();
- return $response;
- }
- }
- ?>
O próximo passo é habilitar um servidor REST no Adianti Framework. Para tal, basta salvarmos o arquivo a seguir no diretório raíz da aplicação com o nome de rest.php. Este script NÃO FAZ PARTE da instalação default do framework por questões de segurança. Como este arquivo disponibiliza as classes do framework para utilização externa, é IMPRESCINDÍVEL implementar um mecanismo de controle, ou seja, filtrar somente as requisições válidas. Para tal, foi colocado ali no arquivo um lembrete (// aqui implementar mecanismo de controle).
Não abordaremos aqui como adicionar segurança à chamada REST, mas uma das formas, é passando uma chave de segurança ou utilizar Token-Based Authorization. Por enquanto, faremos apenas um filtro para permitir somente algumas classes (in_array).
/rest.php
- <?php
- // initialization script
- require_once 'init.php';
- class AdiantiRestServer
- {
- public static function run($request)
- {
- $class = isset($request['class']) ? $request['class'] : '';
- $method = isset($request['method']) ? $request['method'] : '';
- $response = NULL;
- // aqui implementar mecanismo de controle !!
- if (!in_array($class, array('ProductService')))
- {
- return json_encode( array('status' => 'error',
- 'data' => _t('Permission denied')));
- }
- try
- {
- if (class_exists($class))
- {
- if (method_exists($class, $method))
- {
- $rf = new ReflectionMethod($class, $method);
- if ($rf->isStatic())
- {
- $response = call_user_func(array($class, $method), $request);
- }
- else
- {
- $response = call_user_func(array(new $class($request), $method), $request);
- }
- return json_encode( array('status' => 'success', 'data' => $response));
- }
- else
- {
- $error_message = TAdiantiCoreTranslator::translate('Method ^1 not found', "$class::$method");
- return json_encode( array('status' => 'error', 'data' => $error_message));
- }
- }
- else
- {
- $error_message = TAdiantiCoreTranslator::translate('Class ^1 not found', $class);
- return json_encode( array('status' => 'error', 'data' => $error_message));
- }
- }
- catch (Exception $e)
- {
- return json_encode( array('status' => 'error', 'data' => $e->getMessage()));
- }
- }
- }
- print AdiantiRestServer::run($_REQUEST);
- ?>
Agora que já temos a classe de serviço criada, basta invocarmos o Web Service pela linha de comando. Neste caso, basta copiarmos este trecho de arquivo e salvarmos com um nome qualquer (ex: rest_client.php), e executarmos ele pela linha de comando. Antes, lembre de substituir a variável location pelo caminho de sua aplicação
rest_client.php
- <?php
- $location = 'http://www.meusistema.local/rest.php';
- $parameters = array();
- $parameters['class'] = 'ProductService';
- $parameters['method'] = 'getBetween';
- $parameters['from'] = '1';
- $parameters['to'] = '4';
- $url = $location . '?' . http_build_query($parameters);
- var_dump( json_decode( file_get_contents($url) ) );
- ?>
php5 rest_client.php
Pronto, você obterá como resultado os produtos 1 a 4 na forma de um array retornado pelo serviço.
Você também poderá fazer uma chamada Javascript, dessa maneira:
$.ajax({
type: 'GET',
url: 'http://www.meusistema.local/rest.php',
data: {
'class': 'ProductService',
'method': 'getBetween',
'from': '1',
'to': '4'
},
dataType: 'json',
success: function (response) {
console.log(response.data);
}
});
PS: Ao criarmos uma camada específica para serviços (ProductService), desoneramos a classe de modelo (ProductService), e também evitamos de colocar lá chamadas para bibliotecas externas, o que não é recomendado para uma camada de modelo.
Olá Pablo
Necessitei consumir alguns dados do sistema que desenvolvi com o Adianti framework, utilizei esta forma abaixo para gerar o JSON que é consumido pelo aplicativo móvel em Android.
Criei o diretório chamado service coloquei dentro do diretório app, ficando app/service/nomearquivo.class.php
Deu certo estou utilizando como uma aplicação backend.
Obrigado tbm pela sua dica.
Isso resolveu meu problema de impressão de etiquetas.
Delphi + FastReport consumindo um serviço de Dados do Adianti.
Parabéns, Ótimo Artigo.
Boa tarde,
Pessoal estou com dificuldades, até aqui entendi, mais peguei um processo que exige autenticação e não estou conseguindo fazer... abaixo segue trecho do documento do sistema:
"Para garantir a segurança e privacidade dos dados dos clientes que optarem por utilizar a API de Integração, além de disponibilizar os métodos consumíveis através de protocolo HTTPS, foram definidas formas de autenticação para o cliente, mantendo assim a privacidade dos dados. Para que esta autenticação seja possível no Header de cada requisição realizada pelo modulo do cliente a API de Integração devem constar os seguintes cabeçalhos:
Authorization-Token: 123456789
User: teste@email.com.br
App: xyz
como implemento isso nesse exemplo rest_client.php ?
Pablo, tudo bem, como seria forma correta de fazer um post passando Json para classe para inserir no banco ?, com pego isso cabeçalho ?
Carlos e Eduardo,
O php tem a função "get_headers" (php.net/manual/pt_BR/function.get-headers.php), com ela vocês podem ler os cabeçalhos da requisição e implementar a camada de segurança.
Bom dia Pablo
Fiz o exemplo acima descrito e funcionou a partir do script PHP, listou os usuarios do sistema mas precisei acessar estes mesmos dados pelo android e apresenta erro 404.
Você poderia me explicar alguma forma de acessar este ws rest pelo android? o meu script está mostrando erro 404 e nesta linha
no android criei a URL
Caso possa me ajudar agradeço.
Flávio Cardoso
</Usuario>