Интеграция PHP-приложений с сервисом Google Contacts

Чтение и редактирование контактных данных, предоставляемых сервисом Google Contacts, при помощи XML в приложениях на PHP

Сервис Google Contacts предоставляет мощный API для доступа и редактирования контактных данных Gmail, пригодный для использования любыми клиентскими приложениями. Прочитав эту статью, вы узнаете о получении, добавлении, редактировании и удалении контактов при помощи этого интерфейса на примере приложения, написанного на PHP. 

Введение

Немалая часть моего общения с друзьями и коллегами по работе сводится к переписке по электронной почте, поэтому я привык хранить их контактные данные в адресной книге Mozilla Thunderbird - моей любимой почтовой программы. Однако в последние несколько месяцев я постепенно начал переносить контакты в Gmail, который также включает удобную адресную книгу. Этот сервис, известный под именем Google Contacts, открыт для доступа через Web, поддерживает множество информационных полей для описания контактов, а также предоставляет возможности для импорта и экспорта данных. Таким образом, он не просто позволяет сохранить всевозможную контактную информацию, но и делает ее доступной для вас в любой точке планеты, где есть компьютер и Интернет. 

Часто встречающиеся аббревиатуры

  • API: программный интерфейс приложений.
  • DOM: объектная модель документа.
  • HTTP: протокол передачи гипертекста.
  • REST: передача репрезентативного состояния.
  • URL: универсальный локатор ресурсов.
  • XML: расширяемый язык разметки.

Сервис Google Contacts также представляет немалый интерес для разработчиков, поскольку он, как и многие сервисы Google, предоставляет API для доступа к данным, который позволяет легко создавать приложения, оперирующие информацией, хранящейся в личных адресных книгах. Этот API, созданный по принципам REST, может использоваться приложениями, написанными на любом языке, предоставляющем средства для работы с XML. Более того, на сегодняшний день уже существуют клиентские библиотеки для множества популярных языков программирования, в том числе, для моего любимого PHP.

Прочитав эту статью, вы познакомитесь с API для доступа к данным Google Contacts и увидите примеры использования контактной информации в приложении на PHP. Приведенные в статье примеры демонстрируют такие возможности, как получение списка контактов из адресной книги пользователя, добавление, удаление и редактирование контактов, а также манипулирование контактными данными, возвращаемыми в виде информационной ленты. Итак, приступим!


Интерфейс для доступа к данным Google Contacts

Перед тем как перейти непосредственно к написанию кода на PHP, необходимо сказать несколько слов об API для доступа к данным Google Contacts. Аналогично API других сервисов Google, этот интерфейс базируется на HTTP-запросах, содержащих набор представленных в XML аргументов, в ответ на которые сервер возвращает ленты Atom, включающие требуемую информацию. При этом методы API, служащие для чтения, добавления, редактирования и удаления контактов, соответствуют стандартным операциям HTTP (GET, POST, PUT и DELETE). Наконец, полученные от сервиса ленты могут обрабатываться произвольным образом в любом языке, предоставляющем средства для работы с XML.

Информационные ленты Google Contacts, как правило, содержат большой объем информации. Пример такой ленты приведен в листинге 1.

Листинг 1. Пример ленты, содержащей информацию, полученную от сервиса 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>

Каждая лента Google Contacts включает корневой элемент <feed>. Внутри него находятся элементы <link> и <openSearch:>, содержащие ссылки (URL) на разные версии ленты и сводную статистическую информацию соответственно.

В корневом элементе <feed> находятся один или несколько элементов <entry>, каждый из которых представляет собой контактную запись. Контактные данные включают имя, название организации, должность, адреса электронной почты и страницы в Интернете, телефон, факс, ссылку на фотографию и т. д. Кроме того, каждый элемент <entry> включает два тега <link> (<link rel="self" ...> и <link rel="edit" ...>), содержащие URL для получения полной версии записи и ее редактирования соответственно.


Чтение списка контактов

Необходимо помнить, что ленты Google Contacts содержат личную информацию, поэтому выполнение любых операций над ними, в том числе просмотра, требуют аутентификации при помощи имени пользователя и пароля. Аутентификация может производиться одним из двух одобренных Google методов: AuthSub и ClientLogin.

Выполнение аутентификации вручную представляет собой достаточно трудоемкую задачу, требующую немалого объема кода для обработки всевозможных сценариев, которые могут произойти во время транзакции. К счастью, этого можно избежать, воспользовавшись клиентской библиотекой Zend's® GData, которая была создана специально для разработчиков PHP-приложений, желающих использовать API для доступа к данным сервисов Google (ссылка для загрузки Zend's GData приведена в разделе Ресурсы). Данная библиотека предоставляет удобный объектно-ориентированный интерфейс для работы с API сервисов Google и высокоуровневые средства для выполнения наиболее часто встречающихся задач, в частности аутентификации, позволяя, тем самым, разработчикам сконцентрироваться на функциональности своих приложений. Zend's GData будет использоваться ниже, поэтому установите ее перед тем, как переходить к выполнению примеров.

После установки библиотеки Zend's GData можно переходить к рассмотрению примеров работы с лентами Google Contacts в PHP. Пример кода, приведенный в листинге 2, разбирает ленту из листинга 1 при помощи SimpleXML, выделяя из нее требующуюся информацию для последующего форматирования и вывода на Web-страницу.

Листинг 2. Пример получения списка контактов и их отображения на странице
<!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
    // Загрузка библиотеки Zend Gdata
    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');
    
    // Задание учетных параметров для аутентификации через ClientLogin
    $user = "user@gmail.com";
    $pass = "guessme";
    
    try {
      // Выполнение аутентификации и установка версии протокола (3.0)
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // Выполнение запроса и получение ленты
      $query = new Zend_Gdata_Query(
        'http://www.google.com/m8/feeds/contacts/default/full');
      $feed = $gdata->getFeed($query);
      
      // Вывод заголовка и числа полученных записей
      ?>
      
      <h2><?php echo $feed->title; ?></h2>
      <div>
      <?php echo $feed->totalResults; ?> contact(s) found.
      </div>
      
      <?php
      // Разбор ленты и извлечение контактных данных
      $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
    // Вывод результатов
    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>

Результат показан на рисунке 1 (адрес личной электронной почты был сознательно стерт).

Рисунок 1. Web-страница со списком контактов
Screen capture of a Web page that lists contacts

В листинге 2 сначала загружаются библиотеки классов Zend, а затем инициализируется экземпляр класса-сервиса Zend_Gdata. Данный класс использует объект Zend_Http_Client для установки аутентифицированного соединения с Google Contacts, передавая ему учетные данные пользователя. Сразу после открытия соединения выполняется вызов метода getFeed() для получения ленты, содержащей контактную информацию. Этот метод принимает в качестве аргумента объект Zend_Gdata_Query, в котором содержится URL ленты. Также следует обратить внимание на вызов метода setMajorProtocolVersion(), который указывает серверу, что следует использовать API 3.0 для доступа к Google Contacts. В данном случае этот вызов необходим, и его отсутствие может привести к неожиданным последствиям.

Метод getFeed() возвращает ленту в формате XML, аналогичную показанной в листинге 1, которая затем разбирается и представляется в виде объекта PHP. При этом записи ленты оказываются представленными в виде элементов массива, который можно обходить в цикле, получая тем самым доступ к контактным данным. Простейший способ выборки нужных данных из XML заключается в применении SimpleXML, поэтому в данном примере используется метод simplexml_load_string(), который преобразует элементы, содержащие контактные записи, в объекты SimpleXML. Далее выбираются дочерние элементы каждого тега <entry>, которые затем объединяются в единый объект, после чего все подобные объекты сохраняются в массиве $results. После окончания выборки всех записей ленты можно легко обойти все элементы этого массива при помощи оператора foreach(), преобразовав их к виду, подходящему для вывода на Web-страницу.

Необходимо сказать несколько слов об URL внутри объекта Zend_Gdata_Query. Этот адрес был сформирован в соответствии с форматом http://www.google.com/m8/feeds/contacts/USERID/TYPE, т. е. путем добавления имени пользователя и типа ленты к стандартному URL ленты. Существует два типа лент: полный и сокращенный (в последнем случае сервис возвращает только часть контактных данных). Если, как в листинге 2, указать ключевое слово default вместо имени, то будет получена лента по умолчанию для текущего пользователя.


Добавление контактов

Разобравшись с получением контактной информации, возникает естественный вопрос: а как добавлять новые контакты?

Эта задача решается проще, чем можно было бы предположить. Для добавления нового контакта достаточно отправить запрос типа POST, в теле которого содержится представленный в XML фрагмент <entry>, по адресу, соответствующему URL ленты. Пример такого фрагмента приведен в листинге 3.

Листинг 3. Пример контактной записи 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>

Библиотека Zend позволяет еще более упростить добавление контактов. Все, что от вас требуется – это вызвать метод insertEntry(), который создает запрос типа POST и передает данные по указанному URL ленты. Пример приведен в листинге 4.

Листинг 4. Пример добавления новой контактной записи
<?php
// Загрузка библиотеки Zend Gdata
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');

// Задание учетных параметров для аутентификации методом ClientLogin
$user = "user@gmail.com";
$pass = "guessme";

try {
  // Аутентификация и установка версии протокола (3.0)
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // Создание новой записи
  $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);
  
  // Добавление имени
  $name = $doc->createElement('gd:name');
  $entry->appendChild($name);
  $fullName = $doc->createElement('gd:fullName', 'Jack Frost');
  $name->appendChild($fullName);
  
  // Добавление адреса электронной почты
  $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);
  
  // Добавление названия организации
  $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);
  
  // Вставка записи
  $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());
}
?>

В листинге 4 показан пример открытия аутентифицированного соединения с API сервиса Google Contacts через объект Zend_Gdata, который ранее использовался в листинге 2. Далее происходит динамическое формирование фрагмента <entry>, приведенного выше в листинге 3, при помощи расширения DOM в PHP. Наконец, вызов метода insertEntry() приводит к сохранению сформированного фрагмента на одном из серверов Google. Добавленная запись сразу же становится доступной через Web-интерфейс Google Contacts.

Обратите внимание, что вы можете отметить адреса e-mail и телефоны как "домашний", "рабочий" или "мобильный", выбрав соответствующую схему для элемента <gd:organization rel="..." />.

После добавления записи Web-страница должна принять вид как на рисунке 2.

Рисунок 2. Результат добавления новой контактной записи
Screen capture of the output after you add a new contact

Некоторые части подтверждающего сообщения Google были умышленно стерты. Само сообщение представлено в следующем формате: Добавленная запись имеет идентификатор http://www.google.com/m8/feeds/contacts/USER_ID/base/CONTACT_ID.

При просмотре через Web-интерфейс Google Contacts добавленная запись выглядит как на рисунке 3.

Рисунок 3. Просмотр добавленной контактной записи через Web-интерфейс Gmail
Screen capture of the newly-added contact, Jack Frost, in Gmail

Удаление и редактирование контактов

API для доступа к данным Google Contacts также предоставляет возможности для удаления и редактирования контактных записей. Для удаления следует отправить запрос типа DELETE по адресу, соответствующему URL записи (он указан в элементе <link rel="edit" ...>). Если вы используете библиотеку Zend, то достаточно просто передать этот URL методу delete() объекта Zend_Gdata, как показано в листинге 5.

Листинг 5. Пример удаления контактных данных
<?php
// Загрузка библиотеки Zend Gdata
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');

// Задание учетных параметров для аутентификации методом ClientLogin
$user = "user@gmail.com";
$pass = "guessme";

// Задание идентификатора удаляемой записи
// from <link rel=edit>
$id = 'http://www.google.com/m8/feeds/contacts/default/base/29e98jf648c495c7b';

try {
  // Аутентификация и установка версии протокола (3.0)
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $client->setHeaders('If-Match: *');
  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // Удаление контактных данных
  $gdata->delete($id);
  echo '<h2>Delete Contact</h2>';
  echo 'Entry deleted';
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());
}
?>

Для редактирования следует сначала получить содержимое записи методом getEntry(), изменить нужные поля, а затем сохранить изменения на сервере при помощи метода updateEntry() объекта Zend_Gdata. Данный объект самостоятельно отправит запрос типа PUT по URL, указанному в элементе <link rel="self" ...> записи. Пример изменения имени и адреса e-mail в контактной записи показан в листинге 6.

Листинг 6. Редактирование контактных данных
<?php
// Загрузка библиотеки Zend Gdata
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');

// Задание учетных параметров для аутентификации методом ClientLogin
$user = "user@gmail.com";
$pass = "guessme";

// Задание идентификатора редактируемой записи
// from <link rel=self>
$id = 'http://www.google.com/m8/feeds/contacts/default/full/0';

try {
  // Аутентификация и установка версии протокола (3.0)
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $client->setHeaders('If-Match: *');

  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // Выполнение запроса и получение записи
  $query = new Zend_Gdata_Query($id);
  $entry = $gdata->getEntry($query);
  $xml = simplexml_load_string($entry->getXML());

  // Изменение имени
  $xml->name->fullName = 'John Rabbit';
  
  // Изменение основного адреса электронной почты  
  foreach ($xml->email as $email) {
    if (isset($email['primary'])) {
      $email['address'] = 'jr@example.com';  
    }  
  }
  
  // Обновление записи
  $entryResult = $gdata->updateEntry($xml->saveXML(), 
   $entry->getEditLink()->href);
  echo 'Entry updated';
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());
}
?>

Обратите внимание на поле "If-Match" в заголовках HTTP-запросов в листингах 5 и 6. Это поле особенно полезно в многопользовательской среде, поскольку оно позволяет выполнять операцию удаления или обновления только в том случае, если запись не была изменена с момента последнего чтения. Использование этого поля описывается более подробно в руководстве разработчика по использованию API для доступа к данным Google Contacts (ссылка приведена в разделе Ресурсы).


Использование дополнительных параметров

API для доступа к Google Contacts поддерживает несколько дополнительных параметров, влияющих на чтение лент, содержащих контактную информацию:

  • параметр start-index указывает, начиная с какого порядкового номера записи должны включаться в ленту;
  • параметр max-results задает число записей в ленте;
  • при помощи параметров orderby и sortorder задаются способ и направление упорядочивания записей в ленте;
  • параметр showdeleted указывает, следует ли включать в ленту записи, удаленные за последние 30 дней.

При использовании библиотеки Zend значения многих из этих параметров можно устанавливать через соответствующие свойства объекта Zend_Gdata_Query. Кроме того, данный объект содержит метод setParam(), служащий для работы с параметрами, специфичными для конкретного сервиса Google. Оба способа иллюстрируются в листинге 7, в котором длина ленты ограничивается 10 записями, упорядоченными по убыванию даты последнего редактирования.

Листинг 7. Пример использования дополнительных параметров при выполнении запроса
<?php
// Загрузка библиотеки Zend Gdata
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');

// Задание учетных параметров для аутентификации методом ClientLogin
$user = "user@gmail.com";
$pass = "guessme";

try {
  // Аутентификация и установка версии протокола (3.0)
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'cp');
  $gdata = new Zend_Gdata($client);
  $gdata->setMajorProtocolVersion(3);
  
  // Выполнение запроса и получение ленты
  $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);

  // Вывод заголовка и числа записей в ленте
  // остальной код опущен для краткости...
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

Пример простого приложения

Теперь, когда вы уже имеет представление о работе с API для доступа к Google Contacts, пришло время создать простое приложение на PHP, позволяющее добавлять и редактировать контакты. Прототип данного приложения содержит следующие три страницы (ссылка на zip-архив с исходным кодом приведена в разделе Загрузка):

  • contacts-index.php выводит список контактов, а также содержит ссылки для добавления и удаления записей;
  • contacts-save.php отображает форму добавления новой записи и обрабатывает отправленные через нее данные;
  • contacts-delete.php удаляет указанную запись.

Вначале мы рассмотрим первую страницу, представляющую собой модифицированный вариант листинга 2, в который было добавлено несколько ссылок (листинг 8).

Листинг 8. Получение и отображение списка контактов
<!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
    // Загрузка библиотеки Zend Gdata
    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');
    
    // Задание учетных параметров для аутентификации методом ClientLogin
    $user = "user@gmail.com";
    $pass = "guessme";
    
    try {
      // Аутентификация и установка версии протокола (3.0)
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // Выполнение запроса и получение ленты с контактными данными
      $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);
      
      // Отображение числа контактных записей в ленте
      ?>
      
      <h2><?php echo $feed->title; ?></h2>
      <div>
      <?php echo $feed->totalResults; ?> contact(s) found.
      </div>
            
      <?php
      // Разбор ленты и представление контактных записей 
      // в виде массива простых объектов
      $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    
    // Вывод результатов
    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>

Внешний вид страницы показан на рисунке 4.

Рисунок 4. Внешний вид страницы для отображения контактных данных со ссылками для удаления и добавления
Screen capture of a Web page that lists contacts, with add and delete functions

Как видно из рисунка 4, каждая запись теперь включает ссылку для удаления. URL ссылки содержит идентификатор записи, который передается сервису в виде параметра GET-запроса. Серверный скрипт получает данный идентификатор и удаляет запись методом, продемонстрированным в листинге 5. Пример кода приведен в листинге 9.

Листинг 9. Удаление контактных данных
<!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
    // Загрузка библиотеки Zend Gdata
    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');
    
    // Задание учетных параметров для аутентификации методом ClientLogin
    $user = "user@gmail.com";
    $pass = "guessme";
    
    if (empty($_GET['id'])) {
      die('ERROR: Missing ID');
    } 

    try {
      // Аутентификация и установка версии протокола (3.0)
      $client = Zend_Gdata_ClientLogin::getHttpClient(
        $user, $pass, 'cp');
      // Задание значения поля If-Match в заголовке HTTP
      $client->setHeaders('If-Match: *');
      $gdata = new Zend_Gdata($client);
      $gdata->setMajorProtocolVersion(3);
      
      // Удаление записи
      $gdata->delete($_GET['id']);
      echo 'Entry deleted';
    } catch (Exception $e) {
      die('ERROR:' . $e->getMessage());
    }
    ?>
  </body>
</html>

Выше были приведены примеры получения списка записей и их удаления. Что касается добавления, то обратите внимание на листинг 10, в котором показан серверный скрипт, позволяющий создавать записи через Web-форму. Данный скрипт использует библиотеку Zend для формирования и отправки запроса типа POST для сохранения записи на сервере.

Листинг 10. Добавление новых контактных данных
<!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 { 

      // Проверка наличия необходимых входных данных
      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');
      } 
      
      // Первичная обработка ввода и сохранение информации в массиве
      $inputData['name'] = htmlentities($_POST['name']);
      $inputData['email'] = htmlentities($_POST['email']);
      $inputData['org'] = htmlentities($_POST['org']);
      
      // Загрузка библиотеки Zend Gdata
      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');
      
      // Задание учетных параметров для аутентификации методом ClientLogin
      $user = "user@gmail.com";
      $pass = "guessme";
      
      try {
        // Аутентификация и установка версии протокола (3.0)
        $client = Zend_Gdata_ClientLogin::getHttpClient(
          $user, $pass, 'cp');
        $gdata = new Zend_Gdata($client);
        $gdata->setMajorProtocolVersion(3);
        
        // Создание новой записи
        $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);
        
        // Добавление имени
        $name = $doc->createElement('gd:name');
        $entry->appendChild($name);
        $fullName = $doc->createElement('gd:fullName', $inputData['name']);
        $name->appendChild($fullName);
        
        // Добавление адресов электронной почты
        $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);          
        }
        
        // Добавление названия организации
        $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);
        
        // Вставка записи 
        $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>

Листинг 10 состоит из двух частей: Web-формы и кода на PHP, который обрабатывает полученные от пользователя данные. Внешний вид Web-формы показан на рисунке 5.

Рисунок 5. Внешний вид Web-формы для добавления контактных данных
Screen capture of a Web page with form fields to add a new contact

После того как пользователь ввел имя, адрес электронной почты, название организации и отправил форму, ее содержимое передается на обработку второй части скрипта. В ней инициализируется клиентский объект HTTP, с помощью которого открывается аутентифицированное соединение с API сервиса Google Contacts. Затем выполняется проверка данных формы, после чего они помещаются в только что созданный экземпляр DOMDocument.

Далее новый элемент <entry> создается динамически средствами DOM в PHP, а затем вызывается метод insertEntry(), отвечающий за сохранение записи на сервере Google. После сохранения записи API возвращает ее уникальный идентификатор, который показывается пользователю, говоря о том, что новый контакт был успешно добавлен.

После добавления контакта страница примет вид как на рисунке 6.

Рисунок 6. Внешний вид страницы после добавления новой контактной записи
Screen capture of the output after you add a new contact

Некоторые поля в подтверждающем сообщении, показанном на рисунке 6, были умышленно стерты. Само сообщение выдается в формате: Добавленная запись имеет идентификатор http://www.google.com/m8/feeds/contacts/USER_ID/base/CONTACT_ID


Заключение

Итак, вы прошли краткий курс по использованию API для доступа к сервису Google Contacts в приложениях на PHP при помощи SimpleXML и клиентской библиотеки Zend. На приведенных примерах вы познакомились с форматом информационных лент Google Contacts, получением списка контактов, а также их удалением, добавлением и редактированием. Кроме того, вы увидели, как можно создать собственное Web-приложение для отображения контактов, хранящихся в вашей учетной записи Google.

Как видно из примеров, API для доступа к Google Contacts предоставляет разработчикам широкие возможности по созданию новых приложений для управления списком контактов. Попробуйте его в деле, чтобы составить собственное мнение!


Загрузка

ОписаниеИмяРазмер
Исходный код последнего примераcontacts-example-app.zip4 KБ

Ресурсы

Научиться

Получить продукты и технологии

  • Загрузите библиотеку Zend GData, предоставляющую все необходимые средства для доступа к данным Google Contacts из приложений, написанных на PHP 5. (EN)

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Open source
ArticleID=742214
ArticleTitle=Интеграция PHP-приложений с сервисом Google Contacts
publish-date=07222011