Criando aplicativos da Web com YQL e PHP, Parte 1

Use PHP e YQL para recuperar e combinar dados de vários serviços da Web

A Yahoo! Query Language (YQL) fornece uma interface unificada para vários serviços da Web de terceiros, permitindo pesquisar, adicionar, atualizar e excluir dados por meio de uma sintaxe simples similar à SQL. Combine ferramentas eficientes de processamento XML em PHP com YQL e você poderá facilmente adicionar dados de serviços online a um aplicativo da Web com rapidez, eficiência e sem percorrer páginas de documentação de API.

Introdução

Atualmente, quase todos os Web sites populares têm uma API para desenvolvedor, permitindo que programadores de aplicativo da Web acessem e manipulem dados usando estruturas padrão, como REST e SOAP. Por exemplo, a Google oferece as APIs Google Data para acesso aos serviços Google, como Google Buzz, Google Docs e Google Calendar. O Twitter tem uma API REST que permite que os usuários busquem e postem tweets e o Facebook oferece a API Graph para gerenciar perfis e conexões de usuários.

Acrônimos usados frequentemente

  • API: Application program interface
  • DOM: Modelo de Objeto de Document
  • ECS: E-Commerce Service
  • HTML: Linguagem de Marcação de Hipertexto
  • ISBN: International Standard Book Number
  • JSON: JavaScript Object Notation
  • RDBMS: sistema de gerenciamento de banco de dados relacional
  • REST: Representational State Transfer
  • RSS: Really Simple Syndication
  • SOAP: Simple Object Access Protocol
  • SQL: Linguagem de Consulta Estruturada
  • URL: Localizador Uniforme de Recursos
  • XML: Linguagem de marcação extensível

Apesar de essas APIs certamente melhorarem sua vida e proporcionarem uma variedade de novos aplicativos criativos, ainda existem alguns desafios. Por exemplo, um desafio principal de implementação é a falta de uniformidade entre as APIs de diferentes sites. Alguns sites usam REST, enquanto outros usam SOAP. Alguns usam Atom para codificar dados de resposta, mas outros usam RSS, e outros ainda usam XML simples ou JSON. Como resultado, toda vez que você decidir integrar um novo serviço da Web em um aplicativo, primeiro é preciso ler muito e, em seguida, testar bastante para entender totalmente a mecânica da API de serviço antes de começar a integração.

Para resolver este problema específico, os desenvolvedores da Yahoo! decidiram inventar a Yahoo! Query Language, mais conhecida pela sigla YQL. A YQL oferece uma interface unificada similar à SQL para várias APIs de serviço da Web, simplificando de forma significativa a tarefa de integrar dados de terceiros em um aplicativo da Web. Neste artigo em duas partes, apresentarei a YQL, ilustrando como é possível usá-la em combinação com minha linguagem favorita, a PHP, para construir aplicativos da Web sofisticados.


Entendendo YQL

Se estiver familiarizado com SQL, a YQL imediatamente parecerá familiar para você. De forma muito simples, a YQL trata serviços da Web individuais como se fossem tabelas de dados, permitindo que desenvolvedores formulem consultas similares à SQL para extrair informações. O serviço YQL cuida da análise da sequência de consultas, executando-a no serviço remoto, e retornando os resultados em formato XML ou JSON padrão. A sequência de consultas em si é passada para o serviço YQL usando REST, como uma solicitação GET.

Para entender melhor esta abordagem, considere um exemplo simples. Suponha que deseje pesquisar no Twitter todos os posts contendo o termo "master chief." Sem o uso da YQL, normalmente isto seria feito usando a API Twitter Search, formulando uma solicitação como esta:

http://search.twitter.com/search.atom?q=master%20chief&lang=en

Como retorno, a API Twitter Search devolve uma feed Atom de resultados, como a da Figura 1.

Figura 1. Uma feed Atom de resultados da procura da API Twitter Search
Uma feed Atom de resultados da procura da API Twitter Search

Com YQL, é possível simplificar as coisas acessando a tabela de dados do Twitter com uma consulta YQL, da seguinte forma:

SELECT * FROM twitter.search WHERE q='master chief'

Note que isto é quase exatamente como uma consulta SQL padrão: A palavra-chave SELECT indica que é uma operação de recuperação de dados, a palavra-chave FROM especifica a origem de dados e a cláusula WHERE especifica o filtro. Depois de enviar esta consulta, a YQL retorna um documento XML ou JSON padrão com os resultados de sua consulta do Twitter, como a da Figura 2.

Figura 2. Os resultados de uma consulta YQL na tabela de dados do Twitter
Os resultados de uma consulta YQL na tabela de dados do Twitter

Agora, vamos adiantar alguns dias e supor que você tenha decidido adicionar mais alguns dados a seu aplicativo da Web. Especificamente, suponha que gostaria de usar as informações de geocodificação que acompanham os resultados da procura do Twitter para exibir também um mapa da área geográfica de onde cada postagem se originou. Além disso, suponha também que gostaria de acompanhar os resultados da procura do Twitter com uma lista de manchetes de notícias sobre o termo de procura "master chief."

Sem o uso de YQL, seria preciso gastar algum tempo lendo a documentação das APIs do Yahoo! Maps e Google News antes de realizar esta tarefa. Com YQL, é tão simples quanto adicionar algumas consultas:

SELECT * FROM google.news WHERE q="master chief"

SELECT * FROM maps.map WHERE latitude="XX" AND longitude="YY"

A Figura 3 e a Figura 4 ilustram capturas instantâneas dos resultados da consulta.

Figura 3. Os resultados de uma consulta YQL na tabela de dados do Google News
Os resultados de uma consulta YQL na tabela de dados do Google News
Figura 4. Os resultados de uma consulta YQL na tabela de dados do Yahoo Maps
Os resultados de uma consulta YQL na tabela de dados do Yahoo Maps

Os resultados da consulta nas Figuras 3 e 4 claramente indicam que o maior benefício da YQL reside em apresentar uma interface unificada para serviços da Web de terceiros. Ao permitir a consulta a serviços de terceiros usando sintaxe SQL comumente compreendida, a YQL economiza tempo e esforço e facilita a integração de dados de diversas origens em um aplicativo da Web. A capacidade de selecionar XML ou JSON como formatos de saída também é útil, permitindo maior flexibilidade e o uso de programação no lado do servidor (PHP Perl, por exemplo) ou ferramentas do lado do cliente (jQuery ou mooTools, por exemplo) para acessar e manipular os dados resultantes.


Usando o YQL Console

A forma mais fácil de começar com YQL é por meio do YQL Console, uma ferramenta online interativa que permite formular e testar consultas YQL instantaneamente. O YQL Console localiza-se na Yahoo! Developer Network e possui ferramentas de diagnóstico, consultas de amostra e uma lista de tabelas disponíveis.

Para ver como esta ferramenta funciona, navegue para o YQL Console e insira a seguinte consulta para obter uma lista de álbuns musicais populares no momento:

SELECT * FROM music.release.popular

Ao enviar o formulário, a sequência de consultas é enviada para o serviço YQL como uma sequência de consulta codificada com URL. O serviço YQL, a seguir, procura a definição de tabela, realiza a consulta e retorna os resultados. A Figura 5 ilustra como se parece a saída no YQL Console.

Figura 5. Saída da consulta no console YQL interativo
Saída da consulta no console YQL interativo

Usando YQL com PHP

Como a Figura 5 ilustra, a YQL pode retornar dados usando XML ou JSON. Ao construir aplicativos da Web PHP, o XML é normalmente mais conveniente, pois o PHP possui extensões de processamento XML integradas (SimpleXML, DOM ou XMLReader) que podem ser usadas para analisar rapidamente o documento resultante. Assim, a listagem 1 tenta realizar a mesma consulta com PHP e SimpleXML:

Listagem 1. Processando resultados YQL com SimpleXML
<?php
// execute query
// get list of 15 most popular music releases
// retrieve result as SimpleXML object
$xml = simplexml_load_file('
  http://query.yahooapis.com/v1/public/yql?q=
  SELECT * FROM music.release.popular
');

// iterate over query result set
echo '<h2>Popular Music</h2>';
$results = $xml->results;
foreach ($results->Release as $r) {
  echo '<p>';
  echo '<a href="' . $r['url'] . '">' . $r['title'] . 
    '</a> (' . $r['releaseYear'] . ') - ';  
  echo '<a href="' . $r->Artist['url'] . '">' . $r->Artist['name'] . 
    '</a> <br/>'; 
  echo 'Current chart position: ' . $r->ItemInfo->ChartPosition['this'] . 
    ' / Last chart position: ' . $r->ItemInfo->ChartPosition['last']; 
  echo '</p>';
}  
?>

A listagem 1 é iniciada com a formulação de uma consulta para o serviço da Web YQL, passando a mesma sequência de consultas codificada com URL usada no exemplo anterior. Esta solicitação é feita por meio da função simplexml_load_file() , garantindo, portanto, que o documento XML resultante seja automaticamente analisado e convertido em um objeto SimpleXML. O restante do script, então, faz iteração no nó <results> do documento XML, imprimindo o título, link, artista e posição atual de cada álbum.

A Figura 6. ilustra o resultado.

Figura 6. Uma lista de lançamentos de músicas populares, recuperadas por meio da YQL
Uma lista de lançamentos de músicas populares, recuperadas por meio da YQL

Se você usar a Zend Framework, poderá, de forma alternativa, acessar o serviço da Web YQL usando o componente Zend_Rest_Client. A listagem 2, que produz saída equivalente a da listagem 1, ilustra isso.

Listagem 2. Processando resultados YQL com a Zend Framework
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');

// execute YQL query
// get list of most popular music releases
try {
  $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
  $client->q('SELECT * FROM music.release.popular');
  $result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
    echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

// iterate over query result set
echo '<h2>Popular Music</h2>';
foreach ($result->Release as $r) {
  echo '<p>';
  echo '<a href="' . $r['url'] . '">' . $r['title'] . 
    '</a> (' . $r['releaseYear'] . ') - ';  
  echo '<a href="' . $r->Artist['url'] . '">' . $r->Artist['name'] . 
    '</a> <br/>'; 
  echo 'Current chart position: ' . $r->ItemInfo->ChartPosition['this'] . 
    ' / Last chart position: ' . $r->ItemInfo->ChartPosition['last']; 
  echo '</p>';
} 
?>

O componente Zend_Rest_Client da Zend Framework foi projetado especificamente para desenvolvedores que tentam integrar aplicativos PHP com serviços da Web baseados em REST. Com este cliente, é possível realizar respostas GET, POST, PUT e DELETE para um terminal de serviço REST. As respostas REST são retornadas como instâncias de objetos Zend_Rest_Client_Response, o que torna fácil acessar propriedades de respostas individuais.

listagem 2 primeiro carrega as bibliotecas classe Zend e, em seguida, inicializa uma instância da classe Zend_Rest_Client. Este cliente é usado para inicializar uma solicitação GET não autenticada para o terminal do serviço da Web YQL, como foi feito anteriormente na listagem 1. O arquivo XML retornado é, então, analisado e convertido em um objeto Zend_Rest_Client_Response, que pode ser processado usando um loop foreach() padrão. Note que, ao usar o objeto Zend_Rest_Client, não é necessário codificar com URL a consulta YQL, pois o componente se encarrega daquela etapa internamente.


Filtrando e classificando resultados da consulta

Como com consultas SELECT regulares, a YQL permite filtrar resultados da consulta com uma cláusula WHERE, especificar campos obrigatórios e classificar resultados por um ou mais campos. Para ilustrar, considere a seguinte consulta à API Flickr para obter uma lista de locais que correspondam ao termo de procura "england":

SELECT * FROM flickr.places WHERE query="england"

A Figura 7 ilustra a resposta da YQL a esta consulta.

Figura 7. Uma lista de resultados da procura por "england", recuperada do Flickr por meio da YQL
Uma lista de resultados da procura por

A listagem 3 ilustra esta consulta na prática.

Listagem 3. Filtrando resultados YQL com uma cláusula WHERE
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');

// execute YQL query
// get list of Flickr places matching search term
try {
  $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
  $client->q('SELECT * FROM flickr.places WHERE query="england"');
  $result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
    echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

// iterate over query result set
echo '<h2>Search Results</h2>';
echo '<table border=1>';
echo '<tr><th>Name</th><th>Latitude</th><th>
Longitude</th></tr>';
foreach ($result->place as $p) {
  echo '<tr>';
  echo '<td>' . $p . '</td>';  
  echo '<td>' . $p['latitude'] . '</td>';  
  echo '<td>' . $p['longitude'] . '</td>';  
  echo '</tr>';
}  
echo '</table>';
?>

A Figura 8 exibe a saída formatada da listagem 3.

Figura 8. Uma lista formatada de resultados da procura por "england", recuperada do Flickr por meio da YQL
Uma lista formatada de resultados da procura por

É possível adicionar critérios de filtro adicionais com operadores AND e OR. Considere esta revisão da consulta anterior, que filtra adicionalmente os resultados por fuso horário:

SELECT * FROM flickr.places WHERE query="england" AND timezone LIKE "%europe%"

É possível restringir a saída da consulta somente a campos específicos. Esta abordagem é útil quando é necessário somente um pequeno subconjunto dos dados retornados pelo serviço da Web e também reduz o tamanho do pacote de resposta. Segue uma revisão do exemplo anterior, que recupera somente a latitude, longitude e o nome de cada registro:

SELECT latitude, longitude, content FROM flickr.places WHERE query="england"

A YQL também suporta várias funções de utilitário que podem ser usadas para classificar, contar e eliminar duplicações do conjunto de resultados. Essas funções são comumente colocadas depois da sequência de consultas YQL, separadas por um caractere pipe (|). Considere a seguinte consulta, que classifica os resultados por latitude:

SELECT latitude, longitude, content FROM flickr.places 
  WHERE query="england" | sort (field="latitude")

Também é possível aplicar o filtro para remover duplicações do resultado, especificando o campo que deverá ser verificado:

SELECT * FROM flickr.places 
  WHERE query="england" | unique (field="timezone")

A listagem 4 reúne isto tudo em uma ferramenta de consulta interativa que pede ao usuário que insira um nome de local e retorna uma lista classificável de resultados.

Listagem 4. Procurando por nomes de lugares
<html>
  <head></head>
  <body>  
    <form method="post" action="<?php echo htmlentities
    ($_SERVER['PHP_SELF']); ?>">
    Search term:
    <input type="text" name="q" />
    Sort results by:
    <select name="s">
      <option value="timezone">Time zone</option>
      <option value="latitude">Latitude</option>
      <option value="longitude">Longitude</option>
    </select>
    <input type="submit" name="submit" value="Search" />    
    </form>
    <?php
    // check if form is submitted
    // perform necessary validation (omitted for brevity)
    if (isset($_POST['submit'])) {
      // set up Zend auto-loader
      // load Zend REST client classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Rest_Client');
      
      // execute YQL query
      // get list of Flickr places matching search term
      // sort by requested field
      try {
        $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
        $client->q(
          'SELECT latitude, longitude, timezone, content FROM flickr.places 
            WHERE query="' . $_POST['q'] .'" | sort(field="' . $_POST['s'] . '")');
        $result = $client->get();
      } catch (Zend_Rest_Client_Exception $e) {
          echo "Client error: " . $e->getResponse();
      } catch (Exception $e) {
          echo "Error: " . $e->getMessage();
      }
      
      // iterate over query result set
      echo '<h2>Search Results</h2>';
      echo '<table border=1>';
      echo '<tr><th>Name</th><th>Timezone</th>
        <th>Latitude</th><th>Longitude</th></tr>';
      foreach ($result->place as $p) {
        echo '<tr>';
        echo '<td>' . $p . '</td>';  
        echo '<td>' . $p['timezone'] . '</td>';  
        echo '<td>' . $p['latitude'] . '</td>';  
        echo '<td>' . $p['longitude'] . '</td>';  
        echo '</tr>';
      } 
      echo '</table>';
    }
    ?>
  </body>
</html>

A Figura 9 ilustra a listagem 4 em ação.

Figura 9. Uma procura interativa e filtro de classificação para nomes de locais
Uma procura interativa e filtro de classificação para nomes de locais

Para obter uma lista completa de funções YQL, consulte o Guia de YQL (consulte Recursos para obter um link).


Um aplicativo de exemplo: Previsão do tempo por localização

Veremos agora como reunir tudo que você aprendeu até agora para construir um aplicativo simples com base em YQL usando PHP. A listagem 5 pede ao usuário que insira sua localidade em um formulário, e depois, conecta-se ao serviço Yahoo! Serviço de previsão do tempo por meio da tabela weather.bylocation e consultas para uma previsão do tempo local para aquela localidade. Veja o código na listagem 5.

Listagem 5. Recuperando previsões do tempo por localidade
<html>
  <head></head>
  <body>  
    <form method="post" action="<?php echo htmlentities
    ($_SERVER['PHP_SELF']); ?>">
    Enter city name:
    <input type="text" name="city" />
    <input type="submit" name="submit" value="Get forecast" />    
    </form>
    <?php
    // check if form is submitted
    // perform necessary validation (omitted for brevity)
    if (isset($_POST['submit'])) {
      // set up Zend auto-loader
      // load Zend REST client classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Rest_Client');

      // execute YQL query
      // get Yahoo! Weather forecast for selected zip code
      try {
        $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
        $client->env('store://datatables.org/alltableswithkeys');  
        $client->q('SELECT * FROM weather.bylocation 
          WHERE location="' . $_POST['city'] . '"');
        $result = $client->get();
      } catch (Zend_Rest_Client_Exception $e) {
          echo "Client error: " . $e->getResponse();
      } catch (Exception $e) {
          echo "Error: " . $e->getMessage();
}

      // process and print query results
      $data = $result->results->weather->rss->channel->item;
      echo '<h2>' . $data->title . '</h2>';
      echo $data->pubDate . '<br/>';      
      echo $data->description;
    }
    ?>
  </body>
</html>

Depois que o formulário da Web for enviado com um nome de cidade, a listagem 5 usa o componente Zend_Rest_Client para enviar uma consulta YQL para o serviço do tempo. A consulta usa a cláusula WHERE para filtrar o conteúdo da tabela weather.bylocation e recuperar uma previsão do tempo para o CEP especificado. O resultado da consulta é formatado e apresentado como uma página HTML. A Figura 10 ilustra o resultado.

Figura 10. Previsões do tempo por cidade, recuperadas por meio da YQL
Previsões do tempo por cidade, recuperadas por meio da YQL

Note também que a listagem 5 adiciona uma nova variável à sequência de consultas, env. Esta variável é necessária porque a tabela de dados weather.bylocation é chamada de tabela de comunidade, mantida pela comunidade e não pelo Yahoo! propriamente dito. Como resultado, o serviço YQL não reconhece, de maneira automática, a localização da definição desta tabela. A variável env é usada para especificar a localização dos arquivos de definição de tabela. Neste caso, a localização é Community Open Data Tables do Web site da YQL, que serve como um repositório para todas as tabelas da comunidade da YQL (consulte Recursos para obter um link).


Usando consultas YQL aninhadas

O maior valor de um RDBMS tradicional vem de sua capacidade de reunir tabelas individuais para criar diferentes visualizações dos dados contidos nelas. E uma das melhores coisas sobre YQL é que ela permite fazer a mesma coisa com serviços da Web. Usando consultas YQL, é possível combinar dados de vários serviços da Web para apresentar visualizações úteis e novas de dados de terceiros.

Apesar de as possíveis aplicações deste recurso serem limitadas somente por sua criatividade, um exemplo simples pode ajudar a esclarecer o poder deste recurso. Considere a listagem 6, que pede ao usuário que insira o nome de um país e, a seguir, consulta o serviço da Web de entrada para listar os eventos futuros daquele país.

Listagem 6. Buscando eventos por país
<html>
  <head></head>
  <body>  
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
    Search for events in:
    <input type="text" name="country" />
    <input type="submit" name="submit" value="Search" />    
    </form>
    <?php
    // check if form is submitted
    // perform necessary validation (omitted for brevity)
    if (isset($_POST['submit'])) {
      // set up Zend auto-loader
      // load Zend REST client classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Rest_Client');

      // execute YQL query
      // get list of events in requested country
      try {
        $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
        $client->q(
          "SELECT * FROM upcoming.events 
            WHERE country_id IN 
              (SELECT id FROM upcoming.country 
                WHERE name = '" . ucfirst($_POST['country']) . "')");    
        $result = $client->get();
      } catch (Zend_Rest_Client_Exception $e) {
          echo "Client error: " . $e->getResponse();
      } catch (Exception $e) {
          echo "Error: " . $e->getMessage();
}

      // iterate over query result set
      echo '<h2>Events in ' . ucfirst($_POST['country']) . '</h2>';
      foreach ($result->event as $e) {
        echo '<p>';
        echo '<a href="' . $e['url'] . '">' . $e['name'] . 
          '</a> <br/>';
        echo 'Starts: ' . date('d M Y', strtotime($e['start_date'])). '<br/>'; 
        echo !empty($e['end_date']) ?  'Ends: ' . 
          date('d M Y', strtotime($e['end_date'])) . '<br/>' : '';
        echo 'Location: ' . $e['venue_name'] . '<br/>';
        echo 'Address: ' . 
          sprintf('%s, %s', $e['venue_address'], $e['venue_city']) . '<br/>';
        echo $e['description'] . '<br/>';
        echo '</p>';
      } 
}
?>  
  </body>
</html>

A listagem 6 usa duas consultas YQL aninhadas. A consulta interna acessa a tabela de dados "upcoming.country" para recuperar o ID numérico correspondente à cadeia de caractere de país inserida pelo usuário. Este ID numérico é, a seguir, passado para a consulta externa para recuperar uma lista de eventos vinculados ao ID daquele país.

A Figura 11 ilustra um exemplo do resultado.

Figura 11. Uma lista de eventos a serem realizados, que podem ser pesquisados por país
Uma lista de eventos a serem realizados, que podem ser pesquisados por país

É importante notar que, tecnicamente, isto não é uma junção, mas uma subconsulta. Quando este artigo estava sendo elaborado, a YQL não permitia o vínculo de tabelas por meio de chaves comuns (uma junção), mas somente usar os resultados de uma consulta dentro de outra (uma subconsulta).


Um aplicativo de exemplo: Listas e preços de livros mais vendidos

Como você pode imaginar, a capacidade de combinar dados de várias interfaces da Web usando sintaxe simples similar à da SQL é excelente para os desenvolvedores de mashup. Portanto, vamos considerar outro aplicativo um pouco mais complicado: combinar dados das listas de livros mais vendidos do The New York Times com informações de preços do banco de dados da Amazon.com para apresentar uma visualização composta de livros populares, seus preços e sua popularidade.

A primeira etapa na construção deste aplicativo é recuperar a lista atual dos livros mais vendidos do New York Times . A YQL disponibiliza estas informações por meio de sua tabela nyt.bestsellers, mas é preciso uma chave de API válida para executar consultas nesta tabela. Presumindo que você tenha esta chave (consulte Recursos para obter um link que explica como obtê-la), é possível recuperar a lista atual de livros de ficção de capa dura mais vendidos na semana de 21 de julho de 2010 usando uma consulta como esta:

SELECT * FROM nyt.bestsellers WHERE listname='Hardcover Fiction' 
AND date='2010-07-21' AND apikey='NYT-API-KEY'

A Figura 12 ilustra a saída desta consulta.

Figura 12. Uma lista dos livros mais vendidos do New York Times , recuperados por meio da YQL
Uma lista dos livros mais vendidos do New York Times , recuperados por meio da YQL

Note que cada registro do resultado lista o número ISBN exclusivo do livro. Estas são informações críticas para a segunda parte do aplicativo, que precisa procurar o preço do livro em Amazon.com.

Recuperar dados de precificação de Amazon.com pode parecer uma tarefa difícil à primeira vista, mas, na realidade, não poderia ser mais simples. A Amazon.com expõe seu banco de dados de produtos para desenvolvedores de terceiros por meio de seu serviço da Web Amazon ECS (consulte Recursos para obter um link e informações sobre como obter uma chave da API). E a YQL inclui uma tabela de dados para a Amazon ECS, tornando possível recuperar informações de precificação para um ISBN particular com uma consulta como esta:

SELECT DetailPageURL, ItemAttributes, SalesRank, MediumImage FROM amazon.ecs 
WHERE AWSAccessKeyId='AWS-KEY' AND secret='AWS-SECRET-KEY' 
AND ResponseGroup='Medium' AND Operation = 'ItemLookup' 
AND ItemAttributes.Binding = 'Hardcover' AND ItemId = '1400065453'

A Figura 13 ilustra a saída desta consulta.

Figura 13. Dados de produto da Amazon.com, recuperados por meio da YQL
Dados de produto da Amazon.com, recuperados por meio da YQL

Deve estar claro que as duas consultas anteriores podem ser facilmente combinadas para produzir as informações necessárias. A listagem 7 tem o script completo. Lembre-se de substituir as chaves simuladas da API nas consultas com suas próprias chaves antes de executá-las.

Listagem 7. Recuperando listas e preços de livros mais vendidos
<html>
  <head>
    <style type="text/css">
    .item {
      float: left;
      width: 400px;      
      padding:10px;   
    }
    .cover {
      float:left; 
      padding: 5px;
      border: solid 1px black;      
    }
    .data {
      margin-left: 150px;
      font-weight: bolder;  
    }
    </style>
  </head>
  <body>
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');

// execute YQL query
// get list of NYT bestsellers
// retrieve image and price from Amazon.com
try {
  $client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
  $client->env('store://datatables.org/alltableswithkeys');  
  $client->q(
    "SELECT DetailPageURL, ItemAttributes, SalesRank, MediumImage FROM amazon.ecs 
      WHERE AWSAccessKeyId='AWS-KEY' 
      AND secret='AWS-SECRET-KEY' 
      AND ResponseGroup='Medium' 
      AND Operation = 'ItemLookup' 
      AND ItemAttributes.Binding = 'Hardcover' 
      AND ItemId IN 
        (SELECT isbns.isbn.isbn10 FROM nyt.bestsellers 
          WHERE apikey='NYT-KEY' 
          AND listname='Hardcover Fiction' 
          AND date='2010-07-20') 
    | unique(field='ItemAttributes.Title')");    
  $result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
    echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

// iterate over query result set
echo '<h2>New York Times - Hardcover Fiction Bestsellers</h2>';
$count = 1;
foreach ($result->results->Item as $r) {
  echo '<div class="item">';
  echo '<img class="cover" src="' . $r->MediumImage->URL . '"/>';
  echo '<div class="data">';
  echo $count . '. ';
  echo '<a href="' . $r->DetailPageURL . '">' . 
    $r->ItemAttributes->Title . '</a>';
  echo ' - '. $r->ItemAttributes->Author . '<br/>';
  echo 'Amazon.com Sales Rank: ' . $r->SalesRank . '<br/>';
  echo 'Amazon.com Price: ' . 
    $r->ItemAttributes->ListPrice->FormattedPrice . '';
  echo '</div></div>';
  $count++;
}  
?>  
  </body>
</html>

A listagem 7 combina as duas consultas anteriores usando a chave ISBN como o denominador comum para produzir um resultado composto contendo títulos, autores, imagens preços e classificações de vendas dos livros. Este resultado é, a seguir, analisado e processado para gerar uma página HTML (Figura 14).

Figura 14. Uma lista de livros mais vendidos, combinada com dados do produto por meio da YQL
Uma lista de livros mais vendidos, combinada com dados do produto por meio da YQL

Note que na listagem 7, a consulta interna recupera especificamente somente os números ISBN-10 dos livros nas listas de livros mais vendidos. Como estas informações estão alguns nós abaixo na árvore, a notação de pontos é usada para indicar a posição hierárquica exata dos nós necessários para os analisados da consulta. Uma técnica similar é usada ao aplicar o filtro exclusivo à consulta externa, com a notação de pontos usada para indicar o campo pelo qual os resultados deverão ser filtrados.


Conclusão

Como esses exemplos ilustram, a YQL é uma ferramenta eficiente para desenvolvedores de aplicativos da Web: ela apresenta uma interface unificada para diferentes serviços da Web, permitindo um mecanismo de consulta padrão similar à SQL que acelera o desenvolvimento e requer menos informações sobre o serviço de destino. É possível filtrar resultados YQL com cláusulas WHERE e combinar, ou fazer "mash up", de dados de vários serviços por meio do uso de sub-selects. Adicione o PHP, com suas eficientes ferramentas de processamento de XML, à equação e você terá uma combinação com a qual até mesmo o desenvolvedor da Web mais experiente aproveitará!

Os exemplos deste artigo não abrangeram todo o conteúdo. É possível fazer muito mais com a YQL, incluindo paginação de consultas de resultados, extração de dados de documentos RSS, Atom, XML e HTML e adição e modificação de dados com consultas CREATE e UPDATE. Farei uma abordagem mais ampla na segunda parte deste artigo, então volte logo.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=647348
ArticleTitle=Criando aplicativos da Web com YQL e PHP, Parte 1
publish-date=04142011