2009-09-30 6 views
7

私は、Zend Framework MVC実装を使用してプロジェクトを開始します。MVC:どのようにajax?

どのように私はajaxで作業しますか?つまり、すべてのAjaxコードをコントローラに配置する必要がありますか?またはビューに?

たとえば、著者の「ivan」からの投稿をページに表示したいとします。

通常、私は '/ posts/author/ivan'またはsmthのようなリンクを作成し、Postsコントローラ(またはUsersコントローラの場合はどこでも)のbyAuthorAction()のような新しいActionを作成し、 (そしてモデルからの投稿を取得するすべてのコードがそこに入ります)、新しいルートを作成します。

json、xml形式のajax、多分APIのユーザーの投稿を取得する機能を追加する方法、DRYの原則を守り、できるだけスマートなコード構造を設計する方法はありますか?

-

ありがとうございました! 私のような状況でのMVCの設計に関するコメントを見て非常にうれしく思います。私は基本的なMVCの原則でいくつかの経験を持っていますが、より複雑なケースではありません。多分便利なリンク?

答えて

13

あなたは本当にContextSwitchをアクションヘルパーについてのマニュアルの章をお読みください。しかし、ここでは簡単な概要です:

  • ビュースクリプト(アクションname.phtml)

    は持ち運びにくいができるように、コントローラにいくつかのアクションのためのコンテキストスイッチを初期化することができ、通常のHTML出力
  • のために使用されている例えば出力XML-xmlコンテキストはデフォルトでサポートされており、(action-name.xml.phtml)にxmlコンテキストのビュースクリプトを配置します。 xmlコンテキストもレイアウトのレンダリングを無効にします
  • jsonは組み込みのコンテキストスイッチでもサポートされています。デフォルトのオプションは、レイアウトとビューの両方を無効にし、JSON形式のコントローラアクションからビューに割り当てられたすべての変数を出力することですこのオプションは、コンテキストスイッチのsetAutoJsonSerialization(false)メソッドを使用して切り替えることができます。それを切り替えると、ビュースクリプトaction-name.jsonを作成する必要があります。phtmlを使用して変数を手作業でJSON形式で出力する

これらの2つのコンテキストを切り替えるには、URLにフォーマットパラメータを追加する必要があります。/posts/author/ivan/format/jsonまたは/ posts/author/ivan/format/xml。書式を指定しない場合、アプリケーションはプレーンhtmlを出力します。

コンテキストスイッチの特別なバージョンはAjaxContextであり、手動でこれを設定する必要もあります。 'format'パラメータを使用して出力に使用するフォーマットを特定するのではなく、リクエストで送信されたヘッダを調べて 'X-Requested-With:XmlHttpRequest'ヘッダを探し、存在する場合はAjaxContextを調べます。 AjaxContextアクションヘルパーを使用すると、リクエストがAJAXを使用して起動された場合に、特定のアクションに使用するコンテキストを指定できます。

8

ajaxリクエストを検出することによって、XML、JSONなどを返すために同じアクションを利用することができ、それによってajaxリクエストを通常のリクエストと区別することができます。たとえば:

public function fooAction() 
{ 
    if($this->getRequest->isXmlHttpRequest()) { 
     echo json_encode($someData); 
    } else { 
     echo 'This is the normal output'; 
    } 
} 
+0

xmlとjsonの選択方法は? htmlの/ posts/author/ivan、/posts/author/ivan.xml、/posts/author/ivan.json、/posts/author/ivan.rssなどの形式のURLをフォーマットする必要がありますか? –

+0

いいえ、URLは同じになります。 json_encode()を使用してJSON形式のコンテンツを出力できます。 http://ar2.php.net/json_encode –

+0

jsonは軽量でIMOでの作業が簡単です。 JSONビューを作成することも、ビューを使用せずにデータ配列をjson_encode()にエコーすることもできます。自動ビューレンダリングをオフにする必要があります。 – karim79

2

あなたのビューは、HTML以外のものとすることができ、いずれかのパイプラインは、Ajaxのポストであることの要求に対応することができ、またはあなたのコントローラが反応することができます。いずれにしても、別のViewを返すだけで簡単にできます。

1

AjaxContextアクションヘルパー(またはそれが拡張するContextSwitch)を見てください。これにより、まったく同じコントローラコードを使用して別のビュースクリプト(foo.json)に切り替えることができます。 phtml、またはfoo.ajax.phtmlなど)を使用するか、または?formatパラメータから自動的に選択します)、ビューに割り当てるすべての変数を含むオブジェクトを返すJSONアクションヘルパーを使用します。あなたのコントローラからエコーしている必要があります(これはユニットテストを混乱させます)。

+0

ああ、確かに。どのように私はそれを見ていないことができますか? –

0

私の構文が古いかもしれないが、この私のインデックスコントローラーからの私のRESTアクションのスケッチ:

/** 
* REST Action for this application. 
* 
* @return void 
*/ 
public function restAction() 
{ 
    $this->_helper->viewRenderer->setNoRender(true); 

    $parameters = (func_num_args() > 0) ? array($key => func_get_arg(0)) : $this->getRequest()->getParams(); 

    $key = 'restCommand'; 
    if(!array_key_exists($key, $parameters)) throw new Exception('Request for “' . $key . '” not found.'); 
    $restCommand = $parameters[$key]; 

    $xmlString = IndexModel::getEmptyXmlSet($restCommand); 
    $xslFile = IndexModel::getModelFilePath('index'); 

    //Handle OPML-driven REST commands: 
    if(stripos($restCommand, 'opml-') === 0) 
    { 
     $opmlCall = explode('-', $restCommand); 
     if(count($opmlCall) != 3) 
     { 
      $xmlString = Songhay_SimpleXml::getXmlMessage('OPML Call Not Recognized', array('The number of parameters are incorrect.')); 
     } 
     else 
     { 
      $opmlSet = $opmlCall[1]; 
      $opmlId = $opmlCall[2]; 
      $xmlString = IndexModel::getRssFragmentWithOpml($opmlSet, $opmlId); 
     } 
    } 

    //Handle general REST commands: 
    switch($restCommand) 
    { 
     case 'deeplink': 
      $key = 'id'; 
      if(!array_key_exists($key, $parameters)) throw new Exception('Request for “' . $key . '” not found.'); 
      $url = $parameters[$key]; 
      $xmlString = IndexModel::getRssFragment($url); 
      $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); 
      break; 
     case 'index': 
      $opmlFile = IndexModel::getModelFilePath('index', '.xml'); 
      $xmlString = Songhay_SimpleXml::loadXmlAndStripNamespaces($opmlFile); 
      $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); 
      break; 
     default: 
      $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); 
    } 

    $response = $this->getResponse(); 
    $response->setHeader('Content-Type', 'text/xml'); 
    $response->setBody($xmlString); 

    return; 
} 
0

私がcodeigniterでajaxを使用すると、コントローラからまっすぐ出力されます。

私は、フラグやお気に入りなどの単純なAjaxリクエストに対しても別のコントローラを使用します。ログイン、連絡先などのようなajaxリクエストでは、通常のパス(たとえばdomain.com/contact)にロジックを追加しますajaxリクエスト。次に、jsonを出力してスクリプトの実行を終了します。