Новый ответ:
Я придумал шаблон, который, кажется, работает хорошо.Это решает все ваши проблемы: Вот уменьшенная версия того, что я придумал:
Сначала нам нужен наш собственный контроллер.У этого контроллера будет служба, в которой он передает любой запрос на действие в службу, если они не определены:
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 так, что:
- у нас есть прямой доступ к объекту запроса
- , мы можем легко вызвать сервис с любого контроллера
Это будет действовать как промежуточный путь для приложения и фактического хранения данных.
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)
Надеюсь, это поможет.Это работает хорошо для меня.