2011-04-29 20 views
3

我正在使用zend框架構建應用程序。Zend框架Restful webserive邏輯使用

問題是,如何在非REST應用程序中使用Zend_Rest_Controller的相同控制器邏輯。

例如,假設twitter是用Zend Framework編寫的。他們可能會使用Zend_Rest_controller和Route來獲取他們的API。但是,他們將用於他們的網站(顯然使用相同的API邏輯)?他們會編寫一個簡單地啓動REST請求的全新應用程序嗎?那不是超負荷嗎?

[編輯]
如果Web應用程序通過一些http_client類調用API來獲取數據,這使得另一個請求到服務器(它會導致性能下降,減緩響應)。我不想再發出一個請求,並希望使用API​​中的相同業務邏輯。

感謝,
VENU

+0

@ Venu Gopal T親愛的接受他人提出的問題。通過點擊每個答案 – 2011-04-29 12:08:22

+0

ha的勾號標記,對!謝謝 – Venu 2011-04-29 12:10:34

回答

2

新答案:

我想出了一個似乎很好的模式。它解決了您所有的擔憂: 這裏是我想出的縮小版本:

首先,我們需要我們自己的控制器。這個控制器將有一個服務,通過它代理服務的任何行動請求,如果他們沒有定義:

abstract class App_Rest_Controller extends Zend_Controller_Action 
{ 
    /** 
    * @var App_Rest_Service_Abstract 
    */ 
    protected $_service; 

    public function __call($methodName, $args) 
    { 
     if ('Action' == substr($methodName, -6)) { 
      $action = substr($methodName, 0, strlen($methodName) - 6); 
      return $this->_service()->$action(); 
     } 

     return parent::__call($methodName, $args); 
    } 
} 

現在它的時間爲服務。我們延長動作助手摘要使:

  1. 我們不得不請求對象
  2. 直接訪問,我們可以輕鬆地從任何控制器

這將起到對之間一去調用服務應用程序和數據的實際存儲。

abstract class App_Rest_Service_Abstract extends Zend_Controller_Action_Helper_Abstract 
{ 
    /* 
    * @var App_Rest_Storage_Interface 
    */ 
    protected $_storage; 
    public function __call($methodName, $args) 
    { 
     if (!method_exists($this->getStorage(), $methodName)) { 
      throw new App_Rest_Service_Exception(sprintf('The storage does not have the method "%s"', $methodName)); 
     } 

     switch ($methodName) { 
      case 'get': 
      case 'put': 
      case 'delete': 
       //if id param isnot set, throw an exception 
       if (FALSE === ($id = $this->getRequest()->getParam('id', FALSE))) { 
        throw new App_Rest_Service_Exception(sprintf('Method "%s" expects an id param, none provided', $methodName)); 
       } 
       $iterator = $this->getStorage()->$methodName($id, $this->getRequest()->getParams()); 
       break; 
      case 'index': 
      case 'post': 
      default: 
       //if index, post or not a tradition RESTful request, the function must expect the first and only argument to be an array 
       $iterator = $this->getStorage()->$methodName($this->getRequest()->getParams()); 
       break; 
     } 


     return $this->_getResult($iterator); 
    } 

    protected function _getResult($iterator) 
{ /* 
     * write your own, in my case i make a paginator and then 
     * either return it or send data via the json helper 
     * 
     /* 
} 

現在爲接口。這將完成存儲,修改和返回數據的實際工作。使用它作爲界面的美妙之處在於無論您使用什麼模型圖層,都可以輕鬆實現它。我創建了一個簡單的Zend_Form(用於驗證)和一個Zend_Db_Table用於實際數據的抽象存儲。但你也可以在任何對象上實現它。

interface App_Rest_Storage_Interface extends Zend_Validate_Interface 
{ 
    public function index(array $params = NULL); 

    public function get($id, array $params = NULL); 

    public function post(array $params); 

    public function put($id, array $params); 

    public function delete($id, array $params); 

} 

現在可以在您的網站的任何地方進行操作。假設你有一個「客戶」服務。任何內部控制其作爲

$customer = $this->_helper->helper->customers->get(1); 

其他地方一樣簡單(比方說一個視圖助手):

Zend_Controller_Action_HelperBroker::getStaticHelper('customers')->get(1) 

我希望這有助於。它對我來說很好。

+0

是的,我同意你的解決方案。但有一點需要考慮: 1)爲什麼我們需要從助手發送JSON數據,而不是我們可以發送php對象,讓其他控制器決定它應該傳遞哪種格式。因此它在Web控制器中使用它時減少了編碼和解碼。 – Venu 2011-05-07 06:13:30

0

聲明:我從來沒有這樣做,我不知道它是多麼可行的。

由於Zend_Rest_Controller擴展了Zend_Controller_Action,現在使用了真正的休息特定邏輯,除了幾個抽象方法之外,您可以讓您的網站控制器擴展Rest控制器。例如:

class Web_IndexController extends Rest_IndexController 
{ 
    public function IndexAction() { 
     //do whatever your rest contrller would do 
     $result = parent::indexAction(); 
     //add website specific specific logic here 
    } 
} 

如果你的休息控制器的動作返回值,例如基於發生了什麼,然後你可以使用返回的數據做網絡站點特定的邏輯數據庫對象或數組。

有一件事要考慮,如果您使用json動作助手爲您的其餘api返回值,則應該在控制器屬性中構建以抑制發送和退出。例如:

class Rest_IndexController extends Zend_Rest_Controller 
{ 

    protected $_sendJson = TRUE; 
    public function IndexAction() { 
     $this->_helper->json($data, $this->_sendJson); 
    } 
} 

class Web_IndexController extends Rest_IndexController 
{ 
    protected $_sendJson = FALSE; 
} 

快樂黑客!

+0

嘿,謝謝你的回覆! 我在考慮爲api和web(連接到數據庫的db表的一些php類)設置公共業務邏輯層,但是您的想法似乎要好得多。我試圖按照您的建議,但無法擴展另一個模塊中的類。 – Venu 2011-04-29 13:54:46

+0

我正在使用自動加載,它沒有加載另一個模塊中的類。後來,我把需要擴展的課程包括在內。有效!! – Venu 2011-04-29 14:26:40

+0

這個設計仍然存在一些問題.. 1)說web_indexcontroller需要調用兩個不同的API類的方法? 2)如何自動加載其他模塊中的所有類? – Venu 2011-04-29 14:54:23