【IT168 技术】像 Foursquare 这样基于位置的服务非常流行。如果您还没有听说过它们,那么不久将会听说。似乎不管您走到哪里,人们都在使用 Foursquare、Gowalla、Loopt 和其他工具来 “签入” 他们最喜欢的位置,与其他用户就最喜欢的餐饮分享提示,在 Twitter 和 Facebook 等其他服务上分享所有这些活动。
作为一名开发人员,您必须知道这些东西。社交服务,特别是使用社交平台的基于位置的服务,对于 Web 和移动开发人员来说具有巨大的发展空间。这些服务中有大部分使用某种 RESTful 服务,您可以使用它们来请求 JavaScript Serialized Object Notation (JSON) 或 XML 数据。有一些,比如 Facebook,不需要太多身份验证,而其他服务,比如 Foursquare,有一些提要确实需要身份验证,而有些不需要。
出于本文的需要,我假定您知道一些有关 PHP 的东西,但仅此而已。我将轻松地演练其余部分 — 访问 Foursquare 提要,处理工作集,清除它。您在本文结尾构建的样例应用程序很简单:使用 geolat 和 geolong 坐标提供 Foursquare,看看目前有多少人住进附近的位置。由于我居住在得克萨斯州奥斯汀,我想输入第六街的坐标并查看附近的状况会很有趣。
出于两个原因我选择了这么做。第一,因为它是要访问的最简单的提要,但是打开它会为您提供一个相当不错的对于其他提要的预览。第二,它不需要身份验证 — 毕竟,您不是在查找有关谁会入住的详细信息,只是在查看原始计数。场所公共提要在本文范围内提供了大量功能。
何为 Foursquare?
Foursquare 是一种允许用户探究其周围世界的社交位置服务。用户可以下载 Foursquare 应用程序到其 iPhone、Blackberry 或 Android 手机并免费注册,然后将其 Foursquare 帐户连接到其他社交媒体帐户。
在用户下载免费应用程序并连接到 Facebook 或 Twitter 时,他们可以联系其他在 Foursquare 处于活跃状态的朋友。每当他们或他们的朋友签入 到一个地方(即他们在一个位置并告诉其他人他们在那里),消息就会通过 Twitter 或 Facebook 传播给他们的朋友。
当一名用户签入了足够长的时间之后,该用户就成为所在位置的市长,根据该位置经营的业务,可能会也可能不会为该用户提供特别优惠。例如,一家咖啡店可能会为成为市长的任何人供应免费饮料。用户还可以在探索和签入到某个位置时赢取徽章,给其他用户留下提示(例如,“这里的玛格丽塔鸡尾酒太棒了!”),甚至还可能有机会创建还未在服务上出现的位置。
图 1 是 Web 上 Foursquare 主页的屏幕截图。

▲图1 Foursquare 主页
Foursquare 在 2009 年 11 月启动其 API,允许应用程序开发人员以有趣的方式扩展平台。开发人员可以构建位置管理工具、自定义搜索引擎,甚至与 Foursquare API 交互的游戏和其他工具。例如,您可以构建一个地理位置游戏,允许玩家也签入到 Foursquare 位置,作为正常游戏的自然产物。
有了对 Foursquare 的了解之后,让我们看看 Foursquare API。
Foursquare API 快速概览
Foursquare API 允许应用程序开发人员与 Foursquare 平台进行交互。API 本身是一个 REST 式的地址集,您可以向其发送请求,因此实际上没有什么需要下载到您的服务器。话虽如此,在本文中您要使用一组 PHP 库来帮助简化请求和响应,不过这完全是可选步骤。
您目前可以请求 XML 或 JSON 格式的输出,向下面这样的 URLs 发出请求:http://api.foursquare.com/v1/user.json。如果您不使用请求扩展,那么会向您返回 XML。向 http://api.foursquare.com/v1/user 发出的请求会生成 XML 输出。
有 GET 和 POST 方法可供您使用,这表示您不仅仅受限于读取提要,您还可以做一些有用的事情,比如使用 API 签入和创建位置。对于速率限制,您的应用程序的限制为每个方法每小时 200 个请求,所以为了 “发挥好”,您可能希望实现某种结果缓存。
您多半希望使用基本的或 OAuth 身份验证来充分利用各种方法和服务。本文中的示例(/venues)不需要任何身份验证,但它确实有一些供使用身份验证的人使用的额外功能。
您可以用 API 做什么呢?表 1 总结了主要方法。欲了解更多信息,请阅读 API 文档(参考资料)。
表 1. Foursquare API 方法概要

有一大堆其他 API 方法涉及到朋友、测试身份验证、出于不同原因而标记位置、收集和创建提示等。不过我想您有一个大致了解。
构建您自己的 PHP 应用程序
您已经大致了解了 Foursquare API,现在可以切入正题来构建一个简单的应用程序了。正如我在简介部分提到的,我想做的就是创建一个视图,告诉我有多少人签入了奥斯汀第六街酒吧周围的位置。总不能让我一路开车到市中心来查找是否有停车的地方吧!
尽管为这个目的使用 Foursquare 似乎有点无聊,不过注意,您可以采用这一基本思路将其用于各种环境中。例如,您可能想跟踪有多少城中参会人员签入到本地场所,或者有多少人参加各分会。
出于本文的需要,我将整个流程分为三个主要部分:
下载 helper 库
创建一个基本提要
使用提要内容创建一个清除后的 web 页面
下载 foursquare-async 库
尽管您不是很需要 Foursquare API 的封装器,但是从 GitHub 上下载奇妙的 foursquare-async 库是个不错的注意(参见 参考资料)。它提供一些文件,允许您通过 API 使用提供给您的大部分方法。
下载内容包括一个 readme 文件、一个 license 文档,还有三个 PHP 文件:
EpiCurl.php
EpiFoursquare.php
EpiOAuth.php
将这三个 PHP 文件全部放进一个名为 lib 的项目根目录中,接着进入应用程序构建部分。
创建一个提要
接下来,创建一个名为 feed.php 的文件,将其放在项目根目录中。在这个文件中,您可以使用 require() 函数纳入您下载并放入 lib 文件夹的所有 Epi*.php 文件。
然后实例化一个新的 epiFourSquare 对象,然后使用该对象连接到 venues.json 提要,传入任何必要的参数,比如 geolat、geolong 和数量为 50 的结果限制。
最后,使用 json_encode() 将传入的 JSON 提要转换为一个 PHP 数据对象,并将其保存为一个数组。当然,为确保所有内容的安全性,您可以将全部内容包装在 try {...}exception 中。
如果您不通过 json_encode() 运行提要,最终就得处理如下所示的提要之类的东西。

▲图2 原始JSON 提要
这对于一些人来说还好,但是您得承认,图 3 中所示的 PHP 数据对象比较容易弄清楚。

▲图3 JSON 上的 PHP 数据对象
清单 1 显示整个代码。
清单 1. 连接到 Foursquare 场所提要
require('lib/EpiOAuth.php');
require('lib/EpiFoursquare.php');
$fsObj = new EpiFoursquare();
try{
$venues = $fsObj->get_basic('/venues.json',
array('geolat' => '30.268056',
'geolong' => '-97.741381',
'l' => '50'));
$venues_array = json_decode($venues->responseText);
}catch(Exception $e){
echo "Error: ". $e;
}
这不是非常复杂,获取场所提要和签入计数只用了 15 行代码。请注意,示例中的 geolat 和 geolong 坐标与奥斯汀市中心 Driskill Hotel 的邻近地区匹配 — 我将该场所作为一个便利的中心点,因为很多市中心场所都与它很接近。
创建一个 web 视图
此时,您拥有一个已经转化为 PHP 数据对象的 JSON 提要。这对于 PHP 程序员来说很有用,但对其他人几乎没有任何用处。您需要做的就是将这些内容嵌入到一个任何人都可以使用的 web 页面。
为此,在根目录中创建一个 index.php 文件。使用您感到舒适的任何 Cascading Style Sheets (CSS) 和 JavaScript 框架以及设计元素。例如,在 清单 2 所示的样例代码中,我使用了 960 Grid 框架,因为它能够让我的工作简单起来。另外还要包含您刚才编写的 feed.php 代码,然后处理 $venues_array 数组,以将其放入到数据表中。
复杂之处在于,Foursquare API 是分层次的,第一层(组)对您来说没有太大意义。您需要访问场所级别,因为您要在这里搜寻并提取有价值的信息供以后使用。
清单 2 中显示的部分示例提供一种简便方法来访问场所级别:foreach ($venues_array->groups[0]->venues as $v){ 在 PHP 数据对象中的正确位置开始循环,允许您访问 $v->name 项目来获取场所名称,访问 $v->stats->herenow 来获取场所目前的签入量。
事实上,如果您每次通过循环查看 $v 的数据结构,它有点像清单 2。
清单 2. 每个场所的 PHP 数据对象
{
[id] => 5261
[name] => Driskill Hotel
[primarycategory] => stdClass Object
{
[id] => 79273
[fullpathname] => Travel:Hotel
[nodename] => Hotel
[iconurl] => http://foursquare.com/img/categories/travel/hotel.png
}
[address] => 604 Brazos St
[crossstreet] => at W 6th St
[city] => Austin
[state] => TX
[zip] => 78701
[geolat] => 30.2679601
[geolong] => -97.7413707
[stats] => stdClass Object
{
[herenow] => 0
}
[phone] => 5124745911
清单 3 中的代码片段提供整个 index.php 页面,通过一个数据结构循环完成,提取出一个 $final 数组的相关信息,然后使用这些信息来创建数据表。其结果是一个仪表板,显示场所名称、地址和电话号码,以及签入到那里的人数。
还要注意,由于电话号码并非场所的必要字段,因此您必须快速检查一下它是否包含在数据提要中。如果是,那么打印该号码,如果不是,则忽略它。
清单 3. 构建 index.php 视图
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>FourSquare API Test</title>
<link rel="stylesheet" type="text/css" href="css/960.css" media="all" />
<link rel="stylesheet" type="text/css" href="css/reset.css" media="all" />
<link rel="stylesheet" type="text/css" href="css/text.css" media="all" />
<link rel="stylesheet" type="text/css" href="css/tables.css" media="all" />
</head>
<body>
<div class="container_12">
<div class="grid_12">
<h1>FourSquare API Test</h1>
</div>
</div>
<div class="container_12">
<div class="grid_12" id="updates">
<?php
include_once 'feed.php';
$final = array();
foreach ($venues_array->groups[0]->venues as $v){
if (isset($v->phone)){
$PHONE = $v->phone;
}else{
$PHONE = "not listed";
}
$final[$v->id] = array(
'name' => $v->name,
'address' => $v->address,
'herenow' => $v->stats->herenow,
'phone' => $PHONE
);
}
?>
<table border='1' cellspacing='0' cellpadding='0'>
<thead>
<tr valign='top'>
<th>Location</th>
<th>Address</th>
<th>Phone</th>
<th>Here Now</th>
</tr>
</thead>
<tbody>
<?php
foreach ($final as $key => $data){
echo "<tr valign='top'>";
echo "<td>".$data['name']."</td>\n";
echo "<td>". $data['address']."</td>\n";
echo "<td>". $data['phone']."</td>\n";
echo "<td align='center'>". $data['herenow']."</td>\n";
echo "</tr>\n";
}
?>
</tbody>
</table>
</div>
</div>
</body>
</html>
超出 PHP 之外的大部分代码示例都只是为了便于人们查看,不一定有用。您可以应用自己的样式和方法来让信息显得直观明了。例如,您可以将来自 PHP 文件的 JSON 提要绑定到 jQuery.getJSON() 方法中,以便无需刷新 Web 页面即可刷新它。
您还可以使用一个更简单、直观的列表来展现信息,使其在一个小的智能手机屏幕的上下文内看起来更自然。例如,清单 4 显示最终的 foreach 循环,生成了一个列表。
清单 4. 简化的列表
<ul>
<?php
foreach ($final as $key => $data){
echo "<li>";
echo $data['name']." (". $data['herenow'].")". "<br/>\n";
echo $data['address']."<br/>\n";
echo $data['phone']."<br/>\n";
echo "</li>\n";
}
?>
</ul>
仅向 UL 和 LI 节点添加一些类就可以为 iPhone 或其他移动设备上的任何人带来引人注目的视觉体验。他们可以检查您的 web 页面,看具体的 geolat/geolong 坐标周围的位置有什么状况发生,从而决定晚上去哪里。
要改善用户体验,您还有什么可以做的?需要一个用户来在 Foursquare 上进行身份验证,以查看更多细节。关于如何做到这一点的详情超出了本文讨论范围,但是当对用户进行身份验证时,您可以在这个列表中提供有关其朋友的更多信息,您还可以提供一个简单的地图界面来让用户选择初始的 geolat/geolong 坐标,使其成为一个更有用的通用工具。
结束语
现在您知道如何使用 Foursquare API 了,该是时候创建一些有趣的东西了。不过在太深入之前,了解一下其他人都在使用 API 做什么。Foursquare 的 App Gallery 包含其他人创建的一些值得注意的应用程序。