Zend Framework. Использование логики Webserive. - PullRequest
3 голосов
/ 29 апреля 2011

Я создаю приложение, используя Zend Framework.

Вопрос в том, как использовать ту же логику контроллера Zend_Rest_Controller в приложении без REST.

Например, давайте предположим, что твиттер был написан с использованием Zend Framework. Вероятно, они использовали бы Zend_Rest_controller и Route для своего API. Однако, что они будут использовать для своего сайта (который, очевидно, использует ту же логику API)? Будут ли они писать совершенно новое приложение, которое просто запускает запрос REST? Разве это не перегрузка?

[EDIT]
Если веб-приложение вызывает API через некоторый класс http_client для получения данных, это делает еще один запрос к серверу (это приводит к снижению производительности и замедлению ответа). Я не хочу делать еще один запрос и хочу использовать ту же бизнес-логику, что и в API.

Спасибо
Venu

Ответы [ 2 ]

2 голосов
/ 06 мая 2011

Новый ответ:

Я придумал шаблон, который, кажется, работает хорошо.Это решает все ваши проблемы: Вот уменьшенная версия того, что я придумал:

Сначала нам нужен наш собственный контроллер.У этого контроллера будет служба, в которой он передает любой запрос на действие в службу, если они не определены:

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. , мы можем легко вызвать сервис с любого контроллера

Это будет действовать как промежуточный путь для приложения и фактического хранения данных.

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 голосов
/ 29 апреля 2011

Отказ от ответственности: я никогда не делал этого, я не знаю, насколько это возможно.

Поскольку 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;
}

Счастливого взлома!

...