Zend框架Restful webserive逻辑用法

时间:2011-04-29 11:31:16

标签: php web-services zend-framework rest zend-rest-route

我正在使用zend框架构建应用程序。

问题是,如何在非REST应用程序中使用Zend_Rest_Controller的相同控制器逻辑。

例如,我们假设twitter是用Zend Framework编写的。他们可能会使用Zend_Rest_controller和Route作为他们的API。但是,他们会为他们的网站使用什么(显然使用相同的API逻辑)?他们会编写一个简单激活RE​​ST请求的全新应用程序吗?不是那么过载。

[编辑]
如果Web应用程序通过某个http_client类调用API来获取数据,则会向服务器发出另一个请求(这会导致性能下降并降低响应速度)。我不想提出另一个请求,并希望使用API​​中的相同业务逻辑。

谢谢,
VENU

2 个答案:

答案 0 :(得分: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);
    }
}

现在是服务的时候了。我们扩展了Action Helper Abstract,以便:

  1. 我们可以直接访问请求对象
  2. 我们可以轻松地从任何控制器调用服务
  3. 这将在应用程序和实际存储数据之间进行。

    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)
    

    我希望这会有所帮助。它对我很有用。

答案 1 :(得分: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;
}

快乐黑客!