Avançar para a área de conteúdo

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

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

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

  • Fechar [x]

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.

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

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

  • Fechar [x]

Integre seus aplicativos PHP com o Google Contacts

Leia e grave informações de contato do Google Contacts com XML e PHP

Vikram Vaswani, Founder, Melonfire
Photo of Vikram Vaswani
Vikram Vaswani é o fundador e Presidente da Melonfire (este link reside fora de ibm.com), uma empresa de serviços de consultoria com conhecimento especial sobre ferramentas e tecnologias de software livre. Ele também é o autor dos livros PHP Programming Solutions (este link reside fora de ibm.com) e PHP: A Beginners Guide (este link reside fora de ibm.com).

Resumo:  A API de Dados do Google Contacts oferece uma API poderosa e neutra em relação ao cliente para ler e modificar as informações de contato privadas de um usuário do Gmail. Saiba como recuperar, adicionar, excluir e modificar contatos através de aplicativos customizados PHP com esta API em um contexto de aplicativos.

Data:  26/Out/2009
Nível:  Intermediário
Atividade:  3603 visualizações
Comentários:  


Introdução

Como a maioria das minhas comunicações com amigos e colegas ocorre através do e-mail, eu me acostumei a armazenar informações de contato nos aplicativos de catálogo de endereços integrados ao Mozilla Thunderbird, o meu cliente de e-mail padrão. No entanto, nos últimos meses, eu migrei gradualmente as informações para o Gmail, que oferece um catálogo de endereços próprio e poderoso. Este recurso, conhecido como Google Contacts, pode ser facilmente acessado pela Web, suporta um grande número de campos de informações e tem recursos para importação e exportação. Isso possibilita não apenas armazenar dados abrangentes sobre os contatos, mas também fazer com que essas informações de contato "viajem" com você para todos os lugares, pois podem ser acessadas a partir de qualquer computador com acesso à Web.

Acrônimos usados frequentemente

  • API: Application Program Interface
  • DOM: Document Object Model
  • HTTP: Hypertext Transfer Protocol
  • REST: Representational State Transfer
  • URL: Uniform Resource Locator
  • XML: Extensible Markup Language

O Google Contacts também é interessante sob o ponto de vista de desenvolvimento: como vários outros produtos do Google, expõe uma API de Dados que permite que desenvolvedores construam novos aplicativos facilmente usando os dados armazenados em um catálogo de endereços privado. Essa API, que segue o modelo REST, pode ser acessada através de qualquer kit de ferramentas que suporte XML, e já tem bibliotecas cliente para várias linguagens de programação comuns... incluindo a minha favorita, PHP.

Este artigo apresentará a API de Dados do Google Contacts, e mostrará como integrar e usar dados de contato com aplicativos PHP customizados. Nos exemplos, mostraremos como recuperar contatos do catálogo de endereços de um usuário, como adicionar, modificar e excluir contatos e como controlar os dados retornados em um feed de contatos. Então, vamos começar!


Entendendo a API do Google Contacts

Antes de mergulhar no código PHP, são necessárias algumas palavras sobre a API de Dados do Google Contacts. Da mesma forma que em outras APIs de Dados do Google, o sistema aceita pedidos de HTTP que contém um ou mais argumentos de entrada codificados em XML e retornam feeds Atom que contêm as informações solicitadas. Esses feeds podem então ser analisados em qualquer linguagem de programação com suporte a XML. Adicionalmente, as operações HTTP padrão GET, POST, PUT e DELETE são mapeadas para métodos da API que recuperam, adicionam, atualizam e excluem registros, respectivamente.

Um feed típico do Google Contacts contém muitas informações. Considere o exemplo na Listagem 1:


Listagem 1: Exemplo de feed do Google Contacts

<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:author>
    <atom:name>John Doe</atom:name>
    <atom:email>user@gmail.com</atom:email>
  </atom:author>
  <atom:category term="http://schemas.google.com/contact/2008#contact" 
   scheme="http://schemas.google.com/g/2005#kind"/>
  <atom:id>user@gmail.com</atom:id>
  <atom:link href="http://www.google.com/" rel="alternate" type="text/html"/>
  <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full" 
   rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml"/>
  <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full" 
   rel="http://schemas.google.com/g/2005#post" type="application/atom+xml"/>
  <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full/
   batch" rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml"/>
  <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full?
   max-results=25" rel="self" type="application/atom+xml"/>
  <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full?
   start-index=26&max-results=25" rel="next" type="application/atom+xml"/>
  <atom:title type="text">John Doe's Contacts</atom:title>
  <atom:updated>2009-08-31T10:48:00.410Z</atom:updated>
  <atom:generator uri="http://www.google.com/m8/feeds" version="1.0">Contacts
  </atom:generator>
  <atom:entry xmlns:default="http://www.w3.org/2007/app" 
   xmlns:default1="http://schemas.google.com/g/2005" 
   xmlns:default2="http://schemas.google.com/contact/2008">
    <default:edited xmlns="http://www.w3.org/2007/app">2009-08-22T16:52:37.457Z
    </default:edited>
    <default1:name xmlns="http://schemas.google.com/g/2005">
      <default1:fullName>Vikram Vaswani</default1:fullName>
      <default1:givenName>Vikram</default1:givenName>
      <default1:familyName>Vaswani</default1:familyName>
    </default1:name>
    <default1:organization xmlns="http://schemas.google.com/g/2005" 
     rel="http://schemas.google.com/g/2005#work">
      <default1:orgName>Melonfire</default1:orgName>
      <default1:orgTitle>CEO</default1:orgTitle>
    </default1:organization>
    <default1:email xmlns="http://schemas.google.com/g/2005" 
     rel="http://schemas.google.com/g/2005#other" address="vikram@example.org" 
     primary="true"/>
    <default1:email xmlns="http://schemas.google.com/g/2005" 
     rel="http://schemas.google.com/g/2005#home" address="vikram@example.com"/>
    <default1:phoneNumber xmlns="http://schemas.google.com/g/2005" 
     rel="http://schemas.google.com/g/2005#mobile">0012345678901
     </default1:phoneNumber>
    <default1:phoneNumber xmlns="http://schemas.google.com/g/2005" 
     rel="http://schemas.google.com/g/2005#work_fax">0045678901234
     </default1:phoneNumber>
    <default2:website xmlns="http://schemas.google.com/contact/2008" 
     href="http://www.melonfire.com/" rel="home"/>
    <default2:website xmlns="http://schemas.google.com/contact/2008" 
     href="http://www.php-beginners-guide.com/" rel="blog"/>
    <default2:groupMembershipInfo xmlns="http://schemas.google.com/contact/2008" 
     deleted="false" 
     href="http://www.google.com/m8/feeds/groups/user%40gmail.com/base/6"/>
    <atom:category term="http://schemas.google.com/contact/2008#contact" 
     scheme="http://schemas.google.com/g/2005#kind"/>
    <atom:id>http://www.google.com/m8/feeds/contacts/user%40gmail.com/base/0
    </atom:id>
    <atom:link href="http://www.google.com/m8/feeds/photos/media/user%40gmail.com/0" 
     rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*"/>
    <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full/0" 
     rel="self" type="application/atom+xml"/>
    <atom:link href="http://www.google.com/m8/feeds/contacts/user%40gmail.com/full/0" 
     rel="edit" type="application/atom+xml"/>
    <atom:title type="text">Vikram Vaswani</atom:title>
    <atom:updated>2009-08-22T16:52:37.457Z</atom:updated>
    <atom:content type="text">PHP enthusiast</atom:content>
  </atom:entry>
  <atom:entry xmlns:default="http://www.w3.org/2007/app" 
   xmlns:default1="http://schemas.google.com/g/2005">
  </atom:entry>
  <openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  >153</openSearch:totalResults>
  <openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  >1</openSearch:startIndex>
  <openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  >25</openSearch:itemsPerPage>
</atom:feed>

Cada feed de contatos abre com um elemento <feed> como o elemento-raiz. O elemento <feed> contém elementos <link>, que contém URLs para diferentes versões do feed, e elementos <openSearch:> , que contém estatísticas resumidas.

O elemento <feed> mais externo abrange um ou mais elementos <entry>, cada um representando um único contato. Cada <entry> contém mais detalhes do contato, incluindo o nome, organização, título, endereços de e-mail, números de telefone e fax, Web sites e fotografia, entre outros. Cada <entry> contém também dois elementos <link> adicionais, <link rel="self" ...> e <link rel="edit" ...>, que têm os URLs para recuperação da entrada completa e para editar a entrada, respectivamente.


Recuperando contatos

É importante notar que os feeds do Google Contacts são privados. Isso significa que qualquer operação com os dados contidos no feed — inclusive a simples visualização — somente será bem sucedida se a operação for autenticada com o nome do usuário e senha do proprietário do feed usando um dos dois métodos de autenticação aprovados pelo Google: AuthSub ou ClientLogin.

Executar este tipo de autenticação manualmente é uma tarefa bastante complicada, e requer uma boa quantidade de código para tratar os vários cenários que podem aparecer durante uma transação típica de autenticação. Felizmente, não é necessário preocupar-se muito com isso. A Biblioteca Cliente GData do Zend®, projetada especificamente para desenvolvedores que integram aplicativos PHP com a API de Dados do Google, trata todos os detalhes necessários. Esta biblioteca, que pode ser transferida via download separadamente (ver Recursos para obter o link), oferece uma interface conveniente e orientada a objetos para a API de Dados do Google, encapsula as tarefas mais comuns (incluindo autenticação) e permite concentrar os esforços nas funções do núcleo de seus aplicativos. Os exemplos restantes deste artigo usarão essa biblioteca, portanto, verifique se ela está instalada antes de prosseguir.

Depois de instalar a biblioteca GData do Zend, podemos prosseguir para um exemplo de como processar um feed da API de Dados do Google Contacts usando PHP. A Listagem 2 pega um feed da Listagem 1 e usa SimpleXML para extrair fragmentos relevantes de dados desse feed e formatá-los em uma página da Web:


Listagem 2: Recuperando e exibindo contatos
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing contacts</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }
    div.entry {
      display: inline;
      float: left;
      width: 400px;
      height: 150px;
      border: 2px solid; 
      margin: 10px;
      padding: 5px;
    }
    td {
      vertical-align: top;
    }
    </style>    
  </head>
  <body>
     
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Http_Client');
    Zend_Loader::loadClass('Zend_Gdata_Query');
    Zend_Loader::loadClass('Zend_Gdata_Feed');
    
    // set credentials for ClientLogin authentication
    $user = "user@gmail.com";
    $pass = "guessme";
    
    try {
      // perform login and set protocol version to 3.0
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // perform query and get result feed
      $query = new Zend_Gdata_Query(
        'http://www.google.com/m8/feeds/contacts/default/full');
      $feed = $gdata->getFeed($query);
      
      // display title and result count
      ?>
      
      <h2><?php echo $feed->title; ?></h2>
      <div>
      <?php echo $feed->totalResults; ?> contact(s) found.
      </div>
      
      <?php
      // parse feed and extract contact information
      // into simpler objects
      $results = array();
      foreach($feed as $entry){
        $xml = simplexml_load_string($entry->getXML());
        $obj = new stdClass;
        $obj->name = (string) $entry->title;
        $obj->orgName = (string) $xml->organization->orgName; 
        $obj->orgTitle = (string) $xml->organization->orgTitle; 
      
        foreach ($xml->email as $e) {
          $obj->emailAddress[] = (string) $e['address'];
        }
        
        foreach ($xml->phoneNumber as $p) {
          $obj->phoneNumber[] = (string) $p;
        }
        foreach ($xml->website as $w) {
          $obj->website[] = (string) $w['href'];
        }
        
        $results[] = $obj;  
      }
    } catch (Exception $e) {
      die('ERROR:' . $e->getMessage());  
    }
    ?>
    
    <?php
    // display results
    foreach ($results as $r) {
    ?>
    <div class="entry">
      <div class="name"><?php echo (!empty($r->name)) ? 
       $r->name : 'Name not available'; ?></div>
      <div class="data">
        <table>
          <tr>
            <td>Organization</td>
            <td><?php echo $r->orgName; ?></td>
          </tr>
          <tr>
            <td>Email</td>
            <td><?php echo @join(', ', $r->emailAddress); ?></td>
          </tr>
          <tr>
            <td>Phone</td>
            <td><?php echo @join(', ', $r->phoneNumber); ?></td>
          </tr>
          <tr>
            <td>Web</td>
            <td><?php echo @join(', ', $r->website); ?></td>
          </tr>
        </table>
      </div>
    </div>
    <?php
    }
    ?>

  </body>
</html>

A

Figura 1 demonstra a saída que poderá ser vista. Algumas informações de endereços de e-mail pessoais foram mascaradas na captura de tela.


Figura 1. Uma página da Web que lista contatos
Screen capture of a Web page that lists contacts

Primeiro, a Listagem 2 carrega as bibliotecas de classes do Zend, e inicializa uma instância da classe de serviço Zend_Gdata. Essa classe usa um objeto Zend_Http_Client, que é fornecido com todas as informações necessárias de autenticação de usuários e usada para abrir uma conexão autenticada com o serviço do Google Contacts. Após a abertura da conexão autenticada, o método getFeed() recupera o feed de contatos. Esse método aceita um objeto Zend_Gdata_Query, ao qual é passado o URL do feed. Note também a chamada para setMajorProtocolVersion() na Listagem 2, que instrui o servidor para usar a v3.0 da API de Dados do Google Contacts; esta chamada é obrigatória. Se omitida, pode ocorrer um comportamento não esperado.

A resposta para a chamada de API getFeed() é um feed SML semelhante ao da Listagem 1, que é então analisado e convertido em um objeto PHP. As entradas em um feed são representadas como elementos de array, possibilitando interagir com o feed e recuperar as entradas de contato individuais. Como o SimpleXML oferece uma maneira mais fácil de recuperar fragmentos de informações de uma árvore XML, o método simplexml_load_string() é usado para converter o XML de cada entrada em um objeto SimpleXML. Os nós-filho sob cada <entry> são então recuperados e achatados em um objeto mais simples para facilitar a recuperação, e cada objeto resultante é colocado no array $results. Após o processamento de todo o feed, é possível interagir com o array $results com um loop foreach() e formatar o conteúdo para exibição em um navegador da Web.

Algumas palavras sobre o URL do feed passado ao objeto Zend_Gdata_Query: esse URL é gerado acrescentando-se o nome do usuário e o tipo de feed ao URL padrão do feed, da seguinte forma: http://www.google.com/m8/feeds/contacts/USERID/TYPE. Existem dois tipos de feed, full e thin; o thin retorna somente um subconjunto da entrada completa. Se a palavra-chave especial default for usada no lugar do nome do usuário, como na Listagem 2, será retornado o feed padrão do usuário.


Adicionando contatos

O que vimos até agora trata a listagem de contatos. Agora, que tal adicionar novos contatos?

Na verdade, isso não é tão complicado como pode parecer. Para adicionar um novo contato, basta executar um POST para um novo bloco de <entry> codificado em XML para o URL do feed. A Listagem 3 tem um exemplo de um desses blocos:


Listagem 3: Exemplo de entrada do Google Contacts

<?xml version="1.0"?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" 
 xmlns:gd="http://schemas.google.com/g/2005">
  <gd:name>
    <gd:fullName>Jack Frost</gd:fullName>
  </gd:name>
  <gd:email address="jack.frost@example.com" 
   rel="http://schemas.google.com/g/2005#home"/>
  <gd:organization rel="http://schemas.google.com/g/2005#work">
    <gd:orgName>Winter Inc.</gd:orgName>
  </gd:organization>
</atom:entry>

Se a biblioteca do Zend for usada, é ainda mais simples: basta chamar o método insertEntry(), que cria um pedido de POST e transmite os dados para o URL do feed. A Listagem 4 oferece um exemplo:


Listagem 4: Adicionando um novo contato

<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Http_Client');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "user@gmail.com";
$pass = "guessme";

try {
  // perform login and set protocol version to 3.0
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // create new entry
  $doc  = new DOMDocument();
  $doc->formatOutput = true;
  $entry = $doc->createElement('atom:entry');
  $entry->setAttributeNS('http://www.w3.org/2000/xmlns/' ,
   'xmlns:atom', 'http://www.w3.org/2005/Atom');
  $entry->setAttributeNS('http://www.w3.org/2000/xmlns/' ,
   'xmlns:gd', 'http://schemas.google.com/g/2005');
  $doc->appendChild($entry);
  
  // add name element
  $name = $doc->createElement('gd:name');
  $entry->appendChild($name);
  $fullName = $doc->createElement('gd:fullName', 'Jack Frost');
  $name->appendChild($fullName);
  
  // add email element
  $email = $doc->createElement('gd:email');
  $email->setAttribute('address' ,'jack.frost@example.com');
  $email->setAttribute('rel' ,'http://schemas.google.com/g/2005#home');
  $entry->appendChild($email);
  
  // add org name element
  $org = $doc->createElement('gd:organization');
  $org->setAttribute('rel' ,'http://schemas.google.com/g/2005#work');
  $entry->appendChild($org);
  $orgName = $doc->createElement('gd:orgName', 'Winter Inc.');
  $org->appendChild($orgName);
  
  // insert entry
  $entryResult = $gdata->insertEntry($doc->saveXML(), 
   'http://www.google.com/m8/feeds/contacts/default/full');
  echo '<h2>Add Contact</h2>';
  echo 'The ID of the new entry is: ' . $entryResult->id;
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());
}
?>

A Listagem 4 abre uma conexão autenticada para a API de Dados do Google Contacts usando o objeto Zend_Gdata, como visto anteriormente na Listagem 2. Em seguida, a extensão DOM no PHP constrói dinamicamente a <entry> XML mostrada na Listagem 3, e o método insertEntry() é usado para realmente salvar o XML resultante nos servidores do Google. Assim que a entrada é adicionada, deve se tornar imediatamente visível na interface do Google Contacts.

Note que é possível marcar explicitamente endereços de e-mail e números de telefone como pertencendo a "casa", "trabalho" ou "remoto" especificando o esquema apropriado no <gd:organization rel="..." /> elemento.

A Figura 2 mostra a saída depois da adição bem sucedida de uma nova entrada de contato


Figura 2. A saída após a adição de um novo contato
Screen capture of the output after you add a new contact

Alguns campos da mensagem de confirmação do Google estão mascarados na captura de tela da Figura 2. A mensagem é no formato: O ID da nova entrada é http://www.google.com/m8/feeds/contacts/USER_ID/base/CONTACT_ID.

E a Figura 3 mostra como ela é exibida na interface do Google Contacts:


Figura 3. O contato recém-adicionado no Gmail
Screen capture of the newly-added contact, Jack Frost, in Gmail

Excluindo e atualizando contatos

A API de Dados do Google Contacts também permite a edição e exclusão de entradas. Para excluir uma entrada, envie um pedido de DELETE para o URL de edição do contato, que é o URL especificado no elemento <link rel="edit" ...> da entrada. No contexto da biblioteca do Zend, é possível simplesmente passar esse URL para o método delete() do objeto Zend_Gdata, conforme mostrado na Listagem 5:


Listagem 5: Excluindo um contato

<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Http_Client');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "user@gmail.com";
$pass = "guessme";

// set ID of entry to delete
// from <link rel=edit>
$id = 'http://www.google.com/m8/feeds/contacts/default/base/29e98jf648c495c7b';

try {
  // perform login and set protocol version to 3.0
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $client->setHeaders('If-Match: *');
  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // delete entry
  $gdata->delete($id);
  echo '<h2>Delete Contact</h2>';
  echo 'Entry deleted';
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());
}
?>

Para editar uma entrada, use o método getEntry() para recuperar a entrada usando o seu identificador único e altere os valores que deseja atualizar. Em seguida, salve a entrada no servidor com o método updateEntry() do objeto Zend_Gdata, que envia um pedido de PUT para o URL especificado no elemento <link rel="self" ...> da entrada. A Listagem 6 mostra o processo, definindo um novo nome e endereço de e-mail para uma entrada de contato:


Listagem 6: Modificando um contato

<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Http_Client');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "user@gmail.com";
$pass = "guessme";

// set ID of entry to update
// from <link rel=self>
$id = 'http://www.google.com/m8/feeds/contacts/default/full/0';

try {
  // perform login and set protocol version to 3.0
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $client->setHeaders('If-Match: *');

  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // perform query and get entry
  $query = new Zend_Gdata_Query($id);
  $entry = $gdata->getEntry($query);
  $xml = simplexml_load_string($entry->getXML());

  // change name
  $xml->name->fullName = 'John Rabbit';
  
  // change primary email address  
  foreach ($xml->email as $email) {
    if (isset($email['primary'])) {
      $email['address'] = 'jr@example.com';  
    }  
  }
  
  // update entry
  $entryResult = $gdata->updateEntry($xml->saveXML(), 
   $entry->getEditLink()->href);
  echo 'Entry updated';
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());
}
?>

Note que a Listagem 5 e a Listagem 6 adicionam um cabeçalho "If-Match" adicional como parte do pedido de HTTP. Este cabeçalho é particularmente útil em um ambiente multicliente, pois pode ser usado para excluir ou atualizar uma entrada somente se essa entrada não foi alterada desde a última leitura. O Guia dos Desenvolvedores da API de Dados do Google Contacts (veja Recursos para obter um link) discute esse cabeçalho em mais detalhes.


Usando parâmetros adicionais

A API de Dados do Google Contacts também suporta vários parâmetros adicionais que podem ser usados para controlar o feed de resultados. Aqui está uma lista:

  • O parâmetro start-index especifica o deslocamento do início do feed
  • O parâmetro max-results especifica o número de entradas no feed
  • Os parâmetros orderby e sortorder especificam como classificar as entradas do feed
  • O parâmetro showdeleted inclui as entradas excluídas do feed nos últimos 30 dias

Se a biblioteca cliente do Zend estiver sendo usada, é possível definir vários desses parâmetros simplesmente configurando as propriedades correspondentes no objeto Zend_Gdata_Query. Para os parâmetros que são específicos para o serviço, o objeto Zend_Gdata_Query oferece também um método setParam(). As duas técnicas estão ilustradas na Listagem 7, que restringe o resultado para 10 entradas, classificadas em ordem descendente pela sua data de última modificação.


Listagem 7: Definindo parâmetros de consulta adicionais
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Http_Client');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "user@gmail.com";
$pass = "guessme";

try {
  // perform login and set protocol version to 3.0
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // perform query and get result feed
  $query = new Zend_Gdata_Query(
    'http://www.google.com/m8/feeds/contacts/default/full');
  $query->maxResults = 10;
  $query->setParam('orderby', 'lastmodified');
  $query->setParam('sortorder', 'descending');
  $feed = $gdata->getFeed($query);

  // display title and result count
  // snip...
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>


Um aplicativo simples

Agora que você sabe como a API de Dados do Google Contacts funciona, é possível tentar construir um aplicativo PHP simples que possibilita a entrada e manipulação de contatos. Esse aplicativo protótipo tem 3 scripts (veja Download para obter um arquivo compactado):

  • contacts-index.php lista as entradas de contatos e oferece links para adicionar e excluir entradas.
  • contacts-save.php exibe um formulário para adicionar uma nova entrada, e processa o envio.
  • contacts-delete.php exclui uma entrada especificada.

Comece com o primeiro script e atualize a Listagem 1 com alguns links adicionais, como na Listagem 8:


Listagem 8: Recuperando e exibindo contatos

<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing contacts</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }
    div.entry {
      display: inline;
      float: left;
      width: 450px;
      height: 150px;
      border: 2px solid; 
      margin: 10px;
      padding: 5px;
    }
    td {
      vertical-align: top;
    }
    span.links {
      float: right;  
    }
    </style>    
  </head>
  <body>
    <h2>Contacts</h2>
    
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Http_Client');
    Zend_Loader::loadClass('Zend_Gdata_Query');
    Zend_Loader::loadClass('Zend_Gdata_Feed');
    
    // set credentials for ClientLogin authentication
    $user = "user@gmail.com";
    $pass = "guessme";
    
    try {
      // perform login and set protocol version to 3.0
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // perform query and get feed of all results
      $query = new Zend_Gdata_Query(
        'http://www.google.com/m8/feeds/contacts/default/full');
      $query->maxResults = 0;
      $query->setParam('orderby', 'lastmodified');
      $query->setParam('sortorder', 'descending');
      $feed = $gdata->getFeed($query);
      
      // display number of results
      ?>
      
      <h2><?php echo $feed->title; ?></h2>
      <div>
      <?php echo $feed->totalResults; ?> contact(s) found.
      </div>
            
      <?php
      // parse feed and extract contact information
      // into simpler objects
      $results = array();
      foreach($feed as $entry){
        $obj = new stdClass;
        $obj->edit = $entry->getEditLink()->href;
        $xml = simplexml_load_string($entry->getXML());
        $obj->name = (string) $entry->title;
        $obj->orgName = (string) $xml->organization->orgName; 
        $obj->orgTitle = (string) $xml->organization->orgTitle; 
      
        foreach ($xml->email as $e) {
          $obj->emailAddress[] = (string) $e['address'];
        }
        
        foreach ($xml->phoneNumber as $p) {
          $obj->phoneNumber[] = (string) $p;
        }
        foreach ($xml->website as $w) {
          $obj->website[] = (string) $w['href'];
        }
        
        $results[] = $obj;  
      }
    } catch (Exception $e) {
      die('ERROR:' . $e->getMessage());  
    }
    ?>
    
    <div>
    <a href="contacts-save.php">Add a new contact</a>
    </div>    
    
    <?php    
    // display results
    foreach ($results as $r) {
    ?>
    <div class="entry">
      <div class="name"><?php echo (!empty($r->name)) 
       ? $r->name : 'Name not available'; ?> 
        <span class="links"><a href="contacts-delete.php?
         id=<?php echo $r->edit; ?>">Delete</a></span>
      </div>
      <div class="data">
        <table>
          <tr>
            <td>Organization:</td>
            <td><?php echo $r->orgName; ?></td>
          </tr>
          <tr>
            <td>Email:</td>
            <td><?php echo @join(', ', $r->emailAddress); ?></td>
          </tr>
          <tr>
            <td>Phone:</td>
            <td><?php echo @join(', ', $r->phoneNumber); ?></td>
          </tr>
          <tr>
            <td>Web:</td>
            <td><?php echo @join(', ', $r->website); ?></td>
          </tr>
        </table>
      </div>
    </div>
    <?php
    }
    ?>

  </body>
</html><!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing contacts</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }
    div.entry {
      display: inline;
      float: left;
      width: 450px;
      height: 150px;
      border: 2px solid; 
      margin: 10px;
      padding: 5px;
    }
    td {
      vertical-align: top;
    }
    span.links {
      float: right;  
    }
    </style>    
  </head>
  <body>
    <h2>Contacts</h2>
    
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Http_Client');
    Zend_Loader::loadClass('Zend_Gdata_Query');
    Zend_Loader::loadClass('Zend_Gdata_Feed');
    
    // set credentials for ClientLogin authentication
    $user = "user@gmail.com";
    $pass = "guessme";
    
    try {
      // perform login and set protocol version to 3.0
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // perform query and get feed of all results
      $query = new Zend_Gdata_Query(
        'http://www.google.com/m8/feeds/contacts/default/full');
      $query->maxResults = 0;
      $query->setParam('orderby', 'lastmodified');
      $query->setParam('sortorder', 'descending');
      $feed = $gdata->getFeed($query);
      
      // display number of results
      ?>
      
      <h2><?php echo $feed->title; ?></h2>
      <div>
      <?php echo $feed->totalResults; ?> contact(s) found.
      </div>
            
      <?php
      // parse feed and extract contact information
      // into simpler objects
      $results = array();
      foreach($feed as $entry){
        $obj = new stdClass;
        $obj->edit = $entry->getEditLink()->href;
        $xml = simplexml_load_string($entry->getXML());
        $obj->name = (string) $entry->title;
        $obj->orgName = (string) $xml->organization->orgName; 
        $obj->orgTitle = (string) $xml->organization->orgTitle; 
      
        foreach ($xml->email as $e) {
          $obj->emailAddress[] = (string) $e['address'];
        }
        
        foreach ($xml->phoneNumber as $p) {
          $obj->phoneNumber[] = (string) $p;
        }
        foreach ($xml->website as $w) {
          $obj->website[] = (string) $w['href'];
        }
        
        $results[] = $obj;  
      }
    } catch (Exception $e) {
      die('ERROR:' . $e->getMessage());  
    }
    ?>
    
    <div>
    <a href="contacts-save.php">Add a new contact</a>
    </div>    
    
    <?php    
    // display results
    foreach ($results as $r) {
    ?>
    <div class="entry">
      <div class="name"><?php echo (!empty($r->name)) 
       ? $r->name : 'Name not available'; ?> 
        <span class="links"><a href="contacts-delete.php?
         id=<?php echo $r->edit; ?>">Delete</a></span>
      </div>
      <div class="data">
        <table>
          <tr>
            <td>Organization:</td>
            <td><?php echo $r->orgName; ?></td>
          </tr>
          <tr>
            <td>Email:</td>
            <td><?php echo @join(', ', $r->emailAddress); ?></td>
          </tr>
          <tr>
            <td>Phone:</td>
            <td><?php echo @join(', ', $r->phoneNumber); ?></td>
          </tr>
          <tr>
            <td>Web:</td>
            <td><?php echo @join(', ', $r->website); ?></td>
          </tr>
        </table>
      </div>
    </div>
    <?php
    }
    ?>

  </body>
</html>

A Figura 4 ilustra a saída revisada.


Figura 4. Uma página da Web que lista contatos, com funções de adição e exclusão
Screen capture of a Web page that lists contacts, with add and delete functions

É possível ver na Figura 4 que há agora um link adicional Delete ao lado de cada entrada. Esse link inclui o ID da entrada, que é passado para o destino do link como um parâmetro GET. O script de destino lê esse ID e o exclui, usando a técnica descrita na Listagem 5. A Listagem 9 mostra a aparência do código:


Listagem 9: Excluindo contatos
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Deleting contacts</title>
  </head>
  <body>
    <h2>Delete Contact</h2>    

    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Http_Client');
    Zend_Loader::loadClass('Zend_Gdata_Query');
    Zend_Loader::loadClass('Zend_Gdata_Feed');
    
    // set credentials for ClientLogin authentication
    $user = "user@gmail.com";
    $pass = "guessme";
    
    if (empty($_GET['id'])) {
      die('ERROR: Missing ID');
    } 

    try {
      // perform login and set protocol version to 3.0
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      // set GData delete headers
      $client->setHeaders('If-Match: *');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // delete entry
      $gdata->delete($_GET['id']);
      echo 'Entry deleted';
    } catch (Exception $e) {
      die('ERROR:' . $e->getMessage());
    }
    ?>
  </body>
</html>  

Isso resolve a listagem e remoção de entradas. Mas, como adicioná-las? A Listagem 10 introduz outro script, que permite que os usuários adicionem novos contatos através de um formulário da Web. A biblioteca do Zend é usada para construir o pacote de POST correspondente e salvar os dados no servidor:


Listagem 10: Adicionando novos contatos

<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Adding new contacts</title>
    <style>
    body {
      font-family: Verdana;      
    }
    </style>
  </head>
  <body>
    <h2>Add Contact</h2>    
    
    <?php if (!isset($_POST['submit'])) { ?>    
    <form method="post" 
     action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Name: <br/>
      <input name="name" type="text" size="15" /><p/>
      Email address(es): <br/>
      <textarea name="email" type="text"></textarea><p/>
      Organization: <br/>
      <input name="org" type="text" size="15" /><p/>
      <input name="submit" type="submit" value="Save" />      
    </form>    
    
    <?php 
    } else { 

      // check for required input      
      if (empty($_POST['name'])) {
        die('ERROR: Missing name');
      } 
      
      if (empty($_POST['email'])) {
        die('ERROR: Missing email address');
      } 
      
      if (empty($_POST['org'])) {
        die('ERROR: Missing organization');
      } 
      
      // sanitize input and save to array
      $inputData['name'] = htmlentities($_POST['name']);
      $inputData['email'] = htmlentities($_POST['email']);
      $inputData['org'] = htmlentities($_POST['org']);
      
      // load Zend Gdata libraries
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Gdata');
      Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
      Zend_Loader::loadClass('Zend_Http_Client');
      Zend_Loader::loadClass('Zend_Gdata_Query');
      Zend_Loader::loadClass('Zend_Gdata_Feed');
      
      // set credentials for ClientLogin authentication
      $user = "user@gmail.com";
      $pass = "guessme";
      
      try {
        // perform login and set protocol version to 3.0
        $client = Zend_Gdata_ClientLogin::getHttpClient(
          $user, $pass, 'cp');
        $gdata = new Zend_Gdata($client);
        $gdata->setMajorProtocolVersion(3);
        
        // create new entry
        $doc  = new DOMDocument();
        $doc->formatOutput = true;
        $entry = $doc->createElement('atom:entry');
        $entry->setAttributeNS('http://www.w3.org/2000/xmlns/' ,
         'xmlns:atom', 'http://www.w3.org/2005/Atom');
        $entry->setAttributeNS('http://www.w3.org/2000/xmlns/' ,
         'xmlns:gd', 'http://schemas.google.com/g/2005');
        $doc->appendChild($entry);
        
        // add name element
        $name = $doc->createElement('gd:name');
        $entry->appendChild($name);
        $fullName = $doc->createElement('gd:fullName', $inputData['name']);
        $name->appendChild($fullName);
        
        // add email elements
        $arr = explode(',', $inputData['email']);
        foreach ($arr as $a) {
          $email = $doc->createElement('gd:email'); 
          $email->setAttribute('address', $a);
          $email->setAttribute('rel' ,'http://schemas.google.com/g/2005#work');
          $entry->appendChild($email);          
        }
        
        // add org name element
        $org = $doc->createElement('gd:organization');
        $org->setAttribute('rel' ,'http://schemas.google.com/g/2005#work');
        $entry->appendChild($org);
        $orgName = $doc->createElement('gd:orgName', $inputData['org']);
        $org->appendChild($orgName);
        
        // insert entry
        $entryResult = $gdata->insertEntry($doc->saveXML(), 
         'http://www.google.com/m8/feeds/contacts/default/full');
        echo 'The ID of the new entry is: ' . $entryResult->id;
      } catch (Exception $e) {
        die('ERROR:' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

A Listagem 10 contém na realidade duas partes: um formulário da Web, e o código PHP que processa a entrada enviada através do formulário. A Figura 5 ilustra a aparência desse formulário.


Figura 5. Um formulário da Web para adicionar um novo contato
Screen capture of a Web page with form fields to add a new contact

Depois que o usuário inserir o nome, endereço de e-mail e organização de um usuário nesse formulário e enviá-lo, a segunda parte do script entra em ação. Primeiro, um cliente HTTP é inicializado e usado para abrir uma conexão autenticada com a API de Dados do Google Contacts. Em seguida, as entradas inseridas no formulário da Web são validadas, e um novo objeto DOMDocument é inicializado para manter os dados da nova entrada.

Os métodos do DOM no PHP constroem dinamicamente uma nova <entry>, e o método insertEntry() na realidade salva a entrada nos servidores do Google. Após a adição da entrada, a API retornará seu ID exclusivo, que é exibido para o usuário para indicar que a operação teve êxito.

A Figura 6 mostra a saída depois da adição bem sucedida de uma nova entrada.


Figura 6. A saída depois da adição de um novo contato
Screen capture of the output after you add a new contact

Alguns campos da mensagem de confirmação do Google estão mascarados na captura de tela da Figura 6. A mensagem é no formato: O ID da nova entrada é http://www.google.com/m8/feeds/contacts/USER_ID/base/CONTACT_ID.


Conclusão

Neste artigo, oferecemos um curso rápido sobre como integrar dados da API de Dados do Google Contacts com aplicativos PHP usando uma combinação de SimpleXML e a biblioteca cliente do Zend. Os exemplos neste artigo introduziram o formato do feed do Google Contacts, mostraram como recuperar listagens de contatos, adicionar, modificar e excluir contatos, e construir uma interface customizada com os dados de informações de contatos armazenados na Conta Google de um usuário.

Como mostram esses exemplos, a API de Dados do Google Contacts é uma ferramenta poderosa e flexível para desenvolvedores que procuram construir novos aplicativos criativos para gerenciamento de contatos. Experimente em qualquer momento, e veja o que pensa!



Download

DescriçãoNomeTamanhoMétodo de download
Archive of the final code examplecontacts-example-app.zip4KBHTTP

Informações sobre métodos de download


Recursos

Aprender

Obter produtos e tecnologias

Discutir

Sobre o autor

Photo of Vikram Vaswani

Vikram Vaswani é o fundador e Presidente da Melonfire (este link reside fora de ibm.com), uma empresa de serviços de consultoria com conhecimento especial sobre ferramentas e tecnologias de software livre. Ele também é o autor dos livros PHP Programming Solutions (este link reside fora de ibm.com) e PHP: A Beginners Guide (este link reside fora de ibm.com).

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

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.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=439723
ArticleTitle=Integre seus aplicativos PHP com o Google Contacts
publish-date=10262009
author1-email=vikram.melonfire@gmail.com
author1-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).