建立以 API 爲中心的 Web 應用

http://www.oschina.net/translate/creating-an-api-centric-web-application?from=20130818php

 

正計劃着要開始搞一個新的網絡應用?在這篇教程中,咱們將討論如何建立以API爲中心的網絡應用,還會解釋在今天的多平臺世界,這類應用爲何是重要的。css

引言

API?html

對於還不甚熟悉這個術語的朋友,API是Application Programming Interface(應用編程接口)的簡稱。根據維基百科前端

API是以源代碼爲基礎的約定,它用於軟件組件之間相互通訊的接口。API可能包含函數、數據結構、對象類、以及變量等的約定。

API可視化jquery

圖片蒙惠http://blog.zoho.comgit

簡單地講,API指的是一組應用中的函數,它們可以被其它應用(或者這些函數所屬應用本身,下文中咱們將會看到)用來與應用進行交互。API是一種很棒的向外部應用安全和妥善地代表其功能的方式,由於這些外部應用所能利用的全部功能僅限於API中所表現出的功能。github

stoneyang
stoneyang
翻譯於 8個月前

8人頂web

 

 翻譯的不錯哦!數據庫

什麼是「以API爲中心的」網絡應用?

以API爲中心的網絡應用就是基本上經過API調用執行大多數甚或全部功能的一類網絡應用。

以API爲中心的網絡應用就是基本上經過API調用執行大多數甚或全部功能的一類網絡應用。舉個例子,若是你正要登陸一個用戶,你應當將其認證信息發送給API,而後API會向你返回一個結果,說明該用戶是否提供了正確的用戶名-密碼組合。編程

以API爲中心的網絡應用的另一個特徵就是API一直是無狀態的,這意味着這種應用沒法辨別由會話發起的API調用。因爲API調用一般由後端代碼構成,實現對會話的掌控將比較困難,由於這其中一般沒有cookies介入。這種侷限事實上是好事——它「迫使」開發者建造不基於當前用戶狀態工做的API,可是相應地在功能上,它使測試易於進行,由於用戶的當前狀態無需被重建。

stoneyang
stoneyang
翻譯於 8個月前

5人頂

 

 翻譯的不錯哦!

爲何要經歷這些麻煩?

做爲Web開發者,咱們已經親眼目擊了技術的進步。有一個常識是,當代的人們不會只經過瀏覽器來使用應用,還會經過其它諸如移動電話和平板電腦之類的設備使用。舉個例子,這篇發表在Mashable上的名爲「用戶在移動應用上花的時間比在網絡上的多」的寫道:

一項新近的報告代表,用戶花在移動應用上的時間首次超過了花在網絡上的時間。 

Flurry對比了其移動數據與來自comScore和Alexa的統計數據,發如今六月,用戶天天花費81分鐘使用移動應用,而只花74分鐘用於網上衝浪。

 

這裏還有一篇來自ReadWriteWeb的更新的文章「在移動設備上瀏覽網絡的人多於使用IE6和IE7的人數總和」

來自Sitepoint的  瀏覽器趨勢的最新數據代表,在智能手機上瀏覽Web的人比使用IE6和IE7瀏覽的人更多。這兩件難有轉機的老古董多年來一直是Web開發者的噩夢,它們須要各網站儘量穩當地降格到至少經常使用瀏覽器所能支持的水平。可是如今時代不一樣了;2011年十一月中,6.95%的Web活動在移動瀏覽器上發生,而發生在IE6或IE7上的則只有6.49%。

正如咱們所見,愈來愈多的人正經過其它途徑得到訊息,特別是移動設備。

stoneyang
stoneyang
翻譯於 8個月前

2人頂

 

 翻譯的不錯哦!

這與我建立以API爲中心的網絡應用有何關係?

這必將會使咱們的應用更加有用,由於它能夠用在任何你須要的地方。

建立以API爲中心的網絡應用的主要優點之一即是它幫助你創建能夠用於任何設備的功能,瀏覽器、移動電話、甚至是桌面應用。你所須要作的就是建立的API可以使全部這些設備利用它完成通訊,而後,瞧!你將可以建造一個集中式應用,它可以接受來自用戶所使用的任何設備的輸入並執行相應的功能。

以API爲中心的應用的框圖

stoneyang
stoneyang
翻譯於 8個月前

2人頂

 

 翻譯的不錯哦!

經過以這種方式建立應用,咱們可以從容地利用不一樣的人使用不一樣的媒介這一優點。這必將使應用更加有用,由於它能用在用戶須要的任何地方。

爲了證實咱們的觀點,這裏有一篇關於Twitter的從新設計的網站的文章,文章告訴咱們他們如今如何利用他們的API來驅動Twitter.com的,實質上是使其以API爲中心:

最重要的架構改動之一就是Twitter.com如今是咱們本身API的客戶。它從終端提取數據,此終端與移動網站,咱們爲iPhone、iPad、Android,以及全部第三方應用所用端點相同。這一轉變使咱們能向API團隊分配更多的資源,同時生成了40多個補丁。在初始頁面負載和來自客戶端的每一個調用上,全部的數據如今都是從一個高度優化的JSON段緩存中獲取的。

在本篇教程中,咱們將建立一個簡單的TODO列表應用,該應用以API爲中心;還要建立一個瀏覽器上的前端客戶端,該客戶端與咱們的TODO列表應用進行交互。文末,你就能瞭解一個以API爲中心的應用的有機組成部分,同時,還能瞭解怎樣使應用和客戶端二者之間的安全通訊變得容易。記住這些,咱們開始吧!

stoneyang
stoneyang
翻譯於 8個月前

3人頂

 

 翻譯的不錯哦!

步驟 1: 規劃該應用的功能

本教程中咱們將要構建的這個 TODO 應用將會有下面幾個基本的CRUD功能:

  • 建立 TODO 條目
  • 讀取 TODO 條目
  • 更新 TODO 條目 (重命名,標記爲完成,標記爲未完成)
  • 刪除 TODO 條目

每個 TODO 條目將擁有:

  • 一個標題 Title
  • 一個截止日期 Date Due
  • 一個描述 Description
  • 一個判斷 TODO 條目是否完成的標誌 Is Done

讓咱們模擬一下該應用,使咱們考慮該應用之後會是什麼樣子時,能有有一個直觀的參考:

SimpleTODO Mockup 

簡單的TODO 模擬示例
lwei
lwei
翻譯於 8個月前

4人頂

 

 翻譯的不錯哦!

步驟 2: 建立API服務器

既然咱們是在開發一個以API爲中心的應用,咱們將建立兩個「項目」: API 服務器,和前端客戶端。 咱們首先從建立API服務器開始。

在你的web server文件夾,建立一個文件夾,命名爲simpletodo_api,而後建立一個index.php文件。這個index.php文件將做爲一個訪問API的前端控制器,因此,全部訪問API服務器的請求都會由該文件產生。打開它並往裏輸入下列代碼:

01 <?php
02 // 定義數據目錄的路徑
03 define('DATA_PATH'realpath(dirname(__FILE__).'/data'));
04  
05 //引入咱們的models
06 include_once 'models/TodoItem.php';
07  
08 //在一個try-catch塊中包含全部代碼,來捕獲全部可能的異常!
09 try {
10     //得到在POST/GET request中的全部參數
11     $params $_REQUEST;
12      
13     //獲取controller並把它正確的格式化使得第一個字母老是大寫的
14     $controller = ucfirst(strtolower($params['controller']));
15      
16     //獲取action並把它正確的格式化,使它全部的字母都是小寫的,並追加一個'Action'
17     $action strtolower($params['action']).'Action';
18  
19     //檢查controller是否存在。若是不存在,拋出異常
20     iffile_exists("controllers/{$controller}.php") ) {
21         include_once "controllers/{$controller}.php";
22     else {
23         throw new Exception('Controller is invalid.');
24     }
25      
26     //建立一個新的controller實例,並把從request中獲取的參數傳給它
27     $controller new $controller($params);
28      
29     //檢查controller中是否存在action。若是不存在,拋出異常。
30     if( method_exists($controller$action) === false ) {
31         throw new Exception('Action is invalid.');
32     }
33      
34     //執行action
35     $result['data'] = $controller->$action();
36     $result['success'] = true;
37      
38 } catch( Exception $e ) {
39     //捕獲任何一次樣而且報告問題
40     $result array();
41     $result['success'] = false;
42     $result['errormsg'] = $e->getMessage();
43 }
44  
45 //回顯調用API的結果
46 echo json_encode($result);
47 exit();

實質上,這裏咱們建立的是一個簡單的前端控制器,它實現了下列功能:

  • 接受一次擁有任意個參數的API調用
  • 爲本次API調用抽取出Controller和Action
  • 進行必要的檢查確保Controller和Action都存在
  • 執行API調用
  • 捕獲異常,若是有的話
  • 返回一個結果給調用者
lwei
lwei
翻譯於 8個月前

3人頂

 

 翻譯的不錯哦!

除了須要建立index.php外你還須要建立三個文件夾:   controllersmodels 和   data.
API server folders
  • controllers  文件夾存放的是全部咱們API服務器將會用到的的控制器。咱們用MVC架構來使API服務器結構更清楚合理。
  • models 文件夾存放全部API服務器要用到的數據模型。
  • data 文件夾將會用來保存API服務器的任何數據。

在controllers文件夾下建立一個叫Todo.php的文件。這將是任何TODO列表有關任務的控制器。按照TODO應用所需提供的功能,向Todo控制器裏面添加必要的方法:

01 <?php
02 class Todo
03 {
04     private $_params;
05      
06     public function __construct($params)
07     {
08         $this->_params = $params;
09     }
10      
11     public function createAction()
12     {
13         //create a new todo item
14     }
15      
16     public function readAction()
17     {
18         //read all the todo items
19     }
20      
21     public function updateAction()
22     {
23         //update a todo item
24     }
25      
26     public function deleteAction()
27     {
28         //delete a todo item
29     }
30 }

如今爲每一個action中添加必要的功能實現。我將會提供createAction()方法的源碼,其餘方法將留做做業。若是你以爲毫無頭緒,你也能夠下載示例的源碼,從那裏拷貝。

01 public function createAction()
02 {
03     //create a new todo item
04     $todo new TodoItem();
05     $todo->title = $this->_params['title'];
06     $todo->description = $this->_params['description'];
07     $todo->due_date = $this->_params['due_date'];
08     $todo->is_done = 'false';
09      
10     //pass the user's username and password to authenticate the user
11     $todo->save($this->_params['username'], $this->_params['userpass']);
12      
13     //return the todo item in array format
14     return $todo->toArray();
15 }
bigtiger02
bigtiger02
翻譯於 8個月前

3人頂

 

 翻譯的不錯哦!

在文件夾models下建立TodoItem.php,這樣咱們就能夠建立「條目添加」的代碼了。注意:我並無和數據庫進行鏈接,相反我將信息保存到文件中,雖然這能夠用任何數據庫來實現,可是  這樣作相對來講要容易些
01 <?php
02 class TodoItem
03 {
04     public $todo_id;
05     public $title;
06     public $description;
07     public $due_date;
08     public $is_done;
09      
10     public function save($username$userpass)
11     {
12         //get the username/password hash
13         $userhash = sha1("{$username}_{$userpass}");
14         ifis_dir(DATA_PATH."/{$userhash}") === false ) {
15             mkdir(DATA_PATH."/{$userhash}");
16         }
17          
18         //if the $todo_id isn't set yet, it means we need to create a new todo item
19         ifis_null($this->todo_id) || !is_numeric($this->todo_id) ) {
20             //the todo id is the current time
21             $this->todo_id = time();
22         }
23          
24         //get the array version of this todo item
25         $todo_item_array $this->toArray();
26          
27         //save the serialized array version into a file
28         $successfile_put_contents(DATA_PATH."/{$userhash}/{$this->todo_id}.txt", serialize($todo_item_array));
29          
30         //if saving was not successful, throw an exception
31         if$success === false ) {
32             throw new Exception('Failed to save todo item');
33         }
34          
35         //return the array version
36         return $todo_item_array;
37     }
38      
39     public function toArray()
40     {
41         //return an array version of the todo item
42         return array(
43             'todo_id' => $this->todo_id,
44             'title' => $this->title,
45             'description' => $this->description,
46             'due_date' => $this->due_date,
47             'is_done' => $this->is_done
48         );
49     }
50 }

createAction方法使用到TodoItem模型裏面兩個方法:

  • save() – 該方法將TodoItem保存到一個文件中,若有必要,須要設置todo_id。
  • toArray() – 該方法返回一個以變量爲索引的數組Todo條目。

因爲API須要經過HTTP請求調用,在瀏覽器輸入以下地址測試API:

http://localhost/simpletodo_api/?controller=todo&action=create&title=test%20title&description=test%20description&due_date=12/08/2011&username=nikko&userpass=test1234

若是沒有錯,你應該在data文件夾下看到一個新的文件夾,在該文件夾裏面有一個文件,文件內容以下:

createAction() result 

createAction()結果

恭喜!您已經成功建立了一個的API服務器和API調用!

bigtiger02
bigtiger02
翻譯於 8個月前

4人頂

 

 翻譯的不錯哦!

步驟3:確保API服務器具備APP ID和APP SECRET

目前,API服務器被設置爲接受所有API請求。咱們將須要將之限制在咱們本身的應用上,以確保只有咱們本身的前端客戶端可以完成API請求。另外,你實際上也能夠建立一個系統,其中的用戶能夠建立他們本身的應用,而那些應用也用用對你的API服務器的訪問權,這與Facebook和Twitter的應用的的工做原理相似。

咱們從爲使用API服務器的用戶建立一組id-密碼對開始。因爲這只是一個Demo,咱們可使用任何隨機的、32位字符串。對於APP ID,咱們將其設定爲APP001

再次打開index.php文件,而後用下列代碼更新之:

01 <?php
02 // Define path to data folder
03 define('DATA_PATH'realpath(dirname(__FILE__).'/data'));
04  
05 //Define our id-key pairs
06 $applications array(
07     'APP001'=> '28e336ac6c9423d946ba02d19c6a2632'//randomly generated app key
08 );
09 //include our models
10 include_once 'models/TodoItem.php';
11  
12 //wrap the whole thing in a try-catch block to catch any wayward exceptions!
13 try {
14     //*UPDATED*
15     //get the encrypted request
16     $enc_request $_REQUEST['enc_request'];
17      
18     //get the provided app id
19     $app_id $_REQUEST['app_id'];
20      
21     //check first if the app id exists in the list of applications
22     if( !isset($applications[$app_id]) ) {
23         throw new Exception('Application does not exist!');
24     }
25      
26     //decrypt the request
27     $params= json_decode(trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $applications[$app_id], base64_decode($enc_request), MCRYPT_MODE_ECB)));
28      
29     //check if the request is valid by checking if it's an array and looking for the controller and action
30     if$params== false || isset($params->controller) == false || isset($params->action) == false ) {
31         throw new Exception('Request is not valid');
32     }
33      
34     //cast it into an array
35     $params = (array$params;
36     ...
37     ...
38     ...
stoneyang
stoneyang
翻譯於 8個月前

4人頂

 

 翻譯的不錯哦!

咱們在這裏已經完成的其實是實現一個很是簡單的認證咱們的前端客戶端的方法,它利用了與公共-私有密鑰認證類似的系統。基本上,這裏給出的就是認證過程的步驟分解:

公鑰加密

  • 完成一個API調用,其中提供了$app_id$enc_request
  • $enc_request的值是API調用的參數,利用APP KEY進行加密。APP KEY絕對不會被髮送到服務器,它只是被用來散列請求。此外,該請求只能利用APP KEY被解密
  • 一旦API調用到達API服務器,它會查驗它本身的應用列表是否與APP ID所提供的一致
  • 當調用被發現,API服務器嘗試利用與APP ID發送的密鑰相匹配的密鑰進行解密
  • 若是請求被解密成功,那麼繼續執行程序

既然API服務器已經確保具備APP ID和APP SECRET,那麼咱們就能夠開始編寫使用API服務器的前端客戶端了。

stoneyang
stoneyang
翻譯於 8個月前

2人頂

 

 翻譯的不錯哦!

步驟4:建立瀏覽器客戶端

咱們從爲前端客戶端設定新建文件夾開始。在你的Web服務器上的文件夾中建立一個名爲simpletodo_client_browser的文件夾。完成後,建立一個index.php文件,並將下列代碼寫進去:

01 <!DOCTYPE html>
02 <html>
03 <head>
04     <title>SimpleTODO</title>
05      
06     <link rel="stylesheet" href="css/reset.css" type="text/css" />
07     <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
08      
09     <script src="js/jquery.min.js"></script>
10     <script src="js/jquery-ui-1.8.16.custom.min.js"></script>
11      
12     <style>
13     body {
14         padding-top: 40px;
15     }
16     #main {
17         margin-top: 80px;
18         text-align: center;
19     }
20     </style>
21 </head>
22 <body>
23     <div class="topbar">
24         <div class="fill">
25             <div class="container">
26                 <a class="brand" href="index.php">SimpleTODO</a>
27             </div>
28         </div>
29     </div>
30     <div id="main" class="container">
31         <form class="form-stacked" method="POST" action="login.php">
32             <div class="row">
33                 <div class="span5 offset5">
34                     <label for="login_username">Username:</label>
35                     <input type="text" id="login_username" name="login_username"placeholder="username" />
36                  
37                     <label for="login_password">Password:</label>
38                     <input type="password" id="login_password" name="login_password"placeholder="password" />
39                      
40                 </div>
41             </div>
42             <div class="actions">
43                 <button type="submit" name="login_submit" class="btn primary large">Login orRegister</button>
44             </div>
45         </form>
46     </div>
47 </body>
48 </html>
這段代碼的運行結果看起來就像這樣:

SimpleTODO的登陸頁

須要注意的是我在這裏已經包含了兩個JavaScript文件和兩個CSS文件:

接下來,咱們建立login.php文件來存儲客戶端會話中的用戶名和密碼。

1 <?php
2 //get the form values
3 $username $_POST['login_username'];
4 $userpass $_POST['login_password'];
5 session_start();
6 $_SESSION['username'] = $username;
7 $_SESSION['userpass'] = $userpass;
8 header('Location: todo.php');
9 exit();

這裏,咱們簡單地爲用戶開啓一次會話,所依據的是用戶所提供的用戶名和密碼組合。這充當了簡單的組合密鑰,它容許用戶訪問某個特定用戶名和密碼組合所存儲的TODO項。而後咱們重定向至todo.php,那裏是咱們開始與API服務器交互的地方。然而在咱們開始編寫todo.php文件以前,先建立一個 ApiCaller類,它將封裝咱們所需的所有API調用方法,包括請求的加密。

建立apicaller.php,並把下面的代碼寫進去:

01 <?php
02 class ApiCaller
03 {
04     //some variables for the object
05     private $_app_id;
06     private $_app_key;
07     private $_api_url;
08      
09     //construct an ApiCaller object, taking an
10     //APP ID, APP KEY and API URL parameter
11     public function __construct($app_id$app_key$api_url)
12     {
13         $this->_app_id = $app_id;
14         $this->_app_key = $app_key;
15         $this->_api_url = $api_url;
16     }
17      
18     //send the request to the API server
19     //also encrypts the request, then checks
20     //if the results are valid
21     public function sendRequest($request_params)
22     {
23         //encrypt the request parameters
24         $enc_requestbase64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->_app_key, json_encode($request_params), MCRYPT_MODE_ECB));
25          
26         //create the params array, which will
27         //be the POST parameters
28         $params array();
29         $params['enc_request'] = $enc_request;
30         $params['app_id'] = $this->_app_id;
31          
32         //initialize and setup the curl handler
33         $ch = curl_init();
34         curl_setopt($ch, CURLOPT_URL, $this->_api_url);
35         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
36         curl_setopt($ch, CURLOPT_POST, count($params));
37         curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
38  
39         //execute the request
40         $result = curl_exec($ch);
41          
42         //json_decode the result
43         $result = @json_decode($result);
44          
45         //check if we're able to json_decode the result correctly
46         if$result == false || isset($result['success']) == false ) {
47             throw new Exception('Request was not correct');
48         }
49          
50         //if there was an error in the request, throw an exception
51         if$result['success'] == false ) {
52             throw new Exception($result['errormsg']);
53         }
54          
55         //if everything went great, return the data
56         return $result['data'];
57     }
58 }
stoneyang
stoneyang
翻譯於 8個月前

1人頂

 

 翻譯的不錯哦!

咱們將利用ApiCaller類向咱們的API服務器發送請求。這樣,全部必需的加密和cURL初始化代碼將會寫在一個地方,咱們就不用重複代碼了。

  • __construct函數接受三個參數:
  1. $app_id——客戶端的APP ID(瀏覽器端是APP001
  2. $app_key——客戶端的APP KEY(瀏覽器端是28e336ac6c9423d946ba02d19c6a2632
  3. $api_url——API服務器的URL,此處爲http://localhost/simpletodo_api/
  • sendRequest()函數:
  1. 利用mcrypt庫以API服務對其解密的一樣方式來對請求參數進行加密
  2. 生成發往API服務器的$_POST參數
  3. 經過cURL執行API調用
  4. 查驗API調用的結果是否正確
  5. 當一切都按計劃進行的時候返回數據

如今,咱們開始寫todo.php。首先,咱們建立一些代碼來爲密碼爲test1234的用戶nikko(這是咱們先前用來測試API服務器的那個用戶名/密碼組合)獲取當前的todo項。

01 <?php
02 session_start();
03 include_once 'apicaller.php';
04  
05 $apicaller newApiCaller('APP001''28e336ac6c9423d946ba02d19c6a2632''http://localhost/simpletodo_api/');
06  
07 $todo_items $apicaller->sendRequest(array(
08     'controller' => 'todo',
09     'action' => 'read',
10     'username' => $_SESSION['username'],
11     'userpass' => $_SESSION['userpass']
12 ));
13  
14 echo '';
15 var_dump($todo_items);
打開index.php,以nikko/tes1234登陸,而後你應該看到咱們先前建立的TODO項的avar_dump()。

恭喜,你已經成功地作好了一個向API服務器的API調用!在這段代碼中,咱們已經:

  • 開啓會話,使咱們擁有了對$_SESSION中的username以及userpass的訪問權
  • 實例化了一個新的ApiCaller類,爲其提供了APP ID,APP KEY,以及API服務器的URL
  • 經過sendRequest()方法發送了一個請求
stoneyang
stoneyang
翻譯於 8個月前

2人頂

 

 翻譯的不錯哦!

如今,咱們來從新格式化一下數據,讓它們開起來更好看些。向todo.php中添加下列HTML。別忘了移去var_dump()!

001 <!DOCTYPE html>
002 <html>
003 <head>
004     <title>SimpleTODO</title>
005      
006     <link rel="stylesheet" href="css/reset.css" type="text/css" />
007     <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
008     <link rel="stylesheet" href="css/flick/jquery-ui-1.8.16.custom.css" type="text/css" />
009      
010     <script src="js/jquery.min.js"></script>
011     <script src="js/jquery-ui-1.8.16.custom.min.js"></script>
012      
013     <style>
014     body {
015         padding-top: 40px;
016     }
017     #main {
018         margin-top: 80px;
019     }
020      
021     .textalignright {
022         text-align: right;
023     }
024      
025     .marginbottom10 {
026         margin-bottom: 10px;
027     }
028     #newtodo_window {
029         text-align: left;
030         display: none;
031     }
032     </style>
033      
034     <script>
035     $(document).ready(function() {
036         $("#todolist").accordion({
037             collapsible: true
038         });
039         $(".datepicker").datepicker();
040         $('#newtodo_window').dialog({
041             autoOpen: false,
042             height: 'auto',
043             width: 'auto',
044             modal: true
045         });
046         $('#newtodo').click(function() {
047             $('#newtodo_window').dialog('open');
048         });
049     });
050     </script>
051 </head>
052 <body>
053     <div class="topbar">
054         <div class="fill">
055             <div class="container">
056                 <a class="brand" href="index.php">SimpleTODO</a>
057             </div>
058         </div>
059     </div>
060     <div id="main" class="container">
061         <div class="textalignright marginbottom10">
062             <span id="newtodo" class="btn info">Create a new TODO item</span>
063             <div id="newtodo_window" title="Create a new TODO item">
064                 <form method="POST" action="new_todo.php">
065                     <p>Title:<br /><input type="text" class="title" name="title"placeholder="TODO title" /></p>
066                     <p>Date Due:<br /><input type="text" class="datepicker" name="due_date"placeholder="MM/DD/YYYY" /></p>
067                     <p>Description:<br /><textarea class="description"name="description"></textarea></p>
068                     <div class="actions">
069                         <input type="submit" value="Create" name="new_submit" class="btn primary"/>
070                     </div>
071                 </form>
072             </div>
073         </div>
074         <div id="todolist">
075             <?php foreach($todo_items as $todo): ?>
076             <h3><a href="#"><?php echo $todo->title; ?></a></h3>
077             <div>
078                 <form method="POST" action="update_todo.php">
079                 <div class="textalignright">
080                     <a href="delete_todo.php?todo_id=<?php echo $todo->todo_id; ?>">Delete</a>
081                 </div>
082                 <div>
083                     <p>Date Due:<br /><input type="text"id="datepicker_<?php echo $todo->todo_id; ?>" class="datepicker" name="due_date" value="12/09/2011" /></p>
084                     <p>Description:<br /><textarea class="span8"id="description_<?php echo $todo->todo_id; ?>" class="description" name="description"><?phpecho $todo->description; ?></textarea></p>
085                 </div>
086                 <div class="textalignright">
087                     <?php if( $todo->is_done == 'false' ): ?>
088                     <input type="hidden" value="false" name="is_done" />
089                     <input type="submit" class="btn" value="Mark as Done?" name="markasdone_button"/>
090                     <?php else: ?>
091                     <input type="hidden" value="true" name="is_done" />
092                     <input type="button" class="btn success" value="Done!" name="done_button" />
093                     <?php endif; ?>
094                     <input type="hidden" value="<?php echo $todo->todo_id; ?>" name="todo_id" />
095                     <input type="hidden" value="<?php echo $todo->title; ?>" name="title" />
096                     <input type="submit" class="btn primary" value="Save Changes"name="update_button" />
097                 </div>
098                 </form>
099             </div>
100             <?php endforeach; ?>
101         </div>
102     </div>
103 </body>
104 </html>
這段代碼的運行結果以下:

很酷哈?但它目前啥也幹不了,那麼讓咱們開始添加一些功能吧。我將爲new_todo.php提供代碼,它們調用todo/createAPI調用來建立新的TODO項。建立其餘頁(update_todo.php和delete_todo.php)應該與此十分類似,所以我把它們留給你。打開new_todo.php,而後把下面的代碼添進去:

01 <?php
02 session_start();
03 include_once 'apicaller.php';
04  
05 $apicaller newApiCaller('APP001''28e336ac6c9423d946ba02d19c6a2632''http://localhost/simpletodo_api/');
06  
07 $new_item $apicaller->sendRequest(array(
08     'controller' => 'todo',
09     'action' => 'create',
10     'title' => $_POST['title'],
11     'due_date' => $_POST['due_date'],
12     'description' => $_POST['description'],
13     'username' => $_SESSION['username'],
14     'userpass' => $_SESSION['userpass']
15 ));
16  
17 header('Location: todo.php');
18 exit();
19 ?>
正如你所看到的,new_todo.php頁再次使用了ApiCaller調用來簡化向API服務器所發送的  todo/create請求。這主要完成了與以前相同的事情:
  • 開啓一個會話,以使其得到對存儲於$_SESSION中的$username和$userpass的訪問權
  • 實例化一個新的ApiCaller類,爲它提供APP ID, APP KEY,以及API服務器的URL
  • 經過sendRequest()方法發送請求
  • 重定向回todo.php

恭喜,它好用了!你已經成功地建立了一個以API爲中心的應用!

stoneyang
stoneyang
翻譯於 8個月前

2人頂

 

 翻譯的不錯哦!

結論

圍繞API建立並開發應用具備如此之多的優點。想建立一個Android版的SimpleTODO?你須要的全部功能都已經在API服務器上了,因此你所要作的就是建立客戶端!想重構或者優化某些類?沒問題——只要確保輸出相同便可。想添加更多的功能?你能夠在不影響任何客戶端代碼的前提下作到!

儘管存在着某些像是更長的開發時間或者更加複雜,可是以這種方式開發網絡應用的優點卻遠比其劣勢更重要。今天的這種開發由咱們本身權衡取捨,從而使咱們可以在未來獲益。

你是準備使用一臺API服務器做爲你的下一個Web應用,仍是已經在過去的項目中使用了相同的技術?請在評論中告知!

相關文章
相關標籤/搜索