首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

创建一个移动友好的待办事项列表应用程序(3)

创建一个移动友好的待办事项列表应用程序(3)

列出任务清单 2 结合使用了 Google OAuth 库和 Slim 框架来连接、验证任务列表和任务,并显示了它们的摘要。
清单 2. OAuth 身份验证流和任务列表检索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
session_start();
require_once 'vendor/Slim/Slim.php';
require_once 'vendor/google-api-php-client/src/Google_Client.php';
require_once 'vendor/google-api-php-client/src/contrib/Google_TasksService.php';

\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
$app->config(array(
  'debug' => true,
  'templates.path' => './templates'
));
$client = new Google_Client();
$client->setApplicationName('Project X');
$client->setClientId('YOUR-CLIENT-ID');
$client->setClientSecret('YOUR-CLIENT-SECRET');
$client->setRedirectUri('http://tasks.melonfire.com/login');
$client->setScopes(array(
  'https://www.googleapis.com/auth/tasks'
));
$app->client = $client;
$app->tasksService = new Google_TasksService($app->client);


$app->get('/login', function () use ($app) {
   
    if (isset($_GET['code'])) {
      $app->client->authenticate();
      $_SESSION['access_token'] = $app->client->getAccessToken();
      $app->redirect('/index');
      exit;
    }  

    // if token available in session, set token in client
    if (isset($_SESSION['access_token'])) {
      $app->client->setAccessToken($_SESSION['access_token']);
    }

    if ($app->client->getAccessToken()) {
      if (isset($_SESSION['target'])) {
        $app->redirect($_SESSION['target']);
      } else {
        $app->redirect('/index');
      }
    } else {
      $authUrl = $app->client->createAuthUrl();
      $app->redirect($authUrl);
    }
   
});

$app->get('/index', 'authenticate', function () use ($app) {
  $lists = $app->tasksService->tasklists->listTasklists();
  foreach ($lists['items'] as $list) {
    $id = $list['id'];
    $tasks[$id] = $app->tasksService->tasks->listTasks($id);
  }
  $app->render('index.php', array('lists' => $lists, 'tasks' => $tasks));
});


$app->get('/logout', function () use ($app) {
  unset($_SESSION['access_token']);   
  $app->client->revokeToken();
});

$app->run();

function authenticate () {
  $app = \Slim\Slim::getInstance();
  $_SESSION['target'] = $app->request()->getPathInfo();
  if (isset($_SESSION['access_token'])) {
    $app->client->setAccessToken($_SESSION['access_token']);
  }
  if (!$app->client->getAccessToken()) {
    $app->redirect('/login');
  }
}




清单 2(应保存为 $APP_ROOT/index.php)首先加载 Slim 和 Google OAuth 客户端库,以及 Google Tasks 服务对象。它初始化一个新的 Slim 应用程序对象和一个新的 Google_Client 对象。不用说,Google_Client 对象必须配置之前在 Google Cloud Console 中定义的相同的客户端 ID、客户端密钥和重定向 URL。还会初始化一个 Google_TasksService 服务对象,该对象用作通过 PHP 与 Google Tasks API 交互的主要控制点。
Slim 定义 HTTP 方法和端点的路由器回调。完成方式是调用相应的方法(get() 用于 GET 请求、post() 用于 POST 请求等),并传递 URL 路由,以便匹配为该方法的第一个参数。该方法的第二个参数是一个函数,它指定了在路由与一个传入的请求匹配时应采取的操作。清单 2 设置了 3 个这样的路由器回调:/index、/login 和 /logout。我们将依次看看每个回调:
  • /login 回调处理了 OAuth 身份验证流。有关这个流的完整讨论不属于本文的讨论范围,但您可通过 Google API 文档获取有关的详尽细节                    。简言之,此回调使用了 Google_Client 对象的 createAuthUrl() 方法生成 Google 身份验证页面的 URL(参见下图),然后将客户端浏览器重定向到这个 URL。在用户验证应用程序并确认它能够访问的数据后,Google 将客户端重定向回 /login URL,此 URL 将会获取一个访问令牌并将该令牌存储在会话中。这个访问令牌为客户端提供了访问 Google Tasks API 的能力。
  • 成功的 OAuth 身份验证会将客户端重定向到应用程序的索引页面,位于 /index。此回调使用已配置好的 Google_TasksService 对象和它的 listTasklists() 方法来获取经过验证的用户的一组任务列。该代码然后迭代这个任务列表集合,对于每个列表,该代码都会调用服务对象的 listTasks() 方法来获取该列表中的各个任务。然后将此信息传输给视图,视图负责向用户呈现它。下文将给出视图脚本。
  • /logout 方法会销毁会话,进而清空其中存储的访问令牌。为了提高安全性,它还调用了客户端对象的 revokeToken() 方法,这也会让 Google 服务器上的令牌失效。
您已经看到,/index 回调负责获取用户的任务列表和每个列表的任务。此信息存储在 PHP 变量中,并被传输给视图,后者负责将它格式化为容易阅读的列表。视图脚本应位于 $APP_ROOT/templates/index.php,它应类似于:
清单 3. 索引页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="http://code.jquery.com/
    mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
  <script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
  <script src="//code.jquery.com/mobile/1.3.2/
    jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
    <div data-role="page">
      <div data-role="header">
      Tasks
      </div>
      <div data-role="content">
      <div data-role="collapsible-set" data-inset="false">
        <?php foreach ($lists['items'] as $list): ?>
          <?php $id = $list['id']; ?>
          <div data-role="collapsible">
            <h2><?php echo $list['title']; ?></h2>
            <ul data-role="listview">
              <?php if (isset($tasks[$id]['items'])): ?>
                <?php foreach ($tasks[$id]['items'] as $task): ?>
                <li>               
                  <h3><?php echo $task['title']; ?></h3>
                </li>
                <?php endforeach; ?>
              <?php endif; ?>
            </ul>
          </div>
        <?php endforeach; ?>
        </div>
      </div>
    </div>        
</body>
</html>




清单 3 设置了一个依据标准 jQuery Mobile 约定而格式化的列表视图页面。主要页面元素是一个 <div> 元素,它有一个 data-role="page" 属性。该属性中包含针对页面页眉、页脚和内容的不同 <div> 元素。页面内容包含一系列可折叠的 <div> 元素,每个元素表示用户的一个任务列表。单击一个列表的标题会展开它的任务。
要查看此功能是如何实现的,您可以在浏览器中访问 http://tasks.melonfire.com/index(将该 URL 替换为您自己的虚拟主机的 URL)。您应该看到一个与以下列表类似的任务列表:
返回列表