3

zendフレームワークを使用してアプリケーションを構築しています。

問題は、REST以外のアプリ内でZend_Rest_Controllerと同じコントローラーロジックを使用する方法です。

たとえば、TwitterがZendFrameworkで作成されたとしましょう。彼らはおそらくAPIにZend_Rest_controllerとRouteを使用するでしょう。しかし、彼らは彼らのウェブサイト(明らかに同じAPIロジックを使用している)に何を使用しますか?彼らは、RESTリクエストを実行するだけのまったく新しいアプリケーションを作成するでしょうか?その過負荷ではありません。

[編集]
ウェブアプリがhttp_clientクラスを介してAPIを呼び出してデータを取得すると、サーバーに別のリクエストが送信されます(パフォーマンスが低下し、応答が遅くなります)。別のリクエストをしたくなく、APIにあるのと同じビジネスロジックを使用したいと思います。

ありがとう、
Venu

4

2 に答える 2

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. 任意のコントローラーから簡単にサービスを呼び出すことができます

これは、アプリケーションとデータの実際のストレージの間の役割を果たします。

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)

これが役立つことを願っています。それは私にとってうまくいっています。

于 2011-05-06T18:08:17.437 に答える
0

免責事項:私はこれをやったことがなく、それがどれほど実現可能かわかりません。

Zend_Rest_Controller は Zend_Controller_Action をいくつかの抽象メソッドを除いて実際の REST 固有のロジックで拡張するため、Web サイトのコントローラーで 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
    }
}

残りのコントローラーのアクションが、発生した内容に基づいて db オブジェクトや配列などの値を返す場合、返されたデータを使用して Web サイト固有のロジックを実行できます。

考慮すべきことの 1 つは、json アクション ヘルパーを使用して REST 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;
}

ハッピーハッキング!

于 2011-04-29T12:42:02.050 に答える