级别: 中级 Vikram Vaswani, 创始人, Melonfire
2009 年 11 月 12 日 Google Contacts Data API 提供一个强大的、客户端中立的 API,用于读取和修改用户的私有 Gmail 联系人信息。学习利用一个具有该 API 的定制 PHP 应用程序在应用程序上下文中检索、添加、删除和修改联系人。
简介
 |
常用缩写词
- API (Application program interface):应用程序程序接口
- DOM (Document Object Model):文档对象模型
- HTTP (Hypertext Transfer Protocol):超文本传输协议
- REST (Representational State Transfer):具象状态传输
- URL (Uniform Resource Locator):统一资源定位符
- XML (Extensible Markup Language):可扩展标记语言
|
|
由于我与朋友及同事一般通过电子邮件进行联络,所以我已经习惯于将联系人信息存储在与 Mozilla Thunderbird 一起发布的地址簿应用程序中,这是我的默认电子邮件客户端。但是最近几个月,我已经逐渐将信息转移到 Gmail,Gmail 自带了一个强大的地址簿。该特性就是 Google Contacts,很容易通过 Web 进行访问,支持大量的信息字段,并且具有导入和导出特性。利用该特性不仅可以存储大量的联系人信息,而且可以让联系人信息随您而“行”,因为您可以从任何一台可访问 Web 的计算机访问此信息。
Google Contacts 从开发角度也很有趣:跟很多其他 Google 产品一样,它提供一个 Data API,使得开发人员很容易围绕存储在私有地址簿中的数据构建新的应用程序。该 API 遵循 REST 模型,可通过任何支持 XML 的开发工具包访问到,也为很多常见编程语言(包括我喜欢的 PHP)具有客户端库。
本文介绍 Google Contacts Data API,并展示如何与一个定制 PHP 应用程序一起集成和使用联系人数据。在这些例子中,您将从用户的地址簿中检索联系人、添加新联系人、修改和删除联系人,以及控制联系人提要中返回的数据。来吧,下面我们开始学习!
理解 Google Contacts API
在深入 PHP 代码之前,有必要简要介绍一下 Google Contacts Data API。与其他 Google Data API 一样,系统接受包含一个或多个 XML 编码的输入参数的 HTTP 请求,并返回包含所请求的信息的 Atom 提要。这些提要然后可以在任何理解 XML 的编程语言中进行解析。此外,GET、POST、PUT 和 DELETE 等标准的 HTTP 操作分别对应于用于检索、添加、更新和删除记录的 API 方法。
典型的 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>
|
每个 Contacts 提要都以一个 <feed>元素作为根元素开始。<feed>元素包含 <link>元素(其中包含不同版本提要的 URL)和 <openSearch:>元素(其中包含摘要统计信息)。
最外层的 <feed>元素中包含一个或多个 <entry>元素,每个这样的元素代表单个联系人。每个 <entry>包含进一步的详细信息,包括联系人的姓名、单位、头衔、电子邮件地址、电话和传真号码、Web 站点和照片(以及其他信息)。每个 <entry>也包含两个进一步的 <link>元素,即 <link rel="self" ...>和 <link rel="edit" ...>,其中分别包含用于检索完整条目的 URL 和用于编辑条目的 URL。
检索联系人
一定要注意,Google Contacts 提要是私有的。这意味着,对包含在提要中的数据进行的任何操作 —包括仅仅是查看 —必须要经过用提要所有者的用户名和密码进行身份验证后才能成功,使用 Google 批准的两种身份验证方法之一:AuthSub 或 ClientLogin。
手动执行这种类型的身份验证是相当繁琐的,需要一大段代码来处理典型的身份验证事务过程中可能出现的各种情况。幸运的是,您无需太多地担心此问题:Zend's®GData Client Library 专为集成 PHP 应用程序与 Google Data API 的开发人员而设计,将为您处理所有的细节。该库可单独下载(参见 参考资料中的链接),提供一个方便的、到 Google Data API 的面向对象的接口,封装了大多数常见任务(包括身份验证),可以将您从繁琐的事情中解放出来,去关注应用程序的核心功能。本文中其余的例子将用到该库,所以在继续阅读之前,需确保已安装该库。
安装了 Zend's GData 库之后,我们继续来看一个使用 PHP 处理 Google Contacts Data API 提要的例子。清单 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
// 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>
|
图 1显示了您会看到的输出。在屏幕快照中,一些个人电子邮件地址信息被蒙住了。
图 1. 一个列出联系人信息的 Web 页面
首先,清单 2加载 Zend 类库,然后初始化 Zend_Gdata 服务类的一个实例。这个类使用了一个 Zend_Http_Client 对象,该对象是与必要的用户身份认证信息一起提供的,用于打开一个到 Google Contacts 服务的已验证连接。一旦打开了一个已验证连接,getFeed()方法就会检索联系人提要。该方法接受一个 Zend_Gdata_Query 对象,提要 URL 被传递给该对象。也请注意 清单 2中对 setMajorProtocolVersion()的调用,这告诉服务器使用 v3.0 的 Google Contacts Data API;这是一个必需的调用。如果忽略该调用,就可能会看到非预期的行为。
对 getFeed()API 调用的响应是一个类似于 清单 1中的 XML 提要,该提要然后被解析并转换成 PHP 对象。提要中的条目被表示为数组元素,从而使得在提要上迭代和检索单个联系人条目成为可能。由于 SimpleXML 提供一种较容易的方式从 XML 树检索特定的信息,所以 simplexml_load_string()方法被用来将每个条目的 XML 转换成一个 SimpleXML 对象。然后,每个 <entry>下的子节点被检索并简化成一个较简单的对象以方便检索,得到的每个对象又被放在 $results数组中。处理完整个提要之后,就很容易利用一个 foreach()循环在 $results数组上迭代,并对内容进行格式化以显示在 Web 浏览器中。
这里简单解释一下传递给 Zend_Gdata_Query 对象的提要 URL:它通过将用户名和提要类型附加到 http://www.google.com/m8/feeds/contacts/USERID/TYPE 中的标准提要 URL 而产生。提要类型有两种变种,即完全的(full)和瘦的(thin),后者只返回整个条目的一个子集。使用特殊关键字 default取代用户名,跟 清单 2中一样,会返回用户的默认提要。
添加联系人
至此已经介绍了列出联系人。现在,如何添加新联系人呢?
这实际上并不复杂。要添加新联系人,只需 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
// 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());
}
?>
|
清单 4使用 Zend_Gdata 对象打开一个到 Google Contacts
Data API 的已验证连接,如前面 清单 2中所示。接下来,PHP 中的 DOM 扩展动态地构造 清单 3中所示的 XML <entry>,并使用 insertEntry()方法将产生的 XML 实际保存到 Google 服务器。条目一旦添加,就应该立即变得在 Google Contacts 界面中可见。
注意,可以通过在 <gd:organization rel="..." />元素中指定适当的模式,显式地将电子邮件地址和电话号码标记为属于“家庭(home)”、“工作(work)”或“手机(mobile)”。
图 2显示了成功添加新联系人条目之后的输出:
图 2. 添加新联系人之后的输出
在图 2 中的屏幕快照中,来自 Google 的确认消息中的一些字段被蒙住了。消息格式如下:The ID of the new entry is
http://www.google.com/m8/feeds/contacts/USER_ID/base/CONTACT_ID。
图 3显示了它在 Google Contacts 界面中看起来的样子:
图 3. Gmail 中新添加的联系人
删除和更新联系人
Google Contacts Data API 也允许您编辑和删除条目。要删除条目,发送一个 DELETE 请求到联系人的编辑 URL,这是条目的 <link rel="edit" ...>元素中指定的 URL。在 Zend 库上下文中,可以简单地将该 URL 传递给 Zend_Gdata 对象的 delete()方法,如 清单 5中所示:
清单 5:删除联系人
<?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());
}
?>
|
要编辑条目,使用 getEntry()方法和条目的唯一标识符,检索该条目,更改您想要更新的值。然后利用 Zend_Gdata 对象的 updateEntry()方法将条目保存回服务器,该方法发送一个 PUT 请求到条目的 <link rel="self" ...>元素中指定的 URL。清单 6演示了为联系人条目设置一个新名字和电子邮件地址的过程:
清单 6:修改联系人
<?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());
}
?>
|
注意,清单 5和 清单 6都添加一个额外的 "If-Match" 头部作为 HTTP 请求的一部分。该头部在多客户端环境中尤其有用,因为它可用于删除或更新自上次读取以来未发生更改的条目。Google Contacts Data API Developers Guide(参见 参考资料中的链接)更为详细地讨论了该头部。
使用额外的参数
Google Contacts Data API 也支持很多额外的参数,可用于控制产生的提要。下面列出了这些参数:
start-index参数指定提要的起始偏移
max-results参数指定提要中的条目数量
orderby和 sortorder
参数指定如何排序提要条目
showdeleted参数包括在最近 30 天删除的提要中的条目
如果使用的是 Zend 客户端库,只需设置 Zend_Gdata_Query 对象的相应属性,就可以设置很多这些参数。对于那些特定于服务的参数,Zend_Gdata_Query 对象也提供一个 setParam()方法。这些技术都演示在 清单 7中,这里将结果限制为 10 个条目,按最后修改日期降序排列。
清单 7:设置额外的查询参数
<?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());
}
?>
|
一个简单的应用程序
既然知道了 Google Contacts Data API 是如何工作的,就可以尝试来构建一个简单的 PHP 应用程序,用于进行联系人输入和操纵。该原型应用程序具有 3 个脚本(参见 下载,得到一个压缩文件):
- contacts-index.php 列出联系人条目,并提供链接以添加和删除条目。
- contacts-save.php 显示一个表单以添加新条目,并处理提交。
- contacts-delete.php 删除指定的条目。
从第一个脚本开始介绍,并用一些额外的链接更新 清单 1,如 清单 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
// 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>
|
图 4给出了修改后的输出。
图 4. 列出联系人、带添加和删除功能的网页
从 图 4可以看到,现在在每个条目的边上都有了一个额外的 Delete 链接。此链接包含了条目 ID,该 ID 将作为 GET 参数传递给链接目标。目标脚本使用 清单 5所示的技术读取此 ID 并删除它。清单 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
// 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>
|
上面演示了如何列出和删除条目。那么如何添加条目呢? 清单 10给出了另外的脚本,让用户能够通过网页表单添加新的联系人。然后使用 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 {
// 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>
|
清单 10实际上由两部分组成:Web 表单和 PHP 代码。PHP 代码处理通过表单提交的输入。图 5给出了此表单的大概样子。
图 5. 添加新联系人的 Web 表单
一旦用户在表单中输入联系人姓名、电子邮件地址和组织,并提交它,脚本的第二部分将执行操作。首先,初始化 HTTP 客户端,打开一个经过验证的 Google Contacts Data API 连接。接下来,验证输入到 Web 表单中的条目,初始化一个新的 DOMDocument 对象,以保存新条目的数据。
然后,PHP 中的 DOM 方法动态地构建一个新的 <entry>,实际上 insertEntry()方法将条目保存到 Google 服务器。添加条目之后,API 将返回其唯一 ID,显示给用户,以指示操作成功。
图 6给出了成功添加新联系人后的输出。
图 6. 添加新联系人后的输出
在 图 6所示的屏幕快照中,对于来自 Google 的确认消息,有些字段被蒙住。消息的格式如下:The ID of the new entry is
http://www.google.com/m8/feeds/contacts/USER_ID/base/CONTACT_ID。
结束语
在本文中,我们快速介绍了如何结合使用 SimpleXML 和 Zend 客户端库,将来自 Google
Contacts Data API 的数据集成到 PHP 应用程序中。本文中的示例向您介绍了 Google Contacts 摘要格式;展示了如何检索联系人列表;添加、修改和删除联系人;以及利用存储在用户 Google Account 中的联系人信息数据,构建一个自定义的界面。
从这些例子可以看出,Google Contacts Data API 是一个功能强大且极为灵活的工具,开发人员可用于构建针对联系人管理的富有创造力的新应用程序。有时间可以试一试,看能否激发您的灵感!
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Archive of the final code example | contacts-example-app.zip | 4KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
关于作者  | 
|  | Vikram Vaswani 是 Melonfire 的创始人和 CEO,该公司是一家专门研究开源工具和技术的咨询服务公司。他还著有 PHP Programming Solutions 和 How to do Everything with PHP and MySQL 等著作。 |
对本文的评价
|