# RESTFul
[上一頁](# "上一頁")[下一頁](# "下一頁")
### REST介紹
REST(Representational State Transfer表述性狀態轉移)是一種針對網絡應用的設計和開發方式,可以降低開發的復雜性,提高系統的可伸縮性。REST提出了一些設計概念和準則:
1、網絡上的所有事物都被抽象為資源(resource);
2、每個資源對應一個唯一的資源標識(resource identifier);
3、通過通用的連接器接口(generic connector interface)對資源進行操作;
4、對資源的各種操作不會改變資源標識;
5、所有的操作都是無狀態的(stateless)。
需要注意的是,REST是設計風格而不是標準。REST通常基于使用HTTP,URI,和XML以及HTML這些現有的廣泛流行的協議和標準。
傳統的請求模式和REST模式的請求模式區別:
| 作用 | 傳統模式 | REST模式 |
|-----|-----|-----|
| 列舉出所有的用戶 | GET /users/list | GET /users |
| 列出ID為1的用戶信息 | GET /users/show/id/1 | GET /users/1 |
| 插入一個新的用戶 | POST /users/add | POST /users |
| 更新ID為1的用戶信息 | POST /users/mdy/id/1 | PUT /users/1 |
| 刪除ID為1的用戶 | POST /users/delete/id/1 | DELETE /users/1 |
關于更多的REST信息,可以參考:[http://zh.wikipedia.org/wiki/REST](http://zh.wikipedia.org/wiki/REST)
### RESTFul支持
3.2的RESTFul支持更為靈活,你不需要使用REST模式,只需要把控制器繼承Think\Controller\RestController即可。繼承RestController控制器后你的訪問控制器就可以支持下面的一些功能:
- 支持資源類型自動檢測;
- 支持請求類型自動檢測;
- RESTFul方法支持;
- 可以設置允許的請求類型列表;
- 可以設置允許請求和輸出的資源類型;
- 可以設置默認請求類型和默認資源類型;
例如:
~~~
namespace Home\Controller;
use Think\Controller\RestController;
class BlogController extends RestController{
}
~~~
### REST參數
繼承了RestController后,你可以在你的控制器里面設置rest相關的屬性參數,包括:allowMethod,defaultMethod,allowType,defaultType以及allowOutputType。
| 屬性名 | 說明 | 默認值 |
|-----|-----|-----|
| allowMethod | REST允許的請求類型列表 | array('get','post','put','delete') |
| defaultMethod | REST默認請求類型 | get |
| allowType | REST允許請求的資源類型列表 | array('html','xml','json','rss') |
| defaultType | REST默認的資源類型 | html |
| allowOutputType | REST允許輸出的資源類型列表 | array( 'xml' => 'application/xml', 'json' => 'application/json','html' => 'text/html',) |
### REST方法
RESTFul方法的操作方法定義主要區別在于,需要對請求類型和資源類型進行判斷,大多數情況下,通過路由定義可以把操作方法綁定到某個請求類型和資源類型。如果你沒有定義路由的話,需要自己在操作方法里面添加判斷代碼,示例:
~~~
namespace Home\Controller;
use Think\Controller\RestController;
Class InfoController extends RestController {
Public function rest() {
switch ($this->_method){
case 'get': // get請求處理代碼
if ($this->_type == 'html'){
}elseif($this->_type == 'xml'){
}
break;
case 'put': // put請求處理代碼
break;
case 'post': // post請求處理代碼
break;
}
}
}
~~~
> 在Rest操作方法中,可以使用$this->_type獲取當前訪問的資源類型,用$this->_method獲取當前的請求類型。
REST控制器類還提供了response方法用于REST輸出:用法如下:
~~~
$this->response($data,'json');
~~~
Response方法會自動對data數據進行輸出類型編碼,目前支持的包括`xml/json/html`。
除了普通方式定義Restful操作方法外,系統還支持另外一種自動調用方式,就是根據當前請求類型和資源類型自動調用相關操作方法。系統的自動調用規則是:
| 定義規范 | 說明 |
|-----|-----|
| 操作名*提交類型*資源后綴 | 標準的Restful方法定義,例如 read_get_pdf |
| 操作名_資源后綴 | 當前提交類型和defaultMethod屬性相同的時候,例如read_pdf |
| 操作名_提交類型 | 當前資源后綴和defaultType屬性相同的時候,例如read_post |
要使用這種方式的前提就是不能為當前操作定義方法,這樣在空操作的檢查之前系統會首先按照上面的定義規范順序檢查是否存在方法定義,如果檢測到相關的restful方法則不再檢查后面的方法規范,例如我們定義了InfoController如下:
~~~
namespace Home\Controller;
use Think\Controller\RestController;
Class InfoController extends RestController {
protected $allowMethod = array('get','post','put'), // REST允許的請求類型列表
protected $allowType = array('html','xml','json'), // REST允許請求的資源類型列表
Public function read_get_html(){
// 輸出id為1的Info的html頁面
}
Public function read_get_xml(){
// 輸出id為1的Info的XML數據
}
Public function read_xml(){
// 輸出id為1的Info的XML數據
}
Public function read_json(){
// 輸出id為1的Info的json數據
}
}
~~~
如果我們訪問的URL是:
~~~
http://www.domain.com/Info/read/id/1.xml
~~~
假設我們沒有定義路由,這樣訪問的是Info控制器的read操作,那么上面的請求會調用InfoController類的 `read_get_xml`方法,而不是`read_xml`方法,但是如果訪問的URL是:
~~~
http://www.domain.com/Info/read/id/1.json
~~~
那么則會調用read_json方法。
如果我們訪問的URL是
~~~
http://www.domain.com/Info/read/id/1.rss
~~~
由于我們不允許rss資源類型的訪問,所以,調用的方法其實是read_html方法。
### REST路由
我們可以借助3.2的路由參數功能,來解決REST的路由定義問題。例如,
~~~
'blog/:id'=>array('blog/read','status=1',array('ext'=>'xml','method'=>'get')),
~~~
上面的路由定義,把blog/5路由到了blog/read/id/5 并且,約束了后綴是xml 請求類型是get。我們還可以定義其他的路由參數,例如:
~~~
'blog/:id'=>array('blog/update','',array('ext'=>'xml','method'=>'put')),
~~~
為了確保定義不沖突,REST路由定義我們通常改成下面的定義方式:
~~~
array('blog/:id','blog/read','status=1',array('ext'=>'xml','method'=>'get')),
array('blog/:id','blog/update','',array('ext'=>'xml','method'=>'put')),
~~~
> 這樣就可以給相同的路由規則定義不同的參數支持。定義了REST路由后,你的rest方法定義就不受任何約束,當然,如果路由定義的操作方法不存在的時候,系統默認的rest方法規范仍然會有效。
[上一頁](# "上一頁")[下一頁](# "下一頁")
- 序言
- 基礎
- 獲取ThinkPHP
- 環境要求
- 目錄結構
- 入口文件
- 自動生成
- 模塊
- 控制器
- 開發規范
- 配置
- 配置格式
- 配置加載
- 讀取配置
- 動態配置
- 擴展配置
- 批量配置
- 架構
- 模塊化設計
- URL模式
- 多層MVC
- CBD模式
- 命名空間
- 自動加載
- 應用模式
- 項目編譯
- 系統流程
- 路由
- 路由定義
- 規則路由
- 正則路由
- 靜態路由
- 閉包支持
- 實例說明
- 控制器
- 控制器定義
- 前置和后置操作
- Action參數綁定
- 偽靜態
- URL大小寫
- URL生成
- AJAX返回
- 跳轉和重定向
- 輸入變量
- 請求類型
- 空操作
- 空控制器
- 操作綁定到類
- 模型
- 模型定義
- 模型實例化
- 字段定義
- 連接數據庫
- 切換數據庫
- 分布式數據庫支持
- 連貫操作
- WHERE
- TABLE
- ALIAS
- DATA
- FIELD
- ORDER
- LIMIT
- PAGE
- GROUP
- HAVING
- JOIN
- UNION
- DISTINCT
- LOCK
- CACHE
- COMMENT
- RELATION
- 命名范圍
- CURD操作
- 數據創建
- 數據寫入
- 數據讀取
- 數據更新
- 數據刪除
- ActiveRecord
- 字段映射
- 查詢語言
- 查詢方式
- 表達式查詢
- 快捷查詢
- 區間查詢
- 組合查詢
- 統計查詢
- SQL查詢
- 動態查詢
- 子查詢
- 自動驗證
- 自動完成
- 參數綁定
- 虛擬模型
- 模型分層
- 視圖模型
- 關聯模型
- 高級模型
- Mongo模型
- 視圖
- 模板定義
- 模板主題
- 模板賦值
- 模板渲染
- 獲取模板地址
- 獲取內容
- 模板引擎
- 模板
- 變量輸出
- 系統變量
- 使用函數
- 默認值輸出
- 使用運算符
- 標簽庫
- 模板繼承
- 修改定界符
- 三元運算
- 包含文件
- 內置標簽
- Volist標簽
- Foreach標簽
- For標簽
- Switch標簽
- 比較標簽
- 范圍判斷標簽
- IF標簽
- Present標簽
- Empty標簽
- Defined標簽
- Assign標簽
- Define標簽
- 標簽嵌套
- import標簽
- 使用PHP代碼
- 原樣輸出
- 模板注釋
- 模板布局
- 模板替換
- 調試
- 調試模式
- 異常處理
- 日志記錄
- 頁面Trace
- Trace方法
- 變量調試
- 性能調試
- 錯誤調試
- 模型調試
- 緩存
- 數據緩存
- 快速緩存
- 查詢緩存
- SQL解析緩存
- 靜態緩存
- 安全
- 輸入過濾
- 表單合法性檢測
- 表單令牌
- 防止SQL注入
- 目錄安全文件
- 保護模板文件
- 上傳安全
- 防止XSS攻擊
- 其他安全建議
- 擴展
- 類庫擴展
- 驅動擴展
- 緩存驅動
- 數據庫驅動
- 日志驅動
- Session驅動
- 存儲驅動
- 模板引擎驅動
- 標簽庫驅動
- 行為擴展
- 標簽擴展
- Widget擴展
- 應用模式
- 部署
- PATH_INFO支持
- URL重寫
- 模塊部署
- 域名部署
- 入口綁定
- 替換入口
- 專題
- SESSION支持
- Cookie支持
- 多語言支持
- 數據分頁
- 文件上傳
- 驗證碼
- 圖像處理
- RESTFul
- RPC
- SAE
- IP獲取和定位
- 附錄
- 常量參考
- 配置參考
- 升級指導
- 更新日志
- 鳴謝
- 關于