REST介紹與REST在PHP中的應用

當HTTP被髮明出來的時候,其實REST就已經存在了。惋惜這麼多年來,WEB開發模式卻愈來愈背離HTTP的本質,捨本逐末的追求起RPC之類的東西。此時REST從新回到人們的視線裏,無疑讓你們開始反思過去走過的彎路。php

本文並不想從頭介紹REST,只是想舉例說明一下須要注意的問題:數據庫

先來看看人們對REST的困惑:瀏覽器

REST什麼樣子?

最通常的REST例子,相似下面的樣子:安全

1 POST   /articles     建立
2 DELETE /articles/123 刪除
3 PUT    /articles/123 更新或建立
4 GET    /articles/123 查看

順便說說幾個知識點:服務器

GET操做是安全的。所謂安全是指無論進行多少次操做,資源的狀態都不會改變。好比我用GET瀏覽文章,無論瀏覽多少次,那篇文章還在那,沒有 變化。固然,你可能說每瀏覽一次文章,文章的瀏覽數就加一,這不也改變了資源的狀態麼?這並不矛盾,由於這個改變不是GET操做引發的,而是用戶本身設定 的服務端邏輯形成的。架構

PUT,DELETE操做是冪等的。所謂冪等是指無論進行多少次操做,結果都同樣。好比我用PUT修改一篇文章,而後在作一樣的操做,每次操做後的結果並無不一樣,DELETE也是同樣。順便說一句,由於GET操做是安全的,因此它天然也是冪等的。ui

POST操做既不是安全的,也不是冪等的,好比常見的POST重複加載問題:當咱們屢次發出一樣的POST請求後,其結果是建立出了若干的資源。this

安全和冪等的意義在於:當操做沒有達到預期的目標時,咱們能夠不停的重試,而不會對資源產生反作用。從這個意義上說,POST操做每每是有害的,但不少時候咱們仍是不得不使用它。spa

還有一點須要注意的就是,建立操做可使用POST,也可使用PUT,區別在於POST是做用在一個集合資源之上的(/articles), 而PUT操做是做用在一個具體資源之上的(/articles/123),再通俗點說,若是URL能夠在客戶端肯定,那麼就使用PUT,若是是在服務端確 定,那麼就使用POST,好比說不少資源使用數據庫自增主鍵做爲標識信息,而建立的資源的標識信息究竟是什麼只能由服務端提供,這個時候就必須使用 POST。設計

瀏覽器不支持PUT/DELETE方法怎麼辦?

大部分瀏覽器只支持GET/POST方法,這使得咱們沒法完美的實現REST。對於這樣的狀況,大體有幾種解決方法,一種是在表單里加入一個 _method之類名字的隱藏字段,用於表示真正的方法,另外一種是使用X-HTTP-METHOD-OVERRIDE頭信息來重載POST。

HTTP方法夠用麼?

從上面的例子,咱們能夠看到,經過使用已有的HTTP方法:POST,DELETE,PUT,GET就能夠完成資源的增刪改查,但在實際狀況 中,咱們須要作的操做每每並不只僅侷限在簡單的增刪改查操做中,好比說咱們要把一篇文章「置頂」,可是HTTP方法裏沒有一個和「置頂」操做相對應的方 法,這時候該怎麼辦呢?REST對相似問題的解決方案是:建立一個新的資源!在上面的例子裏,咱們能夠這樣:

1 PUT /toparticles/123

經過建立出一個新的資源(toparticles),咱們就可使用簡單的HTTP方法通吃一切操做了。

REST反對使用Session麼?

牢記一點,REST拒絕Session!這是由於REST強調無狀態性。這裏的狀態指的的應用狀態,也能夠稱之爲會話狀態。一旦在服務端保持了這樣的狀態,那麼架構的可擴展性將大打折扣。在REST看來,任何相似的狀態自己都應該是一個獨立的資源。

Cookie對REST有害麼?

一分爲二的看,若是Cookie裏保存的是應用狀態的話,就沒有問題。由於應用狀態原本就屬於客戶端。但若是使用Cookie保存相似PHPSESSIONID之類的東西就不對了,由於這樣的數據並不屬於客戶端狀態,它只不過是使用Session的藉口而已。

再來看看REST在PHP中的現狀:

PHP裏的REST實現案例很少,有點影響都就是CakePHP和Zend,下面分別看看他們的實現:

CakePHP:

設定路由:

1 Router::parseExtensions('xml');
2 Router::mapResources('articles');

編寫控制器:

1 class ArticlesController extends AppController {
2     var $components = array('RequestHandler');
3     function view($id = null) {
4         $article = $this->Article->findById($id);
5         $this->set(compact('article'));
6     }
7     // ...
8 }

視圖:

1 <articles>
2 <?php echo $xml->serialize($article); ?>
3 </articles>

差很少就這樣了,相應的,還能夠實現其餘的功能,因而,以下REST操做便成爲可能:

1 POST   /articles
2 DELETE /articles/123.xml
3 PUT    /articles/123.xml
4 GET    /articles/123.xml

整體看,CakePHP的REST實現基本上是按Rails風格來實現的,大致還過得去。

ZendFramework:

ZendFramework經過Zend_Rest組件來實現Rest功能:

服務端:

1 require_once 'Zend/Rest/Server.php';
2 function sayHello($who, $when)
3 {
4     return "Hello $who, Good $when";
5 }
6 $server = new Zend_Rest_Server();
7 $server->addFunction('sayHello');
8 $server->handle();

客戶端:

1 require_once 'Zend/Rest/Client.php';
2 $client = new Zend_Rest_Client('http://path/to/server/script');
3 $client->sayHello('Davey', 'Day');
4      
5 echo $client->get();

這時候,咱們看一下Web服務器的日誌,會發現生成了一條以下的記錄:

1 GET /path/to/servier/script?method=sayHello&arg0=Davey&arg1=Day&rest=1 HTTP/1.1

咱們發現,實際操做方法是由URL中的method=sayHello指定的,而HTTP固有方法(GET/POST等)則成爲了擺設,這是典 型的RPC風格,若是你們對比Zend_Rest和Zend_XmlRpc文檔的話,會明顯發現它們根本就是一個東西,因此說,Zend_Rest是一個 REST僞實現。

這個基本 REST 設計原則創建了建立、讀取、更新和刪除(create, read, update, and delete,CRUD)操做與 HTTP 方法之間的一對一映射。 根據此映射: 1)若要在服務器上建立資源,應該使用 POST 方法。 2)若要檢索某個資源,應該使用 GET 方法。 3)若要更改資源狀態或對其進行更新,應該使用 PUT 方法。 4)若要刪除某個資源,應該使用 DELETE 方法。

相關文章
相關標籤/搜索